4 #include <mono/metadata/metadata.h>
5 #include <mono/metadata/rawbuffer.h>
6 #include <mono/metadata/appdomain.h>
7 #include <mono/metadata/exception.h>
8 #include <mono/metadata/debug-symfile.h>
17 /* Keep in sync with Mono.CSharp.Debugger.MonoDwarfFileWriter */
19 #define MRT_target_address_size 0x01
20 #define MRT_il_offset 0x02
21 #define MRT_method_start_address 0x03
22 #define MRT_method_end_address 0x04
23 #define MRT_local_variable 0x05
24 #define MRT_method_parameter 0x06
25 #define MRT_type_sizeof 0x07
26 #define MRT_type_field_offset 0x08
27 #define MRT_mono_string_sizeof 0x09
28 #define MRT_mono_string_offset 0x0a
29 #define MRT_mono_array_sizeof 0x0b
30 #define MRT_mono_array_offset 0x0c
31 #define MRT_mono_array_bounds_sizeof 0x0d
32 #define MRT_mono_array_bounds_offset 0x0e
34 #define MRI_string_offset_length 0x00
35 #define MRI_string_offset_vector 0x01
37 #define MRI_array_offset_bounds 0x00
38 #define MRI_array_offset_max_length 0x01
39 #define MRI_array_offset_vector 0x02
41 #define MRI_array_bounds_offset_lower 0x00
42 #define MRI_array_bounds_offset_length 0x01
44 #define MRS_debug_info 0x01
45 #define MRS_debug_abbrev 0x02
46 #define MRS_debug_line 0x03
47 #define MRS_mono_reloc_table 0x04
52 get_sections_elf32 (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
55 Elf32_Shdr *section, *strtab_section;
59 header = symfile->raw_contents;
60 if (header->e_version != EV_CURRENT) {
62 g_warning ("Symbol file %s has unknown ELF version %d",
63 symfile->file_name, header->e_version);
67 if (header->e_machine != EM_386) {
69 g_warning ("ELF file %s is for unknown architecture %d",
70 symfile->file_name, header->e_machine);
74 if (header->e_shentsize != sizeof (*section)) {
76 g_warning ("ELF file %s has unknown section header size "
77 "(expected %d, got %d)", symfile->file_name,
78 sizeof (*section), header->e_shentsize);
82 symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
84 section = symfile->raw_contents + header->e_shoff;
85 strtab_section = section + header->e_shstrndx;
86 strtab = symfile->raw_contents + strtab_section->sh_offset;
88 for (i = 0; i < header->e_shnum; i++, section++) {
89 const gchar *name = strtab + section->sh_name;
91 if (!strcmp (name, ".debug_info")) {
92 MonoDebugSymbolFileSection *sfs;
94 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO];
95 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO;
96 sfs->file_offset = section->sh_offset;
97 sfs->size = section->sh_size;
98 } else if (!strcmp (name, ".debug_line")) {
99 MonoDebugSymbolFileSection *sfs;
101 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE];
102 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE;
103 sfs->file_offset = section->sh_offset;
104 sfs->size = section->sh_size;
105 } else if (!strcmp (name, ".debug_abbrev")) {
106 MonoDebugSymbolFileSection *sfs;
108 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV];
109 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV;
110 sfs->file_offset = section->sh_offset;
111 sfs->size = section->sh_size;
112 } else if (!strcmp (name, ".mono_reloc_table")) {
113 MonoDebugSymbolFileSection *sfs;
115 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE];
116 sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
117 sfs->file_offset = section->sh_offset;
118 sfs->size = section->sh_size;
125 #endif /* HAVE_ELF_H */
128 get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
131 if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
132 return get_sections_elf32 (symfile, emit_warnings);
136 g_warning ("Symbol file %s has unknown file format", symfile->file_name);
142 mono_debug_class_get (MonoDebugSymbolFile *symfile, guint32 type_token)
146 if ((klass = g_hash_table_lookup (symfile->image->class_cache, GUINT_TO_POINTER (type_token))))
152 MonoDebugSymbolFile *
153 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
155 MonoDebugSymbolFile *symfile;
160 fd = open (filename, O_RDWR);
163 g_warning ("Can't open symbol file: %s", filename);
167 file_size = lseek (fd, 0, SEEK_END);
168 lseek (fd, 0, SEEK_SET);
170 if (file_size == (off_t) -1) {
172 g_warning ("Can't get size of symbol file: %s", filename);
176 ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
179 g_warning ("Can't read symbol file: %s", filename);
183 symfile = g_new0 (MonoDebugSymbolFile, 1);
185 symfile->file_name = g_strdup (filename);
186 symfile->image = image;
187 symfile->raw_contents = ptr;
188 symfile->raw_contents_size = file_size;
190 if (!get_sections (symfile, emit_warnings)) {
191 mono_debug_close_symbol_file (symfile);
199 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
204 if (symfile->raw_contents)
205 mono_raw_buffer_free (symfile->raw_contents);
209 g_free (symfile->file_name);
210 g_free (symfile->section_offsets);
215 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
216 MonoDebugMethodInfoFunc method_info_func,
219 const char *reloc_ptr, *reloc_start, *reloc_end;
220 int version, already_relocated = 0;
223 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
226 reloc_ptr = reloc_start = symfile->raw_contents +
227 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
229 version = *((guint16 *) reloc_ptr)++;
230 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
231 g_warning ("Symbol file %s has incorrect relocation table version "
232 "(expected %d, got %d)", symfile->file_name,
233 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
237 already_relocated = *reloc_ptr;
238 *((char *) reloc_ptr)++ = 1;
240 reloc_size = *((guint32 *) reloc_ptr)++;
241 reloc_end = reloc_ptr + reloc_size;
243 while (reloc_ptr < reloc_end) {
244 int type, size, section, offset;
249 size = * ((guint32 *) reloc_ptr)++;
254 section = *tmp_ptr++;
255 offset = *((guint32 *) tmp_ptr)++;
257 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
258 g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
259 symfile->file_name, section);
263 if (!symfile->section_offsets [section].file_offset) {
264 g_warning ("Symbol file %s contains a relocation entry for non-existing "
265 "section %d", symfile->file_name, section);
269 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
273 case MRT_target_address_size:
274 * (guint8 *) base_ptr = sizeof (void *);
276 case MRT_method_start_address: {
277 int token = *((guint32 *) tmp_ptr)++;
278 MonoDebugMethodInfo *minfo;
280 minfo = method_info_func (symfile, token, user_data);
283 * (void **) base_ptr = 0;
288 g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
291 * (void **) base_ptr = minfo->code_start;
295 case MRT_method_end_address: {
296 int token = *((guint32 *) tmp_ptr)++;
297 MonoDebugMethodInfo *minfo;
299 minfo = method_info_func (symfile, token, user_data);
302 * (void **) base_ptr = 0;
306 * (void **) base_ptr = minfo->code_start + minfo->code_size;
310 case MRT_il_offset: {
311 guint32 token = *((guint32 *) tmp_ptr)++;
312 guint32 original = *((guint32 *) tmp_ptr)++;
313 MonoDebugMethodInfo *minfo;
317 minfo = method_info_func (symfile, token, user_data);
320 * (void **) base_ptr = 0;
324 address = minfo->code_size;
326 for (i = 0; i < minfo->num_il_offsets; i++) {
327 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
329 if (il->offset >= original) {
330 address = il->address;
336 g_message ("Relocating IL offset %d in `%s' to %d (%p)",
337 original, minfo->method->name, address,
338 minfo->code_start + address);
341 * (void **) base_ptr = minfo->code_start + address;
345 case MRT_local_variable: {
346 guint32 token = *((guint32 *) tmp_ptr)++;
347 guint32 original = *((guint32 *) tmp_ptr)++;
348 MonoDebugMethodInfo *minfo;
351 minfo = method_info_func (symfile, token, user_data);
354 * (void **) base_ptr = 0;
358 if (original > minfo->num_locals) {
359 g_warning ("Symbol file %s contains relocation entry for non-existing "
360 "local variable %d, but method %s only has %d local variables.",
361 symfile->file_name, original, minfo->method->name,
366 address = minfo->local_offsets [original];
369 g_message ("Relocating local variable %d (%s) to stack offset %d",
370 original, minfo->method->name, address);
373 * (gint32 *) base_ptr = address;
377 case MRT_method_parameter: {
378 guint32 token = *((guint32 *) tmp_ptr)++;
379 guint32 original = *((guint32 *) tmp_ptr)++;
380 MonoDebugMethodInfo *minfo;
383 minfo = method_info_func (symfile, token, user_data);
386 * (void **) base_ptr = 0;
390 if (minfo->method->signature->hasthis) {
392 * (gint32 *) base_ptr = minfo->this_offset;
399 if (original > minfo->num_params) {
400 g_warning ("Symbol file %s contains relocation entry for non-existing "
401 "parameter %d, but method %s only has %d parameters.",
402 symfile->file_name, original, minfo->method->name,
407 address = minfo->param_offsets [original];
410 g_message ("Relocating parameter %d (%s) to stack offset %d",
411 original, minfo->method->name, address);
414 * (gint32 *) base_ptr = address;
418 case MRT_type_sizeof: {
419 guint32 token = *((guint32 *) tmp_ptr)++;
420 MonoClass *klass = mono_debug_class_get (symfile, token);
425 mono_class_init (klass);
427 if (klass->enumtype || klass->valuetype)
428 * (gint8 *) base_ptr = klass->instance_size - sizeof (MonoObject);
430 * (gint8 *) base_ptr = klass->instance_size;
434 case MRT_type_field_offset: {
435 guint32 token = *((guint32 *) tmp_ptr)++;
436 guint32 original = *((guint32 *) tmp_ptr)++;
437 MonoClass *klass = mono_debug_class_get (symfile, token);
443 mono_class_init (klass);
445 if (original > klass->field.count) {
446 g_warning ("Symbol file %s contains invalid field offset entry.",
451 offset = klass->fields [original].offset;
452 if (klass->byval_arg.type == MONO_TYPE_VALUETYPE)
453 offset -= sizeof (MonoObject);
456 g_message ("Setting field %d of type %u to offset %d", original,
460 * (guint32 *) base_ptr = offset;
464 case MRT_mono_string_sizeof:
465 * (gint8 *) base_ptr = sizeof (MonoString);
468 case MRT_mono_string_offset: {
469 guint32 index = *((guint32 *) tmp_ptr)++;
474 case MRI_string_offset_length:
475 offset = (guchar *) &string.length - (guchar *) &string;
478 case MRI_string_offset_vector:
479 offset = (guchar *) &string.c_str - (guchar *) &string;
483 g_warning ("Symbol file %s contains invalid string offset entry",
488 * (guint32 *) base_ptr = offset;
492 case MRT_mono_array_sizeof:
493 * (gint8 *) base_ptr = sizeof (MonoArray);
496 case MRT_mono_array_offset: {
497 guint32 index = *((guint32 *) tmp_ptr)++;
502 case MRI_array_offset_bounds:
503 offset = (guchar *) &array.bounds - (guchar *) &array;
506 case MRI_array_offset_max_length:
507 offset = (guchar *) &array.max_length - (guchar *) &array;
510 case MRI_array_offset_vector:
511 offset = (guchar *) &array.vector - (guchar *) &array;
515 g_warning ("Symbol file %s contains invalid array offset entry",
520 * (guint32 *) base_ptr = offset;
525 case MRT_mono_array_bounds_sizeof:
526 * (gint8 *) base_ptr = sizeof (MonoArrayBounds);
529 case MRT_mono_array_bounds_offset: {
530 guint32 index = *((guint32 *) tmp_ptr)++;
531 MonoArrayBounds bounds;
535 case MRI_array_bounds_offset_lower:
536 offset = (guchar *) &bounds.lower_bound - (guchar *) &bounds;
539 case MRI_array_bounds_offset_length:
540 offset = (guchar *) &bounds.length - (guchar *) &bounds;
544 g_warning ("Symbol file %s contains invalid array bounds offset entry",
549 * (guint32 *) base_ptr = offset;
555 g_warning ("Symbol file %s contains unknown relocation entry %d",
556 symfile->file_name, type);
561 mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
565 ves_icall_Debugger_MonoSymbolWriter_get_local_type_from_sig (MonoReflectionAssembly *assembly,
566 MonoArray *signature)
574 MONO_CHECK_ARG_NULL (assembly);
575 MONO_CHECK_ARG_NULL (signature);
577 domain = mono_domain_get();
578 image = assembly->assembly->image;
580 ptr = mono_array_addr (signature, char, 0);
581 g_assert (*ptr++ == 0x07);
582 len = mono_metadata_decode_value (ptr, &ptr);
585 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
587 return mono_type_get_object (domain, type);
590 MonoReflectionMethod *
591 ves_icall_Debugger_MonoSymbolWriter_method_from_token (MonoReflectionAssembly *assembly, guint32 token)
597 MONO_CHECK_ARG_NULL (assembly);
599 domain = mono_domain_get();
600 image = assembly->assembly->image;
602 method = mono_get_method (image, token, NULL);
604 return mono_method_get_object (domain, method);
608 ves_icall_Debugger_DwarfFileWriter_get_type_token (MonoReflectionType *type)
610 MonoClass *klass = mono_class_from_mono_type (type->type);
612 mono_class_init (klass);
614 return klass->type_token;