#include <config.h>
#include <stdlib.h>
#include <string.h>
+#include <signal.h>
#include <mono/metadata/metadata.h>
#include <mono/metadata/rawbuffer.h>
+#include <mono/metadata/tokentype.h>
#include <mono/metadata/appdomain.h>
#include <mono/metadata/exception.h>
#include <mono/metadata/debug-symfile.h>
#define MRT_method_end_address 0x04
#define MRT_local_variable 0x05
#define MRT_method_parameter 0x06
+#define MRT_type_sizeof 0x07
+#define MRT_type_field_offset 0x08
+#define MRT_mono_string_sizeof 0x09
+#define MRT_mono_string_offset 0x0a
+#define MRT_mono_array_sizeof 0x0b
+#define MRT_mono_array_offset 0x0c
+#define MRT_mono_array_bounds_sizeof 0x0d
+#define MRT_mono_array_bounds_offset 0x0e
+#define MRT_variable_start_scope 0x0f
+#define MRT_variable_end_scope 0x10
+#define MRT_mono_string_fieldsize 0x11
+#define MRT_mono_array_fieldsize 0x12
+#define MRT_type_field_fieldsize 0x13
+#define MRT_mono_string_string_length 0x14
+#define MRT_mono_string_byte_size 0x15
+#define MRT_mono_string_data_location 0x16
+#define MRT_static_type_field_offset 0x17
+#define MRT_mono_array_data_location 0x18
+#define MRT_mono_array_max_length 0x19
+#define MRT_mono_array_length_byte_size 0x1a
+
+#define MRI_string_offset_length 0x00
+#define MRI_string_offset_chars 0x01
+
+#define MRI_array_offset_bounds 0x00
+#define MRI_array_offset_max_length 0x01
+#define MRI_array_offset_vector 0x02
+
+#define MRI_array_bounds_offset_lower 0x00
+#define MRI_array_bounds_offset_length 0x01
#define MRS_debug_info 0x01
#define MRS_debug_abbrev 0x02
#define MRS_debug_line 0x03
#define MRS_mono_reloc_table 0x04
+#define DW_OP_const4u 0x0c
+#define DW_OP_const4s 0x0d
+#define DW_OP_plus 0x22
+#define DW_OP_reg0 0x50
+#define DW_OP_breg0 0x70
+#define DW_OP_fbreg 0x91
+#define DW_OP_piece 0x93
+#define DW_OP_nop 0x96
+
#ifdef HAVE_ELF_H
static gboolean
const char *strtab;
int i;
- header = symfile->raw_contents;
+ header = (Elf32_Ehdr *)symfile->raw_contents;
if (header->e_version != EV_CURRENT) {
if (emit_warnings)
g_warning ("Symbol file %s has unknown ELF version %d",
symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
- section = symfile->raw_contents + header->e_shoff;
+ section = (Elf32_Shdr *)(symfile->raw_contents + header->e_shoff);
strtab_section = section + header->e_shstrndx;
strtab = symfile->raw_contents + strtab_section->sh_offset;
sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
sfs->file_offset = section->sh_offset;
sfs->size = section->sh_size;
+ } else if (!strcmp (name, ".mono_line_numbers")) {
+ MonoDebugSymbolFileSection *sfs;
+
+ sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS];
+ sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS;
+ sfs->file_offset = section->sh_offset;
+ sfs->size = section->sh_size;
+ } else if (!strcmp (name, ".mono_symbol_table")) {
+ MonoDebugSymbolFileSection *sfs;
+
+ sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_SYMBOL_TABLE];
+ sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_SYMBOL_TABLE;
+ sfs->file_offset = section->sh_offset;
+ sfs->size = section->sh_size;
}
}
get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
{
#ifdef HAVE_ELF_H
+#ifdef __FreeBSD__
+ static const char ELFMAG[] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 0 };
+#endif
if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
return get_sections_elf32 (symfile, emit_warnings);
#endif
return FALSE;
}
+static void
+read_line_numbers (MonoDebugSymbolFile *symfile)
+{
+ const char *ptr, *start, *end;
+ int version;
+ long section_size;
+
+ if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS].file_offset)
+ return;
+
+ ptr = start = symfile->raw_contents +
+ symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS].file_offset;
+
+ version = *((guint16 *) ptr)++;
+ if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
+ g_warning ("Symbol file %s has incorrect line number table version "
+ "(expected %d, got %d)", symfile->file_name,
+ MONO_DEBUG_SYMBOL_FILE_VERSION, version);
+ return;
+ }
+
+ section_size = *((guint32 *) ptr)++;
+ end = ptr + section_size;
+
+ symfile->line_number_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, (GDestroyNotify) g_free);
+
+ while (ptr < end) {
+ MonoDebugLineNumberBlock *lnb;
+ guint32 token, source_offset;
+ MonoMethod *method;
+
+ token = * ((guint32 *) ptr)++;
+ method = mono_get_method (symfile->image, token, NULL);
+ if (!method)
+ continue;
+
+ lnb = g_new0 (MonoDebugLineNumberBlock, 1);
+ lnb->token = token;
+ source_offset = * ((guint32 *) ptr)++;
+ lnb->source_file = (const char *) start + source_offset;
+ lnb->start_line = * ((guint32 *) ptr)++;
+ lnb->file_offset = * ((guint32 *) ptr)++;
+
+ g_hash_table_insert (symfile->line_number_table, method, lnb);
+ }
+}
+
+static MonoClass *
+find_class_by_name (MonoDebugSymbolFile *symfile, const char *nspace, const char *name)
+{
+ MonoAssembly **assembly;
+ MonoClass *klass;
+
+ klass = mono_class_from_name (symfile->image, nspace, name);
+
+ if (klass)
+ return klass;
+
+ for (assembly = symfile->image->references; assembly && *assembly; assembly++) {
+ klass = mono_class_from_name ((*assembly)->image, nspace, name);
+
+ if (klass)
+ return klass;
+ }
+
+ g_message (G_STRLOC ": Can't find class %s.%s", nspace, name);
+
+ return NULL;
+}
+
+static void
+read_symbol_table (MonoDebugSymbolFile *symfile)
+{
+ const char *ptr, *start, *end;
+ int version, i;
+ long section_size;
+
+ if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_SYMBOL_TABLE].file_offset)
+ return;
+
+ ptr = start = symfile->raw_contents +
+ symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_SYMBOL_TABLE].file_offset;
+
+ version = *((guint16 *) ptr)++;
+ if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
+ g_warning ("Symbol file %s has incorrect line number table version "
+ "(expected %d, got %d)", symfile->file_name,
+ MONO_DEBUG_SYMBOL_FILE_VERSION, version);
+ return;
+ }
+
+ section_size = *((guint32 *) ptr)++;
+ end = ptr + section_size;
+
+ g_free (symfile->type_table);
+
+ symfile->num_types = * ((guint32 *) ptr)++;
+ symfile->type_table = g_new0 (MonoClass *, symfile->num_types);
+
+ for (i = 0; i < symfile->num_types; i++) {
+ const char *name, *namespace;
+ MonoClass *klass;
+
+ namespace = ptr;
+ ptr += strlen (namespace) + 1;
+
+ name = ptr;
+ ptr += strlen (name) + 1;
+
+ klass = find_class_by_name (symfile, namespace, name);
+
+ if (klass)
+ symfile->type_table [i] = klass;
+ }
+}
+
+static MonoClass *
+mono_debug_class_get (MonoDebugSymbolFile *symfile, guint32 type_token)
+{
+ MonoClass *klass;
+
+ if (!type_token)
+ return mono_defaults.object_class;
+
+ if (type_token <= symfile->num_types)
+ return symfile->type_table [type_token - 1];
+
+ if ((klass = g_hash_table_lookup (symfile->image->class_cache, GUINT_TO_POINTER (type_token))))
+ return klass;
+
+ return NULL;
+}
+
MonoDebugSymbolFile *
mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
{
return NULL;
}
+ read_symbol_table (symfile);
+
+ read_line_numbers (symfile);
+
return symfile;
}
if (symfile->fd)
close (symfile->fd);
+ if (symfile->line_number_table)
+ g_hash_table_destroy (symfile->line_number_table);
g_free (symfile->file_name);
g_free (symfile->section_offsets);
g_free (symfile);
}
+static void
+relocate_variable (MonoDebugVarInfo *var, void *base_ptr)
+{
+ if (!var) {
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ return;
+ }
+
+ /*
+ * Update the location description for a local variable or method parameter.
+ * MCS always reserves 8 bytes for us to do this, if we don't need them all
+ * we just fill up the rest with DW_OP_nop's.
+ */
+
+ switch (var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS) {
+ case MONO_DEBUG_VAR_ADDRESS_MODE_STACK:
+ /*
+ * Variable is on the stack.
+ *
+ * If `index' is zero, use the normal frame register. Otherwise, bits
+ * 0..4 of `index' contain the frame register.
+ *
+ * Both DW_OP_fbreg and DW_OP_breg0 ... DW_OP_breg31 take an ULeb128
+ * argument - since this has an variable size, we set it to zero and
+ * manually add a 4 byte constant using DW_OP_plus.
+ */
+ if (!var->index)
+ /* Use the normal frame register (%ebp on the i386). */
+ * ((guint8 *) base_ptr)++ = DW_OP_fbreg;
+ else
+ /* Use a custom frame register. */
+ * ((guint8 *) base_ptr)++ = DW_OP_breg0 + (var->index & 0x001f);
+ * ((guint8 *) base_ptr)++ = 0;
+ * ((guint8 *) base_ptr)++ = DW_OP_const4s;
+ * ((gint32 *) base_ptr)++ = var->offset;
+ * ((guint8 *) base_ptr)++ = DW_OP_plus;
+ break;
+
+ case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
+ /*
+ * Variable is in the register whose number is contained in bits 0..4
+ * of `index'.
+ *
+ * We need to write exactly 8 bytes in this location description, so instead
+ * of filling up the rest with DW_OP_nop's just add the `offset' even if
+ * it's zero.
+ */
+ * ((guint8 *) base_ptr)++ = DW_OP_reg0 + (var->index & 0x001f);
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_const4s;
+ * ((gint32 *) base_ptr)++ = var->offset;
+ * ((guint8 *) base_ptr)++ = DW_OP_plus;
+ break;
+
+ case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS:
+ /*
+ * Variable is in two registers whose numbers are in bits 0..4 and 5..9 of
+ * the `index' field. Don't add `offset' since we have only two bytes left,
+ * fill them up with DW_OP_nop's.
+ */
+ * ((guint8 *) base_ptr)++ = DW_OP_reg0 + (var->index & 0x001f);
+ * ((guint8 *) base_ptr)++ = DW_OP_piece;
+ * ((guint8 *) base_ptr)++ = sizeof (int);
+ * ((guint8 *) base_ptr)++ = DW_OP_reg0 + ((var->index & 0x1f0) >> 5);
+ * ((guint8 *) base_ptr)++ = DW_OP_piece;
+ * ((guint8 *) base_ptr)++ = sizeof (int);
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+}
+
void
mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
MonoDebugMethodInfoFunc method_info_func,
int version, already_relocated = 0;
long reloc_size;
+ read_symbol_table (symfile);
+
if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
return;
while (reloc_ptr < reloc_end) {
int type, size, section, offset;
const char *tmp_ptr;
- void *base_ptr;
+ char *base_ptr;
type = *reloc_ptr++;
size = * ((guint32 *) reloc_ptr)++;
}
base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
- base_ptr += offset;
+ base_ptr = base_ptr + offset;
switch (type) {
case MRT_target_address_size:
continue;
}
- g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
+#if 0
+ g_message ("Start of `%s' (%ld) relocated to %p", minfo->method->name,
+ token, minfo->code_start);
+#endif
* (void **) base_ptr = minfo->code_start;
continue;
}
- * (void **) base_ptr = minfo->code_start + minfo->code_size;
+ * (void **) base_ptr = (char *)minfo->code_start + minfo->code_size;
break;
}
}
}
- g_message ("Relocating IL offset %d in `%s' to %d (%p)",
+#if 0
+ g_message ("Relocating IL offset %04x in `%s' to %d (%p)",
original, minfo->method->name, address,
minfo->code_start + address);
+#endif
* (void **) base_ptr = minfo->code_start + address;
guint32 token = *((guint32 *) tmp_ptr)++;
guint32 original = *((guint32 *) tmp_ptr)++;
MonoDebugMethodInfo *minfo;
- gint32 address;
minfo = method_info_func (symfile, token, user_data);
if (!minfo) {
- * (void **) base_ptr = 0;
+ relocate_variable (NULL, base_ptr);
continue;
}
"local variable %d, but method %s only has %d local variables.",
symfile->file_name, original, minfo->method->name,
minfo->num_locals);
+ g_message (G_STRLOC ": %d", token);
+ G_BREAKPOINT ();
continue;
}
- address = minfo->local_offsets [original];
-
- g_message ("Relocating local variable %d (%s) to stack offset %d",
- original, minfo->method->name, address);
-
- * (gint32 *) base_ptr = address;
+ relocate_variable (&minfo->locals [original], base_ptr);
break;
}
guint32 token = *((guint32 *) tmp_ptr)++;
guint32 original = *((guint32 *) tmp_ptr)++;
MonoDebugMethodInfo *minfo;
- gint32 address;
minfo = method_info_func (symfile, token, user_data);
if (!minfo) {
- * (void **) base_ptr = 0;
+ relocate_variable (NULL, base_ptr);
continue;
}
+ if (minfo->method->signature->hasthis) {
+ if (original == 0) {
+ relocate_variable (minfo->this_var, base_ptr);
+ continue;
+ }
+
+ original--;
+ }
+
if (original > minfo->num_params) {
g_warning ("Symbol file %s contains relocation entry for non-existing "
"parameter %d, but method %s only has %d parameters.",
continue;
}
- address = minfo->param_offsets [original];
+ relocate_variable (&minfo->params [original], base_ptr);
+
+ break;
+ }
+ case MRT_type_sizeof: {
+ guint32 token = *((guint32 *) tmp_ptr)++;
+ MonoClass *klass = mono_debug_class_get (symfile, token);
+
+ if (!klass)
+ continue;
+
+ mono_class_init (klass);
+
+ if (klass->enumtype || klass->valuetype)
+ * (gint8 *) base_ptr = klass->instance_size - sizeof (MonoObject);
+ else
+ * (gint8 *) base_ptr = klass->instance_size;
+
+ break;
+ }
+ case MRT_type_field_offset: {
+ guint32 token = *((guint32 *) tmp_ptr)++;
+ guint32 original = *((guint32 *) tmp_ptr)++;
+ MonoClass *klass = mono_debug_class_get (symfile, token);
+ guint32 off;
+
+ if (!klass)
+ continue;
+
+ mono_class_init (klass);
+
+ if (original > klass->field.count) {
+ g_warning ("Symbol file %s contains invalid field offset entry.",
+ symfile->file_name);
+ g_message (G_STRLOC ": %d", token);
+ /* G_BREAKPOINT (); */
+ continue;
+ }
+
+ if (!klass->fields)
+ continue;
+
+ off = klass->fields [original].offset;
+ if (klass->byval_arg.type == MONO_TYPE_VALUETYPE)
+ off -= sizeof (MonoObject);
- g_message ("Relocating parameter %d (%s) to stack offset %d",
- original, minfo->method->name, address);
+#if 0
+ g_message ("Setting field %d of type %u to offset %d", original,
+ token, off);
+#endif
- * (gint32 *) base_ptr = address;
+ * (guint32 *) base_ptr = off;
break;
}
+ case MRT_mono_string_sizeof:
+ * (gint8 *) base_ptr = sizeof (MonoString);
+ break;
+
+ case MRT_mono_string_offset: {
+ guint32 idx = *((guint32 *) tmp_ptr)++;
+ MonoString string;
+ guint32 off;
+
+ switch (idx) {
+ case MRI_string_offset_length:
+ off = (guchar *) &string.length - (guchar *) &string;
+ break;
+
+ case MRI_string_offset_chars:
+ off = (guchar *) &string.chars - (guchar *) &string;
+ break;
+
+ default:
+ g_warning ("Symbol file %s contains invalid string offset entry",
+ symfile->file_name);
+ continue;
+ }
+
+ * (guint32 *) base_ptr = off;
+
+ break;
+ }
+ case MRT_mono_array_sizeof:
+ * (gint8 *) base_ptr = sizeof (MonoArray);
+ break;
+
+ case MRT_mono_array_offset: {
+ guint32 idx = *((guint32 *) tmp_ptr)++;
+ MonoArray array;
+ guint32 off;
+
+ switch (idx) {
+ case MRI_array_offset_bounds:
+ off = (guchar *) &array.bounds - (guchar *) &array;
+ break;
+
+ case MRI_array_offset_max_length:
+ off = (guchar *) &array.max_length - (guchar *) &array;
+ break;
+
+ case MRI_array_offset_vector:
+ off = (guchar *) &array.vector - (guchar *) &array;
+ break;
+
+ default:
+ g_warning ("Symbol file %s contains invalid array offset entry",
+ symfile->file_name);
+ continue;
+ }
+
+ * (guint32 *) base_ptr = off;
+
+ break;
+ }
+
+ case MRT_mono_array_bounds_sizeof:
+ * (gint8 *) base_ptr = sizeof (MonoArrayBounds);
+ break;
+
+ case MRT_mono_array_bounds_offset: {
+ guint32 idx = *((guint32 *) tmp_ptr)++;
+ MonoArrayBounds bounds;
+ guint32 off;
+
+ switch (idx) {
+ case MRI_array_bounds_offset_lower:
+ off = (guchar *) &bounds.lower_bound - (guchar *) &bounds;
+ break;
+
+ case MRI_array_bounds_offset_length:
+ off = (guchar *) &bounds.length - (guchar *) &bounds;
+ break;
+
+ default:
+ g_warning ("Symbol file %s contains invalid array bounds offset entry",
+ symfile->file_name);
+ continue;
+ }
+
+ * (guint32 *) base_ptr = off;
+
+ break;
+ }
+
+ case MRT_variable_start_scope: {
+ guint32 token = *((guint32 *) tmp_ptr)++;
+ guint32 original = *((guint32 *) tmp_ptr)++;
+ MonoDebugMethodInfo *minfo;
+ gint32 address;
+
+ minfo = method_info_func (symfile, token, user_data);
+
+ if (!minfo || !minfo->locals) {
+ * (void **) base_ptr = 0;
+ continue;
+ }
+
+ if (original > minfo->num_locals) {
+ g_warning ("Symbol file %s contains relocation entry for non-existing "
+ "local variable %d, but method %s only has %d local variables.",
+ symfile->file_name, original, minfo->method->name,
+ minfo->num_locals);
+ continue;
+ }
+
+ address = minfo->locals [original].begin_scope;
+
+ * (void **) base_ptr = minfo->code_start + address;
+
+ break;
+ }
+
+ case MRT_variable_end_scope: {
+ guint32 token = *((guint32 *) tmp_ptr)++;
+ guint32 original = *((guint32 *) tmp_ptr)++;
+ MonoDebugMethodInfo *minfo;
+ gint32 address;
+
+ minfo = method_info_func (symfile, token, user_data);
+
+ if (!minfo || !minfo->locals) {
+ * (void **) base_ptr = 0;
+ continue;
+ }
+
+ if (original > minfo->num_locals) {
+ g_warning ("Symbol file %s contains relocation entry for non-existing "
+ "local variable %d, but method %s only has %d local variables.",
+ symfile->file_name, original, minfo->method->name,
+ minfo->num_locals);
+ continue;
+ }
+
+ address = minfo->locals [original].end_scope;
+
+ * (void **) base_ptr = minfo->code_start + address;
+
+ break;
+ }
+
+ case MRT_mono_string_fieldsize: {
+ guint32 idx = *((guint32 *) tmp_ptr)++;
+ MonoString string;
+ guint32 fieldsize;
+
+ switch (idx) {
+ case MRI_string_offset_length:
+ fieldsize = sizeof (string.length);
+ break;
+
+ default:
+ g_warning ("Symbol file %s contains invalid string fieldsize entry",
+ symfile->file_name);
+ continue;
+ }
+
+ * (guint32 *) base_ptr = fieldsize;
+
+ break;
+ }
+
+ case MRT_mono_array_fieldsize: {
+ guint32 idx = *((guint32 *) tmp_ptr)++;
+ MonoArray array;
+ guint32 fieldsize;
+
+ switch (idx) {
+ case MRI_array_offset_bounds:
+ fieldsize = sizeof (array.bounds);
+ break;
+
+ case MRI_array_offset_max_length:
+ fieldsize = sizeof (array.max_length);
+ break;
+
+ case MRI_array_offset_vector:
+ fieldsize = sizeof (array.vector);
+ break;
+
+ default:
+ g_warning ("Symbol file %s contains invalid array fieldsize entry",
+ symfile->file_name);
+ continue;
+ }
+
+ * (guint32 *) base_ptr = fieldsize;
+
+ break;
+ }
+
+ case MRT_mono_string_string_length: {
+ MonoString string;
+ guint32 offset = (guchar *) &string.length - (guchar *) &string;
+
+ * ((guint8 *) base_ptr)++ = DW_OP_const4u;
+ * ((gint32 *) base_ptr)++ = offset;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+
+ break;
+ }
+
+ case MRT_mono_string_byte_size: {
+ MonoString string;
+
+ * (guint32 *) base_ptr = sizeof (string.length);
+
+ break;
+ }
+
+ case MRT_mono_string_data_location: {
+ MonoString string;
+ guint32 offset = (guchar *) &string.chars - (guchar *) &string;
+
+ * ((guint8 *) base_ptr)++ = DW_OP_const4u;
+ * ((gint32 *) base_ptr)++ = offset;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+
+ break;
+ }
+
+ case MRT_static_type_field_offset: {
+ guint32 token = *((guint32 *) tmp_ptr)++;
+ guint32 original = *((guint32 *) tmp_ptr)++;
+ MonoClass *klass = mono_debug_class_get (symfile, token);
+ MonoVTable *vtable;
+ guint32 off;
+
+ if (!klass)
+ continue;
+
+ mono_class_init (klass);
+
+ if (original > klass->field.count) {
+ g_warning ("Symbol file %s contains invalid field offset entry.",
+ symfile->file_name);
+ continue;
+ }
+
+ if (!klass->fields)
+ continue;
+
+ vtable = mono_class_vtable (mono_domain_get (), klass);
+
+ off = klass->fields [original].offset;
+
+#if 0
+ g_message ("Setting field %d of type %u (%p) to offset %d", original,
+ token, klass, off);
+#endif
+
+ * (void **) base_ptr = (char *) vtable->data + off;
+
+ break;
+ }
+
+ case MRT_mono_array_data_location: {
+ MonoArray array;
+ guint32 offset = (guchar *) &array.vector - (guchar *) &array;
+
+ * ((guint8 *) base_ptr)++ = DW_OP_const4u;
+ * ((gint32 *) base_ptr)++ = offset;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+
+ break;
+ }
+
+ case MRT_mono_array_max_length: {
+ MonoArray array;
+ guint32 offset = (guchar *) &array.max_length - (guchar *) &array;
+
+ * ((guint8 *) base_ptr)++ = DW_OP_const4u;
+ * ((gint32 *) base_ptr)++ = offset;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+ * ((guint8 *) base_ptr)++ = DW_OP_nop;
+
+ break;
+ }
+
+ case MRT_mono_array_length_byte_size: {
+ MonoArray array;
+
+ * (guint32 *) base_ptr = sizeof (array.max_length);
+
+ break;
+ }
+
default:
g_warning ("Symbol file %s contains unknown relocation entry %d",
symfile->file_name, type);
mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
}
-MonoReflectionType *
-mono_debug_local_type_from_signature (MonoReflectionAssembly *assembly, MonoArray *signature)
+gchar *
+mono_debug_find_source_location (MonoDebugSymbolFile *symfile, MonoMethod *method, guint32 offset,
+ guint32 *line_number)
{
- MonoDomain *domain;
- MonoImage *image;
- MonoClass *klass;
- MonoType *type;
+ MonoDebugLineNumberBlock *lnb;
const char *ptr;
- int len = 0;
-
- MONO_CHECK_ARG_NULL (assembly);
- MONO_CHECK_ARG_NULL (signature);
- domain = mono_domain_get();
- image = assembly->assembly->image;
-
- ptr = mono_array_addr (signature, char, 0);
- g_assert (*ptr++ == 0x07);
- len = mono_metadata_decode_value (ptr, &ptr);
- g_assert (len == 1);
-
- type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
+ if (!symfile->line_number_table)
+ return NULL;
- klass = mono_class_from_mono_type (type);
+ lnb = g_hash_table_lookup (symfile->line_number_table, method);
+ if (!lnb)
+ return NULL;
- mono_class_init (klass);
+ ptr = symfile->raw_contents +
+ symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS].file_offset;
- return mono_type_get_object (domain, type);
-}
+ ptr += lnb->file_offset;
-MonoReflectionMethod *
-mono_debug_method_from_token (MonoReflectionAssembly *assembly, guint32 token)
-{
- MonoDomain *domain;
- MonoImage *image;
- MonoMethod *method;
+ do {
+ guint32 row, iloffset;
- MONO_CHECK_ARG_NULL (assembly);
+ row = * ((guint32 *) ptr)++;
+ iloffset = * ((guint32 *) ptr)++;
- domain = mono_domain_get();
- image = assembly->assembly->image;
+ if (!row && !offset)
+ return NULL;
+ if (!row)
+ continue;
- method = mono_get_method (image, token, NULL);
+ if (iloffset >= offset) {
+ if (line_number) {
+ *line_number = row;
+ return g_strdup (lnb->source_file);
+ } else
+ return g_strdup_printf ("%s:%d", lnb->source_file, row);
+ }
+ } while (1);
- return mono_method_get_object (domain, method);
+ return NULL;
}