Method header parsing

svn path=/trunk/mono/; revision=41


Commit migrated from eb6fb07489
This commit is contained in:
Miguel de Icaza 2001-06-28 05:04:00 +00:00
parent be71b0fcf3
commit fe93a14505
5 changed files with 218 additions and 11 deletions

View File

@ -88,3 +88,22 @@ dump_table_param (metadata_t *m)
fprintf (output, "\n");
}
void
dump_table_field (metadata_t *m)
{
metadata_tableinfo_t *t = &m->tables [META_TABLE_FIELD];
int i;
fprintf (output, "Field Table (0..%d)\n", t->rows);
for (i = 0; i < t->rows; i++){
guint32 cols [3];
expand (t, i, cols, CSIZE (cols));
fprintf (output, "%d: 0x%02x %s\n",
i,
cols [0],
mono_metadata_string_heap (m, cols [1]));
}
fprintf (output, "\n");
}

View File

@ -4,3 +4,4 @@ void dump_table_typeref (metadata_t *m);
void dump_table_typedef (metadata_t *m);
void dump_table_assemblyref (metadata_t *m);
void dump_table_param (metadata_t *m);
void dump_table_field (metadata_t *m);

View File

@ -163,10 +163,8 @@ dis_field_list (metadata_t *m, guint32 start, guint32 end)
guint32 cols [3];
int i;
if (end > t->rows + 1){
fprintf (output, "ERROR index out of range in fields");
exit (1);
}
if (end > t->rows + 1)
g_error ("ERROR index out of range in fields");
for (i = start; i < end; i++){
char *sig, *flags;
@ -283,12 +281,21 @@ method_impl_flags (guint32 f)
static void
dis_code (metadata_t *m, cli_image_info_t *ii, guint32 rva)
{
MonoMetaMethodHeader *mh;
const char *ptr = cli_rva_map (ii, rva);
if (rva == 0)
return;
hex_dump (ptr, 0, 64);
mh = mono_metadata_parse_mh (ptr);
fprintf (output, "\t.maxstack %d\n", mh->max_stack);
fprintf (output, "\t// Code size=%d (0x%x)\n", mh->code_size, mh->code_size);
printf ("Values Code Size=%d/0x%x\nMaxStack=%d\nLocalTok=%x",
mh->code_size, mh->code_size, mh->max_stack, mh->local_var_sig_tok);
hex_dump (mh->code, 0, mh->code_size);
printf ("\nAfter the code\n");
hex_dump (mh->code + mh->code_size, 0, 64);
mono_metadata_free_mh (mh);
}
typedef struct {
@ -434,9 +441,15 @@ dis_type (metadata_t *m, cli_image_info_t *ii, int n)
guint32 cols [6];
guint32 cols_next [6];
const char *name;
gboolean next_is_valid, last;
expand (t, n, cols, CSIZE (cols));
expand (t, n + 1, cols_next, CSIZE (cols_next));
if (t->rows < n+1){
expand (t, n + 1, cols_next, CSIZE (cols_next));
next_is_valid = 1;
} else
next_is_valid = 0;
fprintf (output, ".namespace %s\n{\n", mono_metadata_string_heap (m, cols [2]));
name = mono_metadata_string_heap (m, cols [1]);
@ -455,11 +468,22 @@ dis_type (metadata_t *m, cli_image_info_t *ii, int n)
* The value in the table is always valid, we know we have fields
* if the value stored is different than the next record.
*/
if (next_is_valid)
last = cols_next [4] - 1;
else
last = m->tables [META_TABLE_FIELD].rows;
if (cols [4] != cols_next [4])
dis_field_list (m, cols [4] - 1, cols_next [4] - 1);
dis_field_list (m, cols [4] - 1, last);
fprintf (output, "\n");
if (next_is_valid)
last = cols [5] - 1;
else
last = m->tables [META_TABLE_METHOD].rows;
if (cols [4] != cols_next [5])
dis_method_list (m, ii, cols [5] - 1, cols_next [5] - 1);
dis_method_list (m, ii, cols [5] - 1, last);
fprintf (output, " }\n}\n\n");
}
@ -518,6 +542,9 @@ disassemble_file (const char *file)
case META_TABLE_PARAM:
dump_table_param (m);
break;
case META_TABLE_FIELD:
dump_table_field (m);
break;
default:
g_error ("Internal error");
}
@ -562,6 +589,8 @@ main (int argc, char *argv [])
dump_table = META_TABLE_ASSEMBLYREF;
else if (strcmp (argv [i], "--param") == 0)
dump_table = META_TABLE_PARAM;
else if (strcmp (argv [i], "--fields") == 0)
dump_table = META_TABLE_FIELD;
} else
input_files = g_list_append (input_files, argv [i]);
}

View File

@ -10,6 +10,8 @@
#include <config.h>
#include <glib.h>
#include "metadata.h"
#include "methodheader.h"
#include "endian.h"
/*
* Encoding of the "description" argument:
@ -327,6 +329,12 @@ static struct {
/* 2B */ { NULL, NULL },
};
/**
* mono_meta_table_name:
* @table: table index
*
* Returns the name for the @table index
*/
const char *
mono_meta_table_name (int table)
{
@ -557,6 +565,13 @@ compute_size (metadata_t *meta, MonoMetaTable *table, int rowcount, guint32 *res
return size;
}
/**
* mono_metadata_compute_table_bases:
* @meta: metadata context to compute table values
*
* Computes the table bases for the metadata structure.
* This is an internal function used by the image loader code.
*/
void
mono_metadata_compute_table_bases (metadata_t *meta)
{
@ -574,7 +589,16 @@ mono_metadata_compute_table_bases (metadata_t *meta)
base += meta->tables [i].rows * meta->tables [i].row_size;
}
}
/**
* mono_metadata_locate:
* @meta: metadata context
* @table: table code.
* @idx: index of element to retrieve from @table.
*
* Returns a pointer to the @idx element in the metadata table
* whose code is @table.
*/
char *
mono_metadata_locate (metadata_t *meta, int table, int idx)
{
@ -589,6 +613,12 @@ mono_metadata_locate_token (metadata_t *meta, guint32 token)
return mono_metadata_locate (meta, token >> 24, token & 0xffffff);
}
/**
* mono_metadata_get_table:
* @table: table to retrieve
*
* Returns the MonoMetaTable structure for table @table
*/
MonoMetaTable *
mono_metadata_get_table (MetaTableEnum table)
{
@ -599,16 +629,130 @@ mono_metadata_get_table (MetaTableEnum table)
return tables [table].table;
}
/**
* mono_metadata_string_heap:
* @meta: metadata context
* @index: index into the string heap.
*
* Returns: an in-memory pointer to the @index in the string heap.
*/
const char *
mono_metadata_string_heap (metadata_t *meta, guint32 index)
{
return meta->raw_metadata + meta->heap_strings.sh_offset + index;
}
/**
* mono_metadata_blob_heap:
* @meta: metadata context
* @index: index into the blob.
*
* Returns: an in-memory pointer to the @index in the Blob heap.
*/
const char *
mono_metadata_blob_heap (metadata_t *meta, guint32 index)
{
return meta->raw_metadata + meta->heap_blob.sh_offset + index;
}
static const char *
dword_align (const char *ptr)
{
return (const char *) (((guint32) (ptr + 3)) & ~3);
}
MonoMetaMethodHeader *
mono_metadata_parse_mh (const char *ptr)
{
MonoMetaMethodHeader *mh;
unsigned char flags = *(unsigned char *) ptr;
unsigned char format = flags & METHOD_HEADER_FORMAT_MASK;
guint16 fat_flags;
unsigned char sect_data_flags;
int hsize, sect_data_len;
g_return_val_if_fail (ptr != NULL, NULL);
g_return_val_if_fail (mh != NULL, NULL);
mh = g_new0 (MonoMetaMethodHeader, 1);
switch (format){
case METHOD_HEADER_TINY_FORMAT:
ptr++;
mh->max_stack = 8;
mh->local_var_sig_tok = 0;
mh->code_size = flags >> 2;
mh->code = ptr;
break;
case METHOD_HEADER_TINY_FORMAT1:
ptr++;
mh->max_stack = 8;
mh->local_var_sig_tok = 0;
mh->code_size = flags >> 3;
mh->code = ptr;
break;
case METHOD_HEADER_FAT_FORMAT:
fat_flags = read16 (ptr);
ptr += 2;
hsize = (fat_flags >> 12) & 0xf;
mh->max_stack = *(guint16 *) ptr;
ptr += 2;
mh->code_size = *(guint32 *) ptr;
ptr += 4;
mh->local_var_sig_tok = *(guint32 *) ptr;
ptr += 4;
if (fat_flags & METHOD_HEADER_INIT_LOCALS)
mh->init_locals = 1;
else
mh->init_locals = 0;
mh->code = ptr;
if (!(fat_flags & METHOD_HEADER_MORE_SECTS))
return mh;
/*
* There are more sections
*/
ptr = mh->code + mh->code_size;
/* align on 32-bit boundary */
/* FIXME: not 64-bit clean code */
ptr = dword_align (ptr);
sect_data_flags = *ptr;
ptr++;
if (sect_data_flags & METHOD_HEADER_SECTION_MORE_SECTS){
g_error ("Can not deal with more sections");
}
if (sect_data_flags & METHOD_HEADER_SECTION_FAT_FORMAT){
sect_data_len = (ptr [0] << 16) | (ptr [1] << 8) | ptr [2];
ptr += 3;
} else {
sect_data_len = ptr [0];
ptr++;
}
if (!(sect_data_flags & METHOD_HEADER_SECTION_EHTABLE))
return mh;
ptr = dword_align (ptr);
break;
default:
return NULL;
}
return mh;
}
void
mono_metadata_free_mh (MonoMetaMethodHeader *mh)
{
g_free (mh);
}

View File

@ -172,3 +172,17 @@ char *mono_metadata_locate_token (metadata_t *meta, guint32 token);
const char *mono_metadata_string_heap (metadata_t *meta, guint32 index);
const char *mono_metadata_blob_heap (metadata_t *meta, guint32 index);
typedef struct {
guint32 code_size;
const char *code;
short max_stack;
guint32 local_var_sig_tok;
/* if local_var_sig_tok != 0, then the following apply: */
unsigned int init_locals : 1;
} MonoMetaMethodHeader;
MonoMetaMethodHeader *mono_metadata_parse_mh (const char *ptr);
void mono_metadata_free_mh (MonoMetaMethodHeader *mh);