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
26 #define MRS_debug_info 0x01
27 #define MRS_debug_abbrev 0x02
28 #define MRS_debug_line 0x03
29 #define MRS_mono_reloc_table 0x04
34 get_sections_elf32 (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
37 Elf32_Shdr *section, *strtab_section;
41 header = symfile->raw_contents;
42 if (header->e_version != EV_CURRENT) {
44 g_warning ("Symbol file %s has unknown ELF version %d",
45 symfile->file_name, header->e_version);
49 if (header->e_machine != EM_386) {
51 g_warning ("ELF file %s is for unknown architecture %d",
52 symfile->file_name, header->e_machine);
56 if (header->e_shentsize != sizeof (*section)) {
58 g_warning ("ELF file %s has unknown section header size "
59 "(expected %d, got %d)", symfile->file_name,
60 sizeof (*section), header->e_shentsize);
64 symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
66 section = symfile->raw_contents + header->e_shoff;
67 strtab_section = section + header->e_shstrndx;
68 strtab = symfile->raw_contents + strtab_section->sh_offset;
70 for (i = 0; i < header->e_shnum; i++, section++) {
71 const gchar *name = strtab + section->sh_name;
73 if (!strcmp (name, ".debug_info")) {
74 MonoDebugSymbolFileSection *sfs;
76 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO];
77 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO;
78 sfs->file_offset = section->sh_offset;
79 sfs->size = section->sh_size;
80 } else if (!strcmp (name, ".debug_line")) {
81 MonoDebugSymbolFileSection *sfs;
83 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE];
84 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE;
85 sfs->file_offset = section->sh_offset;
86 sfs->size = section->sh_size;
87 } else if (!strcmp (name, ".debug_abbrev")) {
88 MonoDebugSymbolFileSection *sfs;
90 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV];
91 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV;
92 sfs->file_offset = section->sh_offset;
93 sfs->size = section->sh_size;
94 } else if (!strcmp (name, ".mono_reloc_table")) {
95 MonoDebugSymbolFileSection *sfs;
97 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE];
98 sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
99 sfs->file_offset = section->sh_offset;
100 sfs->size = section->sh_size;
107 #endif /* HAVE_ELF_H */
110 get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
113 if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
114 return get_sections_elf32 (symfile, emit_warnings);
118 g_warning ("Symbol file %s has unknown file format", symfile->file_name);
123 MonoDebugSymbolFile *
124 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
126 MonoDebugSymbolFile *symfile;
131 fd = open (filename, O_RDWR);
134 g_warning ("Can't open symbol file: %s", filename);
138 file_size = lseek (fd, 0, SEEK_END);
139 lseek (fd, 0, SEEK_SET);
141 if (file_size == (off_t) -1) {
143 g_warning ("Can't get size of symbol file: %s", filename);
147 ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
150 g_warning ("Can't read symbol file: %s", filename);
154 symfile = g_new0 (MonoDebugSymbolFile, 1);
156 symfile->file_name = g_strdup (filename);
157 symfile->image = image;
158 symfile->raw_contents = ptr;
159 symfile->raw_contents_size = file_size;
161 if (!get_sections (symfile, emit_warnings)) {
162 mono_debug_close_symbol_file (symfile);
170 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
175 if (symfile->raw_contents)
176 mono_raw_buffer_free (symfile->raw_contents);
180 g_free (symfile->file_name);
181 g_free (symfile->section_offsets);
186 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
187 MonoDebugMethodInfoFunc method_info_func,
190 const char *reloc_ptr, *reloc_start, *reloc_end;
191 int version, already_relocated = 0;
194 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
197 reloc_ptr = reloc_start = symfile->raw_contents +
198 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
200 version = *((guint16 *) reloc_ptr)++;
201 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
202 g_warning ("Symbol file %s has incorrect relocation table version "
203 "(expected %d, got %d)", symfile->file_name,
204 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
208 already_relocated = *reloc_ptr;
209 *((char *) reloc_ptr)++ = 1;
211 reloc_size = *((guint32 *) reloc_ptr)++;
212 reloc_end = reloc_ptr + reloc_size;
214 while (reloc_ptr < reloc_end) {
215 int type, size, section, offset;
220 size = * ((guint32 *) reloc_ptr)++;
225 section = *tmp_ptr++;
226 offset = *((guint32 *) tmp_ptr)++;
228 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
229 g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
230 symfile->file_name, section);
234 if (!symfile->section_offsets [section].file_offset) {
235 g_warning ("Symbol file %s contains a relocation entry for non-existing "
236 "section %d", symfile->file_name, section);
240 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
244 case MRT_target_address_size:
245 * (guint8 *) base_ptr = sizeof (void *);
247 case MRT_method_start_address: {
248 int token = *((guint32 *) tmp_ptr)++;
249 MonoDebugMethodInfo *minfo;
251 minfo = method_info_func (symfile, token, user_data);
254 * (void **) base_ptr = 0;
258 g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
260 * (void **) base_ptr = minfo->code_start;
264 case MRT_method_end_address: {
265 int token = *((guint32 *) tmp_ptr)++;
266 MonoDebugMethodInfo *minfo;
268 minfo = method_info_func (symfile, token, user_data);
271 * (void **) base_ptr = 0;
275 * (void **) base_ptr = minfo->code_start + minfo->code_size;
279 case MRT_il_offset: {
280 guint32 token = *((guint32 *) tmp_ptr)++;
281 guint32 original = *((guint32 *) tmp_ptr)++;
282 MonoDebugMethodInfo *minfo;
286 minfo = method_info_func (symfile, token, user_data);
289 * (void **) base_ptr = 0;
293 address = minfo->code_size;
295 for (i = 0; i < minfo->num_il_offsets; i++) {
296 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
298 if (il->offset >= original) {
299 address = il->address;
304 g_message ("Relocating IL offset %d in `%s' to %d (%p)",
305 original, minfo->method->name, address,
306 minfo->code_start + address);
308 * (void **) base_ptr = minfo->code_start + address;
312 case MRT_local_variable: {
313 guint32 token = *((guint32 *) tmp_ptr)++;
314 guint32 original = *((guint32 *) tmp_ptr)++;
315 MonoDebugMethodInfo *minfo;
318 minfo = method_info_func (symfile, token, user_data);
321 * (void **) base_ptr = 0;
325 if (original > minfo->num_locals) {
326 g_warning ("Symbol file %s contains relocation entry for non-existing "
327 "local variable %d, but method %s only has %d local variables.",
328 symfile->file_name, original, minfo->method->name,
333 address = minfo->local_offsets [original];
335 g_message ("Relocating local variable %d (%s) to stack offset %d",
336 original, minfo->method->name, address);
338 * (gint32 *) base_ptr = address;
342 case MRT_method_parameter: {
343 guint32 token = *((guint32 *) tmp_ptr)++;
344 guint32 original = *((guint32 *) tmp_ptr)++;
345 MonoDebugMethodInfo *minfo;
348 minfo = method_info_func (symfile, token, user_data);
351 * (void **) base_ptr = 0;
355 if (original > minfo->num_params) {
356 g_warning ("Symbol file %s contains relocation entry for non-existing "
357 "parameter %d, but method %s only has %d parameters.",
358 symfile->file_name, original, minfo->method->name,
363 address = minfo->param_offsets [original];
365 g_message ("Relocating parameter %d (%s) to stack offset %d",
366 original, minfo->method->name, address);
368 * (gint32 *) base_ptr = address;
373 g_warning ("Symbol file %s contains unknown relocation entry %d",
374 symfile->file_name, type);
379 mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
383 mono_debug_local_type_from_signature (MonoReflectionAssembly *assembly, MonoArray *signature)
392 MONO_CHECK_ARG_NULL (assembly);
393 MONO_CHECK_ARG_NULL (signature);
395 domain = mono_domain_get();
396 image = assembly->assembly->image;
398 ptr = mono_array_addr (signature, char, 0);
399 g_assert (*ptr++ == 0x07);
400 len = mono_metadata_decode_value (ptr, &ptr);
403 type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
405 klass = mono_class_from_mono_type (type);
407 mono_class_init (klass);
409 return mono_type_get_object (domain, type);
412 MonoReflectionMethod *
413 mono_debug_method_from_token (MonoReflectionAssembly *assembly, guint32 token)
419 MONO_CHECK_ARG_NULL (assembly);
421 domain = mono_domain_get();
422 image = assembly->assembly->image;
424 method = mono_get_method (image, token, NULL);
426 return mono_method_get_object (domain, method);