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
28 #define MRS_debug_info 0x01
29 #define MRS_debug_abbrev 0x02
30 #define MRS_debug_line 0x03
31 #define MRS_mono_reloc_table 0x04
36 get_sections_elf32 (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
39 Elf32_Shdr *section, *strtab_section;
43 header = symfile->raw_contents;
44 if (header->e_version != EV_CURRENT) {
46 g_warning ("Symbol file %s has unknown ELF version %d",
47 symfile->file_name, header->e_version);
51 if (header->e_machine != EM_386) {
53 g_warning ("ELF file %s is for unknown architecture %d",
54 symfile->file_name, header->e_machine);
58 if (header->e_shentsize != sizeof (*section)) {
60 g_warning ("ELF file %s has unknown section header size "
61 "(expected %d, got %d)", symfile->file_name,
62 sizeof (*section), header->e_shentsize);
66 symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
68 section = symfile->raw_contents + header->e_shoff;
69 strtab_section = section + header->e_shstrndx;
70 strtab = symfile->raw_contents + strtab_section->sh_offset;
72 for (i = 0; i < header->e_shnum; i++, section++) {
73 const gchar *name = strtab + section->sh_name;
75 if (!strcmp (name, ".debug_info")) {
76 MonoDebugSymbolFileSection *sfs;
78 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO];
79 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO;
80 sfs->file_offset = section->sh_offset;
81 sfs->size = section->sh_size;
82 } else if (!strcmp (name, ".debug_line")) {
83 MonoDebugSymbolFileSection *sfs;
85 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE];
86 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE;
87 sfs->file_offset = section->sh_offset;
88 sfs->size = section->sh_size;
89 } else if (!strcmp (name, ".debug_abbrev")) {
90 MonoDebugSymbolFileSection *sfs;
92 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV];
93 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV;
94 sfs->file_offset = section->sh_offset;
95 sfs->size = section->sh_size;
96 } else if (!strcmp (name, ".mono_reloc_table")) {
97 MonoDebugSymbolFileSection *sfs;
99 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE];
100 sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
101 sfs->file_offset = section->sh_offset;
102 sfs->size = section->sh_size;
109 #endif /* HAVE_ELF_H */
112 get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
115 if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
116 return get_sections_elf32 (symfile, emit_warnings);
120 g_warning ("Symbol file %s has unknown file format", symfile->file_name);
125 MonoDebugSymbolFile *
126 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
128 MonoDebugSymbolFile *symfile;
133 fd = open (filename, O_RDWR);
136 g_warning ("Can't open symbol file: %s", filename);
140 file_size = lseek (fd, 0, SEEK_END);
141 lseek (fd, 0, SEEK_SET);
143 if (file_size == (off_t) -1) {
145 g_warning ("Can't get size of symbol file: %s", filename);
149 ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
152 g_warning ("Can't read symbol file: %s", filename);
156 symfile = g_new0 (MonoDebugSymbolFile, 1);
158 symfile->file_name = g_strdup (filename);
159 symfile->image = image;
160 symfile->raw_contents = ptr;
161 symfile->raw_contents_size = file_size;
163 if (!get_sections (symfile, emit_warnings)) {
164 mono_debug_close_symbol_file (symfile);
172 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
177 if (symfile->raw_contents)
178 mono_raw_buffer_free (symfile->raw_contents);
182 g_free (symfile->file_name);
183 g_free (symfile->section_offsets);
188 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
189 MonoDebugMethodInfoFunc method_info_func,
192 const char *reloc_ptr, *reloc_start, *reloc_end;
193 int version, already_relocated = 0;
196 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
199 reloc_ptr = reloc_start = symfile->raw_contents +
200 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
202 version = *((guint16 *) reloc_ptr)++;
203 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
204 g_warning ("Symbol file %s has incorrect relocation table version "
205 "(expected %d, got %d)", symfile->file_name,
206 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
210 already_relocated = *reloc_ptr;
211 *((char *) reloc_ptr)++ = 1;
213 reloc_size = *((guint32 *) reloc_ptr)++;
214 reloc_end = reloc_ptr + reloc_size;
216 while (reloc_ptr < reloc_end) {
217 int type, size, section, offset;
222 size = * ((guint32 *) reloc_ptr)++;
227 section = *tmp_ptr++;
228 offset = *((guint32 *) tmp_ptr)++;
230 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
231 g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
232 symfile->file_name, section);
236 if (!symfile->section_offsets [section].file_offset) {
237 g_warning ("Symbol file %s contains a relocation entry for non-existing "
238 "section %d", symfile->file_name, section);
242 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
246 case MRT_target_address_size:
247 * (guint8 *) base_ptr = sizeof (void *);
249 case MRT_method_start_address: {
250 int token = *((guint32 *) tmp_ptr)++;
251 MonoDebugMethodInfo *minfo;
253 minfo = method_info_func (symfile, token, user_data);
256 * (void **) base_ptr = 0;
261 g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
264 * (void **) base_ptr = minfo->code_start;
268 case MRT_method_end_address: {
269 int token = *((guint32 *) tmp_ptr)++;
270 MonoDebugMethodInfo *minfo;
272 minfo = method_info_func (symfile, token, user_data);
275 * (void **) base_ptr = 0;
279 * (void **) base_ptr = minfo->code_start + minfo->code_size;
283 case MRT_il_offset: {
284 guint32 token = *((guint32 *) tmp_ptr)++;
285 guint32 original = *((guint32 *) tmp_ptr)++;
286 MonoDebugMethodInfo *minfo;
290 minfo = method_info_func (symfile, token, user_data);
293 * (void **) base_ptr = 0;
297 address = minfo->code_size;
299 for (i = 0; i < minfo->num_il_offsets; i++) {
300 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
302 if (il->offset >= original) {
303 address = il->address;
309 g_message ("Relocating IL offset %d in `%s' to %d (%p)",
310 original, minfo->method->name, address,
311 minfo->code_start + address);
314 * (void **) base_ptr = minfo->code_start + address;
318 case MRT_local_variable: {
319 guint32 token = *((guint32 *) tmp_ptr)++;
320 guint32 original = *((guint32 *) tmp_ptr)++;
321 MonoDebugMethodInfo *minfo;
324 minfo = method_info_func (symfile, token, user_data);
327 * (void **) base_ptr = 0;
331 if (original > minfo->num_locals) {
332 g_warning ("Symbol file %s contains relocation entry for non-existing "
333 "local variable %d, but method %s only has %d local variables.",
334 symfile->file_name, original, minfo->method->name,
339 address = minfo->local_offsets [original];
342 g_message ("Relocating local variable %d (%s) to stack offset %d",
343 original, minfo->method->name, address);
346 * (gint32 *) base_ptr = address;
350 case MRT_method_parameter: {
351 guint32 token = *((guint32 *) tmp_ptr)++;
352 guint32 original = *((guint32 *) tmp_ptr)++;
353 MonoDebugMethodInfo *minfo;
356 minfo = method_info_func (symfile, token, user_data);
359 * (void **) base_ptr = 0;
363 if (original > minfo->num_params) {
364 g_warning ("Symbol file %s contains relocation entry for non-existing "
365 "parameter %d, but method %s only has %d parameters.",
366 symfile->file_name, original, minfo->method->name,
371 address = minfo->param_offsets [original];
374 g_message ("Relocating parameter %d (%s) to stack offset %d",
375 original, minfo->method->name, address);
378 * (gint32 *) base_ptr = address;
382 case MRT_type_sizeof: {
383 guint32 token = *((guint32 *) tmp_ptr)++;
384 MonoClass *klass = mono_class_get (symfile->image, token);
386 g_message ("Setting size of type %u to %d", token, klass->instance_size);
388 * (gint8 *) base_ptr = klass->instance_size;
392 case MRT_type_field_offset: {
393 guint32 token = *((guint32 *) tmp_ptr)++;
394 guint32 original = *((guint32 *) tmp_ptr)++;
395 MonoClass *klass = mono_class_get (symfile->image, token);
398 if (original > klass->field.count) {
399 g_warning ("Symbol file %s contains invalid field offset entry.",
404 offset = klass->fields [original].offset;
405 if (klass->byval_arg.type == MONO_TYPE_VALUETYPE)
406 offset -= sizeof (MonoObject);
408 g_message ("Setting field %d of type %u to offset %d", original,
411 * (guint32 *) base_ptr = offset;
416 g_warning ("Symbol file %s contains unknown relocation entry %d",
417 symfile->file_name, type);
422 mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
426 ves_icall_Debugger_MonoSymbolWriter_get_local_type_from_sig (MonoReflectionAssembly *assembly,
427 MonoArray *signature)
436 MONO_CHECK_ARG_NULL (assembly);
437 MONO_CHECK_ARG_NULL (signature);
439 domain = mono_domain_get();
440 image = assembly->assembly->image;
442 ptr = mono_array_addr (signature, char, 0);
443 g_assert (*ptr++ == 0x07);
444 len = mono_metadata_decode_value (ptr, &ptr);
447 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
449 klass = mono_class_from_mono_type (type);
451 mono_class_init (klass);
453 return mono_type_get_object (domain, type);
456 MonoReflectionMethod *
457 ves_icall_Debugger_MonoSymbolWriter_method_from_token (MonoReflectionAssembly *assembly, guint32 token)
463 MONO_CHECK_ARG_NULL (assembly);
465 domain = mono_domain_get();
466 image = assembly->assembly->image;
468 method = mono_get_method (image, token, NULL);
470 return mono_method_get_object (domain, method);
474 ves_icall_Debugger_DwarfFileWriter_get_type_token (MonoReflectionType *type)
476 MonoClass *klass = mono_class_from_mono_type (type->type);
478 mono_class_init (klass);
480 return klass->type_token;