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)
147 if ((klass = g_hash_table_lookup (symfile->image->class_cache, GUINT_TO_POINTER (type_token))))
150 for (ptr = symfile->image->references; ptr && *ptr; ptr++) {
151 MonoImage *image = (*ptr)->image;
153 if ((klass = g_hash_table_lookup (image->class_cache, GUINT_TO_POINTER (type_token))))
160 MonoDebugSymbolFile *
161 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
163 MonoDebugSymbolFile *symfile;
168 fd = open (filename, O_RDWR);
171 g_warning ("Can't open symbol file: %s", filename);
175 file_size = lseek (fd, 0, SEEK_END);
176 lseek (fd, 0, SEEK_SET);
178 if (file_size == (off_t) -1) {
180 g_warning ("Can't get size of symbol file: %s", filename);
184 ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
187 g_warning ("Can't read symbol file: %s", filename);
191 symfile = g_new0 (MonoDebugSymbolFile, 1);
193 symfile->file_name = g_strdup (filename);
194 symfile->image = image;
195 symfile->raw_contents = ptr;
196 symfile->raw_contents_size = file_size;
198 if (!get_sections (symfile, emit_warnings)) {
199 mono_debug_close_symbol_file (symfile);
207 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
212 if (symfile->raw_contents)
213 mono_raw_buffer_free (symfile->raw_contents);
217 g_free (symfile->file_name);
218 g_free (symfile->section_offsets);
223 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
224 MonoDebugMethodInfoFunc method_info_func,
227 const char *reloc_ptr, *reloc_start, *reloc_end;
228 int version, already_relocated = 0;
231 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
234 reloc_ptr = reloc_start = symfile->raw_contents +
235 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
237 version = *((guint16 *) reloc_ptr)++;
238 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
239 g_warning ("Symbol file %s has incorrect relocation table version "
240 "(expected %d, got %d)", symfile->file_name,
241 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
245 already_relocated = *reloc_ptr;
246 *((char *) reloc_ptr)++ = 1;
248 reloc_size = *((guint32 *) reloc_ptr)++;
249 reloc_end = reloc_ptr + reloc_size;
251 while (reloc_ptr < reloc_end) {
252 int type, size, section, offset;
257 size = * ((guint32 *) reloc_ptr)++;
262 section = *tmp_ptr++;
263 offset = *((guint32 *) tmp_ptr)++;
265 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
266 g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
267 symfile->file_name, section);
271 if (!symfile->section_offsets [section].file_offset) {
272 g_warning ("Symbol file %s contains a relocation entry for non-existing "
273 "section %d", symfile->file_name, section);
277 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
281 case MRT_target_address_size:
282 * (guint8 *) base_ptr = sizeof (void *);
284 case MRT_method_start_address: {
285 int token = *((guint32 *) tmp_ptr)++;
286 MonoDebugMethodInfo *minfo;
288 minfo = method_info_func (symfile, token, user_data);
291 * (void **) base_ptr = 0;
296 g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
299 * (void **) base_ptr = minfo->code_start;
303 case MRT_method_end_address: {
304 int token = *((guint32 *) tmp_ptr)++;
305 MonoDebugMethodInfo *minfo;
307 minfo = method_info_func (symfile, token, user_data);
310 * (void **) base_ptr = 0;
314 * (void **) base_ptr = minfo->code_start + minfo->code_size;
318 case MRT_il_offset: {
319 guint32 token = *((guint32 *) tmp_ptr)++;
320 guint32 original = *((guint32 *) tmp_ptr)++;
321 MonoDebugMethodInfo *minfo;
325 minfo = method_info_func (symfile, token, user_data);
328 * (void **) base_ptr = 0;
332 address = minfo->code_size;
334 for (i = 0; i < minfo->num_il_offsets; i++) {
335 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
337 if (il->offset >= original) {
338 address = il->address;
344 g_message ("Relocating IL offset %d in `%s' to %d (%p)",
345 original, minfo->method->name, address,
346 minfo->code_start + address);
349 * (void **) base_ptr = minfo->code_start + address;
353 case MRT_local_variable: {
354 guint32 token = *((guint32 *) tmp_ptr)++;
355 guint32 original = *((guint32 *) tmp_ptr)++;
356 MonoDebugMethodInfo *minfo;
359 minfo = method_info_func (symfile, token, user_data);
362 * (void **) base_ptr = 0;
366 if (original > minfo->num_locals) {
367 g_warning ("Symbol file %s contains relocation entry for non-existing "
368 "local variable %d, but method %s only has %d local variables.",
369 symfile->file_name, original, minfo->method->name,
374 address = minfo->local_offsets [original];
377 g_message ("Relocating local variable %d (%s) to stack offset %d",
378 original, minfo->method->name, address);
381 * (gint32 *) base_ptr = address;
385 case MRT_method_parameter: {
386 guint32 token = *((guint32 *) tmp_ptr)++;
387 guint32 original = *((guint32 *) tmp_ptr)++;
388 MonoDebugMethodInfo *minfo;
391 minfo = method_info_func (symfile, token, user_data);
394 * (void **) base_ptr = 0;
398 if (original > minfo->num_params) {
399 g_warning ("Symbol file %s contains relocation entry for non-existing "
400 "parameter %d, but method %s only has %d parameters.",
401 symfile->file_name, original, minfo->method->name,
406 address = minfo->param_offsets [original];
409 g_message ("Relocating parameter %d (%s) to stack offset %d",
410 original, minfo->method->name, address);
413 * (gint32 *) base_ptr = address;
417 case MRT_type_sizeof: {
418 guint32 token = *((guint32 *) tmp_ptr)++;
419 MonoClass *klass = mono_debug_class_get (symfile, token);
421 if (!klass || !klass->inited)
424 g_message ("Setting size of type %u to %d", token, klass->instance_size);
426 * (gint8 *) base_ptr = klass->instance_size;
430 case MRT_type_field_offset: {
431 guint32 token = *((guint32 *) tmp_ptr)++;
432 guint32 original = *((guint32 *) tmp_ptr)++;
433 MonoClass *klass = mono_debug_class_get (symfile, token);
436 if (!klass || !klass->inited)
439 if (original > klass->field.count) {
440 g_warning ("Symbol file %s contains invalid field offset entry.",
445 offset = klass->fields [original].offset;
446 if (klass->byval_arg.type == MONO_TYPE_VALUETYPE)
447 offset -= sizeof (MonoObject);
449 g_message ("Setting field %d of type %u to offset %d", original,
452 * (guint32 *) base_ptr = offset;
456 case MRT_mono_string_sizeof:
457 * (gint8 *) base_ptr = sizeof (MonoString);
460 case MRT_mono_string_offset: {
461 guint32 index = *((guint32 *) tmp_ptr)++;
466 case MRI_string_offset_length:
467 offset = (guchar *) &string.length - (guchar *) &string;
470 case MRI_string_offset_vector:
471 offset = (guchar *) &string.c_str - (guchar *) &string;
475 g_warning ("Symbol file %s contains invalid string offset entry",
480 * (guint32 *) base_ptr = offset;
484 case MRT_mono_array_sizeof:
485 * (gint8 *) base_ptr = sizeof (MonoArray);
488 case MRT_mono_array_offset: {
489 guint32 index = *((guint32 *) tmp_ptr)++;
494 case MRI_array_offset_bounds:
495 offset = (guchar *) &array.bounds - (guchar *) &array;
498 case MRI_array_offset_max_length:
499 offset = (guchar *) &array.max_length - (guchar *) &array;
502 case MRI_array_offset_vector:
503 offset = (guchar *) &array.vector - (guchar *) &array;
507 g_warning ("Symbol file %s contains invalid array offset entry",
512 * (guint32 *) base_ptr = offset;
517 case MRT_mono_array_bounds_sizeof:
518 * (gint8 *) base_ptr = sizeof (MonoArrayBounds);
521 case MRT_mono_array_bounds_offset: {
522 guint32 index = *((guint32 *) tmp_ptr)++;
523 MonoArrayBounds bounds;
527 case MRI_array_bounds_offset_lower:
528 offset = (guchar *) &bounds.lower_bound - (guchar *) &bounds;
531 case MRI_array_bounds_offset_length:
532 offset = (guchar *) &bounds.length - (guchar *) &bounds;
536 g_warning ("Symbol file %s contains invalid array bounds offset entry",
541 * (guint32 *) base_ptr = offset;
547 g_warning ("Symbol file %s contains unknown relocation entry %d",
548 symfile->file_name, type);
553 mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
557 ves_icall_Debugger_MonoSymbolWriter_get_local_type_from_sig (MonoReflectionAssembly *assembly,
558 MonoArray *signature)
567 MONO_CHECK_ARG_NULL (assembly);
568 MONO_CHECK_ARG_NULL (signature);
570 domain = mono_domain_get();
571 image = assembly->assembly->image;
573 ptr = mono_array_addr (signature, char, 0);
574 g_assert (*ptr++ == 0x07);
575 len = mono_metadata_decode_value (ptr, &ptr);
578 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
580 klass = mono_class_from_mono_type (type);
582 mono_class_init (klass);
584 return mono_type_get_object (domain, type);
587 MonoReflectionMethod *
588 ves_icall_Debugger_MonoSymbolWriter_method_from_token (MonoReflectionAssembly *assembly, guint32 token)
594 MONO_CHECK_ARG_NULL (assembly);
596 domain = mono_domain_get();
597 image = assembly->assembly->image;
599 method = mono_get_method (image, token, NULL);
601 return mono_method_get_object (domain, method);
605 ves_icall_Debugger_DwarfFileWriter_get_type_token (MonoReflectionType *type)
607 MonoClass *klass = mono_class_from_mono_type (type->type);
609 mono_class_init (klass);
611 return klass->type_token;