5 #include <mono/metadata/metadata.h>
6 #include <mono/metadata/rawbuffer.h>
7 #include <mono/metadata/tokentype.h>
8 #include <mono/metadata/appdomain.h>
9 #include <mono/metadata/exception.h>
10 #include <mono/metadata/debug-symfile.h>
19 /* Keep in sync with Mono.CSharp.Debugger.MonoDwarfFileWriter */
21 #define MRT_target_address_size 0x01
22 #define MRT_il_offset 0x02
23 #define MRT_method_start_address 0x03
24 #define MRT_method_end_address 0x04
25 #define MRT_local_variable 0x05
26 #define MRT_method_parameter 0x06
27 #define MRT_type_sizeof 0x07
28 #define MRT_type_field_offset 0x08
29 #define MRT_mono_string_sizeof 0x09
30 #define MRT_mono_string_offset 0x0a
31 #define MRT_mono_array_sizeof 0x0b
32 #define MRT_mono_array_offset 0x0c
33 #define MRT_mono_array_bounds_sizeof 0x0d
34 #define MRT_mono_array_bounds_offset 0x0e
35 #define MRT_variable_start_scope 0x0f
36 #define MRT_variable_end_scope 0x10
37 #define MRT_mono_string_fieldsize 0x11
38 #define MRT_mono_array_fieldsize 0x12
39 #define MRT_type_field_fieldsize 0x13
40 #define MRT_mono_string_string_length 0x14
41 #define MRT_mono_string_byte_size 0x15
42 #define MRT_mono_string_data_location 0x16
43 #define MRT_static_type_field_offset 0x17
45 #define MRI_string_offset_length 0x00
46 #define MRI_string_offset_chars 0x01
48 #define MRI_array_offset_bounds 0x00
49 #define MRI_array_offset_max_length 0x01
50 #define MRI_array_offset_vector 0x02
52 #define MRI_array_bounds_offset_lower 0x00
53 #define MRI_array_bounds_offset_length 0x01
55 #define MRS_debug_info 0x01
56 #define MRS_debug_abbrev 0x02
57 #define MRS_debug_line 0x03
58 #define MRS_mono_reloc_table 0x04
60 #define DW_OP_const4u 0x0c
61 #define DW_OP_const4s 0x0d
62 #define DW_OP_plus 0x22
63 #define DW_OP_reg0 0x50
64 #define DW_OP_breg0 0x70
65 #define DW_OP_fbreg 0x91
66 #define DW_OP_piece 0x93
67 #define DW_OP_nop 0x96
72 get_sections_elf32 (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
75 Elf32_Shdr *section, *strtab_section;
79 header = (Elf32_Ehdr *)symfile->raw_contents;
80 if (header->e_version != EV_CURRENT) {
82 g_warning ("Symbol file %s has unknown ELF version %d",
83 symfile->file_name, header->e_version);
87 if (header->e_machine != EM_386) {
89 g_warning ("ELF file %s is for unknown architecture %d",
90 symfile->file_name, header->e_machine);
94 if (header->e_shentsize != sizeof (*section)) {
96 g_warning ("ELF file %s has unknown section header size "
97 "(expected %d, got %d)", symfile->file_name,
98 sizeof (*section), header->e_shentsize);
102 symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
104 section = (Elf32_Shdr *)(symfile->raw_contents + header->e_shoff);
105 strtab_section = section + header->e_shstrndx;
106 strtab = symfile->raw_contents + strtab_section->sh_offset;
108 for (i = 0; i < header->e_shnum; i++, section++) {
109 const gchar *name = strtab + section->sh_name;
111 if (!strcmp (name, ".debug_info")) {
112 MonoDebugSymbolFileSection *sfs;
114 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO];
115 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO;
116 sfs->file_offset = section->sh_offset;
117 sfs->size = section->sh_size;
118 } else if (!strcmp (name, ".debug_line")) {
119 MonoDebugSymbolFileSection *sfs;
121 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE];
122 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE;
123 sfs->file_offset = section->sh_offset;
124 sfs->size = section->sh_size;
125 } else if (!strcmp (name, ".debug_abbrev")) {
126 MonoDebugSymbolFileSection *sfs;
128 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV];
129 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV;
130 sfs->file_offset = section->sh_offset;
131 sfs->size = section->sh_size;
132 } else if (!strcmp (name, ".mono_reloc_table")) {
133 MonoDebugSymbolFileSection *sfs;
135 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE];
136 sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
137 sfs->file_offset = section->sh_offset;
138 sfs->size = section->sh_size;
139 } else if (!strcmp (name, ".mono_line_numbers")) {
140 MonoDebugSymbolFileSection *sfs;
142 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS];
143 sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS;
144 sfs->file_offset = section->sh_offset;
145 sfs->size = section->sh_size;
152 #endif /* HAVE_ELF_H */
155 get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
159 static const char ELFMAG[] = { ELFMAG0, ELFMAG1, ELFMAG2, ELFMAG3, 0 };
161 if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
162 return get_sections_elf32 (symfile, emit_warnings);
166 g_warning ("Symbol file %s has unknown file format", symfile->file_name);
172 read_line_numbers (MonoDebugSymbolFile *symfile)
174 const char *ptr, *start, *end;
178 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS].file_offset)
181 ptr = start = symfile->raw_contents +
182 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS].file_offset;
184 version = *((guint16 *) ptr)++;
185 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
186 g_warning ("Symbol file %s has incorrect line number table version "
187 "(expected %d, got %d)", symfile->file_name,
188 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
192 section_size = *((guint32 *) ptr)++;
193 end = ptr + section_size;
195 symfile->line_number_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
196 NULL, (GDestroyNotify) g_free);
199 MonoDebugLineNumberBlock *lnb;
200 guint32 token, source_offset;
203 token = * ((guint32 *) ptr)++;
204 method = mono_get_method (symfile->image, token, NULL);
208 lnb = g_new0 (MonoDebugLineNumberBlock, 1);
210 source_offset = * ((guint32 *) ptr)++;
211 lnb->source_file = (const char *) start + source_offset;
212 lnb->start_line = * ((guint32 *) ptr)++;
213 lnb->file_offset = * ((guint32 *) ptr)++;
215 g_hash_table_insert (symfile->line_number_table, method, lnb);
220 mono_debug_class_get (MonoDebugSymbolFile *symfile, guint32 type_token)
224 if ((klass = g_hash_table_lookup (symfile->image->class_cache, GUINT_TO_POINTER (type_token))))
230 MonoDebugSymbolFile *
231 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
233 MonoDebugSymbolFile *symfile;
238 fd = open (filename, O_RDWR);
241 g_warning ("Can't open symbol file: %s", filename);
245 file_size = lseek (fd, 0, SEEK_END);
246 lseek (fd, 0, SEEK_SET);
248 if (file_size == (off_t) -1) {
250 g_warning ("Can't get size of symbol file: %s", filename);
254 ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
257 g_warning ("Can't read symbol file: %s", filename);
261 symfile = g_new0 (MonoDebugSymbolFile, 1);
263 symfile->file_name = g_strdup (filename);
264 symfile->image = image;
265 symfile->raw_contents = ptr;
266 symfile->raw_contents_size = file_size;
268 if (!get_sections (symfile, emit_warnings)) {
269 mono_debug_close_symbol_file (symfile);
273 read_line_numbers (symfile);
279 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
284 if (symfile->raw_contents)
285 mono_raw_buffer_free (symfile->raw_contents);
289 if (symfile->line_number_table)
290 g_hash_table_destroy (symfile->line_number_table);
291 g_free (symfile->file_name);
292 g_free (symfile->section_offsets);
297 relocate_variable (MonoDebugVarInfo *var, void *base_ptr)
300 * ((guint8 *) base_ptr)++ = DW_OP_nop;
301 * ((guint8 *) base_ptr)++ = DW_OP_nop;
302 * ((guint8 *) base_ptr)++ = DW_OP_nop;
303 * ((guint8 *) base_ptr)++ = DW_OP_nop;
304 * ((guint8 *) base_ptr)++ = DW_OP_nop;
305 * ((guint8 *) base_ptr)++ = DW_OP_nop;
306 * ((guint8 *) base_ptr)++ = DW_OP_nop;
307 * ((guint8 *) base_ptr)++ = DW_OP_nop;
312 * Update the location description for a local variable or method parameter.
313 * MCS always reserves 8 bytes for us to do this, if we don't need them all
314 * we just fill up the rest with DW_OP_nop's.
317 switch (var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS) {
318 case MONO_DEBUG_VAR_ADDRESS_MODE_STACK:
320 * Variable is on the stack.
322 * If `index' is zero, use the normal frame register. Otherwise, bits
323 * 0..4 of `index' contain the frame register.
325 * Both DW_OP_fbreg and DW_OP_breg0 ... DW_OP_breg31 take an ULeb128
326 * argument - since this has an variable size, we set it to zero and
327 * manually add a 4 byte constant using DW_OP_plus.
330 /* Use the normal frame register (%ebp on the i386). */
331 * ((guint8 *) base_ptr)++ = DW_OP_fbreg;
333 /* Use a custom frame register. */
334 * ((guint8 *) base_ptr)++ = DW_OP_breg0 + (var->index & 0x001f);
335 * ((guint8 *) base_ptr)++ = 0;
336 * ((guint8 *) base_ptr)++ = DW_OP_const4s;
337 * ((gint32 *) base_ptr)++ = var->offset;
338 * ((guint8 *) base_ptr)++ = DW_OP_plus;
341 case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
343 * Variable is in the register whose number is contained in bits 0..4
346 * We need to write exactly 8 bytes in this location description, so instead
347 * of filling up the rest with DW_OP_nop's just add the `offset' even if
350 * ((guint8 *) base_ptr)++ = DW_OP_reg0 + (var->index & 0x001f);
351 * ((guint8 *) base_ptr)++ = DW_OP_nop;
352 * ((guint8 *) base_ptr)++ = DW_OP_const4s;
353 * ((gint32 *) base_ptr)++ = var->offset;
354 * ((guint8 *) base_ptr)++ = DW_OP_plus;
357 case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS:
359 * Variable is in two registers whose numbers are in bits 0..4 and 5..9 of
360 * the `index' field. Don't add `offset' since we have only two bytes left,
361 * fill them up with DW_OP_nop's.
363 * ((guint8 *) base_ptr)++ = DW_OP_reg0 + (var->index & 0x001f);
364 * ((guint8 *) base_ptr)++ = DW_OP_piece;
365 * ((guint8 *) base_ptr)++ = sizeof (int);
366 * ((guint8 *) base_ptr)++ = DW_OP_reg0 + ((var->index & 0x1f0) >> 5);
367 * ((guint8 *) base_ptr)++ = DW_OP_piece;
368 * ((guint8 *) base_ptr)++ = sizeof (int);
369 * ((guint8 *) base_ptr)++ = DW_OP_nop;
370 * ((guint8 *) base_ptr)++ = DW_OP_nop;
374 g_assert_not_reached ();
379 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
380 MonoDebugMethodInfoFunc method_info_func,
383 const char *reloc_ptr, *reloc_start, *reloc_end;
384 int version, already_relocated = 0;
387 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
390 reloc_ptr = reloc_start = symfile->raw_contents +
391 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
393 version = *((guint16 *) reloc_ptr)++;
394 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
395 g_warning ("Symbol file %s has incorrect relocation table version "
396 "(expected %d, got %d)", symfile->file_name,
397 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
401 already_relocated = *reloc_ptr;
402 *((char *) reloc_ptr)++ = 1;
404 reloc_size = *((guint32 *) reloc_ptr)++;
405 reloc_end = reloc_ptr + reloc_size;
407 while (reloc_ptr < reloc_end) {
408 int type, size, section, offset;
413 size = * ((guint32 *) reloc_ptr)++;
418 section = *tmp_ptr++;
419 offset = *((guint32 *) tmp_ptr)++;
421 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
422 g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
423 symfile->file_name, section);
427 if (!symfile->section_offsets [section].file_offset) {
428 g_warning ("Symbol file %s contains a relocation entry for non-existing "
429 "section %d", symfile->file_name, section);
433 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
434 base_ptr = base_ptr + offset;
437 case MRT_target_address_size:
438 * (guint8 *) base_ptr = sizeof (void *);
440 case MRT_method_start_address: {
441 int token = *((guint32 *) tmp_ptr)++;
442 MonoDebugMethodInfo *minfo;
444 minfo = method_info_func (symfile, token, user_data);
447 * (void **) base_ptr = 0;
452 g_message ("Start of `%s' (%ld) relocated to %p", minfo->method->name,
453 token, minfo->code_start);
456 * (void **) base_ptr = minfo->code_start;
460 case MRT_method_end_address: {
461 int token = *((guint32 *) tmp_ptr)++;
462 MonoDebugMethodInfo *minfo;
464 minfo = method_info_func (symfile, token, user_data);
467 * (void **) base_ptr = 0;
471 * (void **) base_ptr = (char *)minfo->code_start + minfo->code_size;
475 case MRT_il_offset: {
476 guint32 token = *((guint32 *) tmp_ptr)++;
477 guint32 original = *((guint32 *) tmp_ptr)++;
478 MonoDebugMethodInfo *minfo;
482 minfo = method_info_func (symfile, token, user_data);
485 * (void **) base_ptr = 0;
489 address = minfo->code_size;
491 for (i = 0; i < minfo->num_il_offsets; i++) {
492 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
494 if (il->offset >= original) {
495 address = il->address;
501 g_message ("Relocating IL offset %04x in `%s' to %d (%p)",
502 original, minfo->method->name, address,
503 minfo->code_start + address);
506 * (void **) base_ptr = minfo->code_start + address;
510 case MRT_local_variable: {
511 guint32 token = *((guint32 *) tmp_ptr)++;
512 guint32 original = *((guint32 *) tmp_ptr)++;
513 MonoDebugMethodInfo *minfo;
515 minfo = method_info_func (symfile, token, user_data);
518 relocate_variable (NULL, base_ptr);
522 if (original > minfo->num_locals) {
523 g_warning ("Symbol file %s contains relocation entry for non-existing "
524 "local variable %d, but method %s only has %d local variables.",
525 symfile->file_name, original, minfo->method->name,
527 g_message (G_STRLOC ": %d", token);
532 relocate_variable (&minfo->locals [original], base_ptr);
536 case MRT_method_parameter: {
537 guint32 token = *((guint32 *) tmp_ptr)++;
538 guint32 original = *((guint32 *) tmp_ptr)++;
539 MonoDebugMethodInfo *minfo;
541 minfo = method_info_func (symfile, token, user_data);
544 relocate_variable (NULL, base_ptr);
548 if (minfo->method->signature->hasthis) {
550 relocate_variable (minfo->this_var, base_ptr);
557 if (original > minfo->num_params) {
558 g_warning ("Symbol file %s contains relocation entry for non-existing "
559 "parameter %d, but method %s only has %d parameters.",
560 symfile->file_name, original, minfo->method->name,
565 relocate_variable (&minfo->params [original], base_ptr);
569 case MRT_type_sizeof: {
570 guint32 token = *((guint32 *) tmp_ptr)++;
571 MonoClass *klass = mono_debug_class_get (symfile, token);
576 mono_class_init (klass);
578 if (klass->enumtype || klass->valuetype)
579 * (gint8 *) base_ptr = klass->instance_size - sizeof (MonoObject);
581 * (gint8 *) base_ptr = klass->instance_size;
585 case MRT_type_field_offset: {
586 guint32 token = *((guint32 *) tmp_ptr)++;
587 guint32 original = *((guint32 *) tmp_ptr)++;
588 MonoClass *klass = mono_debug_class_get (symfile, token);
594 mono_class_init (klass);
596 if (original > klass->field.count) {
597 g_warning ("Symbol file %s contains invalid field offset entry.",
599 g_message (G_STRLOC ": %d", token);
600 /* G_BREAKPOINT (); */
607 off = klass->fields [original].offset;
608 if (klass->byval_arg.type == MONO_TYPE_VALUETYPE)
609 off -= sizeof (MonoObject);
612 g_message ("Setting field %d of type %u to offset %d", original,
616 * (guint32 *) base_ptr = off;
620 case MRT_mono_string_sizeof:
621 * (gint8 *) base_ptr = sizeof (MonoString);
624 case MRT_mono_string_offset: {
625 guint32 idx = *((guint32 *) tmp_ptr)++;
630 case MRI_string_offset_length:
631 off = (guchar *) &string.length - (guchar *) &string;
634 case MRI_string_offset_chars:
635 off = (guchar *) &string.chars - (guchar *) &string;
639 g_warning ("Symbol file %s contains invalid string offset entry",
644 * (guint32 *) base_ptr = off;
648 case MRT_mono_array_sizeof:
649 * (gint8 *) base_ptr = sizeof (MonoArray);
652 case MRT_mono_array_offset: {
653 guint32 idx = *((guint32 *) tmp_ptr)++;
658 case MRI_array_offset_bounds:
659 off = (guchar *) &array.bounds - (guchar *) &array;
662 case MRI_array_offset_max_length:
663 off = (guchar *) &array.max_length - (guchar *) &array;
666 case MRI_array_offset_vector:
667 off = (guchar *) &array.vector - (guchar *) &array;
671 g_warning ("Symbol file %s contains invalid array offset entry",
676 * (guint32 *) base_ptr = off;
681 case MRT_mono_array_bounds_sizeof:
682 * (gint8 *) base_ptr = sizeof (MonoArrayBounds);
685 case MRT_mono_array_bounds_offset: {
686 guint32 idx = *((guint32 *) tmp_ptr)++;
687 MonoArrayBounds bounds;
691 case MRI_array_bounds_offset_lower:
692 off = (guchar *) &bounds.lower_bound - (guchar *) &bounds;
695 case MRI_array_bounds_offset_length:
696 off = (guchar *) &bounds.length - (guchar *) &bounds;
700 g_warning ("Symbol file %s contains invalid array bounds offset entry",
705 * (guint32 *) base_ptr = off;
710 case MRT_variable_start_scope: {
711 guint32 token = *((guint32 *) tmp_ptr)++;
712 guint32 original = *((guint32 *) tmp_ptr)++;
713 MonoDebugMethodInfo *minfo;
716 minfo = method_info_func (symfile, token, user_data);
718 if (!minfo || !minfo->locals) {
719 * (void **) base_ptr = 0;
723 if (original > minfo->num_locals) {
724 g_warning ("Symbol file %s contains relocation entry for non-existing "
725 "local variable %d, but method %s only has %d local variables.",
726 symfile->file_name, original, minfo->method->name,
731 address = minfo->locals [original].begin_scope;
733 * (void **) base_ptr = minfo->code_start + address;
738 case MRT_variable_end_scope: {
739 guint32 token = *((guint32 *) tmp_ptr)++;
740 guint32 original = *((guint32 *) tmp_ptr)++;
741 MonoDebugMethodInfo *minfo;
744 minfo = method_info_func (symfile, token, user_data);
746 if (!minfo || !minfo->locals) {
747 * (void **) base_ptr = 0;
751 if (original > minfo->num_locals) {
752 g_warning ("Symbol file %s contains relocation entry for non-existing "
753 "local variable %d, but method %s only has %d local variables.",
754 symfile->file_name, original, minfo->method->name,
759 address = minfo->locals [original].end_scope;
761 * (void **) base_ptr = minfo->code_start + address;
766 case MRT_mono_string_fieldsize: {
767 guint32 idx = *((guint32 *) tmp_ptr)++;
772 case MRI_string_offset_length:
773 fieldsize = sizeof (string.length);
777 g_warning ("Symbol file %s contains invalid string fieldsize entry",
782 * (guint32 *) base_ptr = fieldsize;
787 case MRT_mono_array_fieldsize: {
788 guint32 idx = *((guint32 *) tmp_ptr)++;
793 case MRI_array_offset_bounds:
794 fieldsize = sizeof (array.bounds);
797 case MRI_array_offset_max_length:
798 fieldsize = sizeof (array.max_length);
801 case MRI_array_offset_vector:
802 fieldsize = sizeof (array.vector);
806 g_warning ("Symbol file %s contains invalid array fieldsize entry",
811 * (guint32 *) base_ptr = fieldsize;
816 case MRT_mono_string_string_length: {
818 guint32 offset = (guchar *) &string.length - (guchar *) &string;
820 * ((guint8 *) base_ptr)++ = DW_OP_const4u;
821 * ((gint32 *) base_ptr)++ = offset;
822 * ((guint8 *) base_ptr)++ = DW_OP_nop;
823 * ((guint8 *) base_ptr)++ = DW_OP_nop;
824 * ((guint8 *) base_ptr)++ = DW_OP_nop;
829 case MRT_mono_string_byte_size: {
832 * (guint32 *) base_ptr = sizeof (string.length);
837 case MRT_mono_string_data_location: {
839 guint32 offset = (guchar *) &string.chars - (guchar *) &string;
841 * ((guint8 *) base_ptr)++ = DW_OP_const4u;
842 * ((gint32 *) base_ptr)++ = offset;
843 * ((guint8 *) base_ptr)++ = DW_OP_nop;
844 * ((guint8 *) base_ptr)++ = DW_OP_nop;
845 * ((guint8 *) base_ptr)++ = DW_OP_nop;
850 case MRT_static_type_field_offset: {
851 guint32 token = *((guint32 *) tmp_ptr)++;
852 guint32 original = *((guint32 *) tmp_ptr)++;
853 MonoClass *klass = mono_debug_class_get (symfile, token);
860 mono_class_init (klass);
862 if (original > klass->field.count) {
863 g_warning ("Symbol file %s contains invalid field offset entry.",
871 vtable = mono_class_vtable (mono_domain_get (), klass);
873 off = klass->fields [original].offset;
876 g_message ("Setting field %d of type %u (%p) to offset %d", original,
880 * (void **) base_ptr = vtable->data + off;
886 g_warning ("Symbol file %s contains unknown relocation entry %d",
887 symfile->file_name, type);
892 mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
896 mono_debug_find_source_location (MonoDebugSymbolFile *symfile, MonoMethod *method, guint32 offset,
897 guint32 *line_number)
899 MonoDebugLineNumberBlock *lnb;
902 if (!symfile->line_number_table)
905 lnb = g_hash_table_lookup (symfile->line_number_table, method);
909 ptr = symfile->raw_contents +
910 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_LINE_NUMBERS].file_offset;
912 ptr += lnb->file_offset;
915 guint32 row, iloffset;
917 row = * ((guint32 *) ptr)++;
918 iloffset = * ((guint32 *) ptr)++;
925 if (iloffset >= offset) {
928 return g_strdup (lnb->source_file);
930 return g_strdup_printf ("%s:%d", lnb->source_file, row);