mirror of https://github.com/dotnet/runtime
Method header parsing
svn path=/trunk/mono/; revision=41
Commit migrated from eb6fb07489
This commit is contained in:
parent
be71b0fcf3
commit
fe93a14505
|
@ -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");
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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]);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue