3 #include <mono/metadata/metadata.h>
4 #include <mono/metadata/rawbuffer.h>
5 #include <mono/metadata/debug-symfile.h>
15 /* Keep in sync with Mono.CSharp.Debugger.MonoDwarfFileWriter */
17 #define MRT_target_address_size 0x01
18 #define MRT_il_offset 0x02
19 #define MRT_method_start_address 0x03
20 #define MRT_method_end_address 0x04
22 #define MRS_debug_info 0x01
23 #define MRS_debug_abbrev 0x02
24 #define MRS_debug_line 0x03
25 #define MRS_mono_reloc_table 0x04
30 get_sections_elf32 (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
33 Elf32_Shdr *section, *strtab_section;
37 header = symfile->raw_contents;
38 if (header->e_version != EV_CURRENT) {
40 g_warning ("Symbol file %s has unknown ELF version %d",
41 symfile->file_name, header->e_version);
45 if (header->e_machine != EM_386) {
47 g_warning ("ELF file %s is for unknown architecture %d",
48 symfile->file_name, header->e_machine);
52 if (header->e_shentsize != sizeof (*section)) {
54 g_warning ("ELF file %s has unknown section header size "
55 "(expected %d, got %d)", symfile->file_name,
56 sizeof (*section), header->e_shentsize);
60 symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
62 section = symfile->raw_contents + header->e_shoff;
63 strtab_section = section + header->e_shstrndx;
64 strtab = symfile->raw_contents + strtab_section->sh_offset;
66 for (i = 0; i < header->e_shnum; i++, section++) {
67 const gchar *name = strtab + section->sh_name;
69 if (!strcmp (name, ".debug_info")) {
70 MonoDebugSymbolFileSection *sfs;
72 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO];
73 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO;
74 sfs->file_offset = section->sh_offset;
75 sfs->size = section->sh_size;
76 } else if (!strcmp (name, ".debug_line")) {
77 MonoDebugSymbolFileSection *sfs;
79 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE];
80 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE;
81 sfs->file_offset = section->sh_offset;
82 sfs->size = section->sh_size;
83 } else if (!strcmp (name, ".debug_abbrev")) {
84 MonoDebugSymbolFileSection *sfs;
86 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV];
87 sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV;
88 sfs->file_offset = section->sh_offset;
89 sfs->size = section->sh_size;
90 } else if (!strcmp (name, ".mono_reloc_table")) {
91 MonoDebugSymbolFileSection *sfs;
93 sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE];
94 sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
95 sfs->file_offset = section->sh_offset;
96 sfs->size = section->sh_size;
103 #endif /* HAVE_ELF_H */
106 get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
109 if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
110 return get_sections_elf32 (symfile, emit_warnings);
114 g_warning ("Symbol file %s has unknown file format", symfile->file_name);
119 MonoDebugSymbolFile *
120 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
122 MonoDebugSymbolFile *symfile;
127 fd = open (filename, O_RDWR);
130 g_warning ("Can't open symbol file: %s", filename);
134 file_size = lseek (fd, 0, SEEK_END);
135 lseek (fd, 0, SEEK_SET);
137 if (file_size == (off_t) -1) {
139 g_warning ("Can't get size of symbol file: %s", filename);
143 ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
146 g_warning ("Can't read symbol file: %s", filename);
150 symfile = g_new0 (MonoDebugSymbolFile, 1);
152 symfile->file_name = g_strdup (filename);
153 symfile->image = image;
154 symfile->raw_contents = ptr;
156 if (!get_sections (symfile, emit_warnings)) {
157 mono_debug_close_symbol_file (symfile);
165 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
170 if (symfile->raw_contents)
171 mono_raw_buffer_free (symfile->raw_contents);
175 g_free (symfile->file_name);
176 g_free (symfile->section_offsets);
181 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
182 MonoDebugMethodInfoFunc method_info_func,
185 const char *reloc_ptr, *reloc_start, *reloc_end;
186 int version, already_relocated = 0;
189 if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
192 reloc_ptr = reloc_start = symfile->raw_contents +
193 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
195 version = *((guint16 *) reloc_ptr)++;
196 if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
197 g_warning ("Symbol file %s has incorrect relocation table version "
198 "(expected %d, got %d)", symfile->file_name,
199 MONO_DEBUG_SYMBOL_FILE_VERSION, version);
203 already_relocated = *reloc_ptr;
204 *((char *) reloc_ptr)++ = 1;
206 reloc_size = *((guint32 *) reloc_ptr)++;
207 reloc_end = reloc_ptr + reloc_size;
209 while (reloc_ptr < reloc_end) {
210 int type, size, section, offset;
215 size = * ((guint32 *) reloc_ptr)++;
220 section = *tmp_ptr++;
221 offset = *((guint32 *) tmp_ptr)++;
223 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
224 g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
225 symfile->file_name, section);
229 if (!symfile->section_offsets [section].file_offset) {
230 g_warning ("Symbol file %s contains a relocation entry for non-existing "
231 "section %d", symfile->file_name, section);
235 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
239 case MRT_target_address_size:
240 * (guint8 *) base_ptr = sizeof (void *);
242 case MRT_method_start_address: {
243 int token = *((guint32 *) tmp_ptr)++;
244 MonoDebugMethodInfo *minfo;
246 minfo = method_info_func (symfile, token, user_data);
249 * (void **) base_ptr = 0;
253 g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
255 * (void **) base_ptr = minfo->code_start;
259 case MRT_method_end_address: {
260 int token = *((guint32 *) tmp_ptr)++;
261 MonoDebugMethodInfo *minfo;
263 minfo = method_info_func (symfile, token, user_data);
266 * (void **) base_ptr = 0;
270 * (void **) base_ptr = minfo->code_start + minfo->code_size;
274 case MRT_il_offset: {
275 guint32 token = *((guint32 *) tmp_ptr)++;
276 guint32 original = *((guint32 *) tmp_ptr)++;
277 MonoDebugMethodInfo *minfo;
281 minfo = method_info_func (symfile, token, user_data);
284 * (void **) base_ptr = 0;
288 address = minfo->code_size;
290 for (i = 0; i < minfo->num_il_offsets; i++) {
291 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
293 if (il->offset >= original) {
294 address = il->address;
299 g_message ("Relocating IL offset %d in `%s' to %d (%p)",
300 original, minfo->method->name, address,
301 minfo->code_start + address);
303 * (void **) base_ptr = minfo->code_start + address;
308 g_warning ("Symbol file %s contains unknown relocation entry %d",
309 symfile->file_name, type);