Mon Apr 22 19:28:14 CEST 2002 Paolo Molaro <lupus@ximian.com>
[mono.git] / mono / metadata / debug-symfile.c
1 #include <config.h>
2 #include <stdlib.h>
3 #include <string.h>
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>
9
10 #include <fcntl.h>
11 #include <unistd.h>
12
13 #ifdef HAVE_ELF_H
14 #include <elf.h>
15 #endif
16
17 /* Keep in sync with Mono.CSharp.Debugger.MonoDwarfFileWriter */
18 #define MRT_none                        0x00
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
33 #define MRT_variable_start_scope        0x0f
34 #define MRT_variable_end_scope          0x10
35 #define MRT_mono_string_fieldsize       0x11
36 #define MRT_mono_array_fieldsize        0x12
37 #define MRT_type_field_fieldsize        0x13
38
39 #define MRI_string_offset_length        0x00
40 #define MRI_string_offset_vector        0x01
41
42 #define MRI_array_offset_bounds         0x00
43 #define MRI_array_offset_max_length     0x01
44 #define MRI_array_offset_vector         0x02
45
46 #define MRI_array_bounds_offset_lower   0x00
47 #define MRI_array_bounds_offset_length  0x01
48
49 #define MRS_debug_info                  0x01
50 #define MRS_debug_abbrev                0x02
51 #define MRS_debug_line                  0x03
52 #define MRS_mono_reloc_table            0x04
53
54 #define DW_OP_const4s                   0x0d
55 #define DW_OP_plus                      0x22
56 #define DW_OP_reg0                      0x50
57 #define DW_OP_breg0                     0x70
58 #define DW_OP_fbreg                     0x91
59 #define DW_OP_piece                     0x93
60 #define DW_OP_nop                       0x96
61
62 #ifdef HAVE_ELF_H
63
64 static gboolean
65 get_sections_elf32 (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
66 {
67         Elf32_Ehdr *header;
68         Elf32_Shdr *section, *strtab_section;
69         const char *strtab;
70         int i;
71
72         header = (Elf32_Ehdr *)symfile->raw_contents;
73         if (header->e_version != EV_CURRENT) {
74                 if (emit_warnings)
75                         g_warning ("Symbol file %s has unknown ELF version %d",
76                                    symfile->file_name, header->e_version);
77                 return FALSE;
78         }
79
80         if (header->e_machine != EM_386) {
81                 if (emit_warnings)
82                         g_warning ("ELF file %s is for unknown architecture %d",
83                                    symfile->file_name, header->e_machine);
84                 return FALSE;
85         }
86
87         if (header->e_shentsize != sizeof (*section)) {
88                 if (emit_warnings)
89                         g_warning ("ELF file %s has unknown section header size "
90                                    "(expected %d, got %d)", symfile->file_name,
91                                    sizeof (*section), header->e_shentsize);
92                 return FALSE;
93         }
94
95         symfile->section_offsets = g_new0 (MonoDebugSymbolFileSection, MONO_DEBUG_SYMBOL_SECTION_MAX);
96
97         section = (Elf32_Shdr *)(symfile->raw_contents + header->e_shoff);
98         strtab_section = section + header->e_shstrndx;
99         strtab = symfile->raw_contents + strtab_section->sh_offset;
100
101         for (i = 0; i < header->e_shnum; i++, section++) {
102                 const gchar *name = strtab + section->sh_name;
103
104                 if (!strcmp (name, ".debug_info")) {
105                         MonoDebugSymbolFileSection *sfs;
106
107                         sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO];
108                         sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_INFO;
109                         sfs->file_offset = section->sh_offset;
110                         sfs->size = section->sh_size;
111                 } else if (!strcmp (name, ".debug_line")) {
112                         MonoDebugSymbolFileSection *sfs;
113
114                         sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE];
115                         sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_LINE;
116                         sfs->file_offset = section->sh_offset;
117                         sfs->size = section->sh_size;
118                 } else if (!strcmp (name, ".debug_abbrev")) {
119                         MonoDebugSymbolFileSection *sfs;
120
121                         sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV];
122                         sfs->type = MONO_DEBUG_SYMBOL_SECTION_DEBUG_ABBREV;
123                         sfs->file_offset = section->sh_offset;
124                         sfs->size = section->sh_size;
125                 } else if (!strcmp (name, ".mono_reloc_table")) {
126                         MonoDebugSymbolFileSection *sfs;
127
128                         sfs = &symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE];
129                         sfs->type = MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE;
130                         sfs->file_offset = section->sh_offset;
131                         sfs->size = section->sh_size;
132                 }
133         }
134
135         return TRUE;
136 }
137
138 #endif /* HAVE_ELF_H */
139
140 static gboolean
141 get_sections (MonoDebugSymbolFile *symfile, gboolean emit_warnings)
142 {
143 #ifdef HAVE_ELF_H
144         if (!strncmp (symfile->raw_contents, ELFMAG, strlen (ELFMAG)))
145                 return get_sections_elf32 (symfile, emit_warnings);
146 #endif
147
148         if (emit_warnings)
149                 g_warning ("Symbol file %s has unknown file format", symfile->file_name);
150
151         return FALSE;
152 }
153
154 static MonoClass *
155 mono_debug_class_get (MonoDebugSymbolFile *symfile, guint32 type_token)
156 {
157         MonoClass *klass;
158
159         if ((klass = g_hash_table_lookup (symfile->image->class_cache, GUINT_TO_POINTER (type_token))))
160                 return klass;
161
162         return NULL;
163 }
164
165 MonoDebugSymbolFile *
166 mono_debug_open_symbol_file (MonoImage *image, const char *filename, gboolean emit_warnings)
167 {
168         MonoDebugSymbolFile *symfile;
169         off_t file_size;
170         void *ptr;
171         int fd;
172
173         fd = open (filename, O_RDWR);
174         if (fd == -1) {
175                 if (emit_warnings)
176                         g_warning ("Can't open symbol file: %s", filename);
177                 return NULL;
178         }
179
180         file_size = lseek (fd, 0, SEEK_END);
181         lseek (fd, 0, SEEK_SET);
182
183         if (file_size == (off_t) -1) {
184                 if (emit_warnings)
185                         g_warning ("Can't get size of symbol file: %s", filename);
186                 return NULL;
187         }
188
189         ptr = mono_raw_buffer_load (fd, 1, 0, file_size);
190         if (!ptr) {
191                 if (emit_warnings)
192                         g_warning ("Can't read symbol file: %s", filename);
193                 return NULL;
194         }
195
196         symfile = g_new0 (MonoDebugSymbolFile, 1);
197         symfile->fd = fd;
198         symfile->file_name = g_strdup (filename);
199         symfile->image = image;
200         symfile->raw_contents = ptr;
201         symfile->raw_contents_size = file_size;
202
203         if (!get_sections (symfile, emit_warnings)) {
204                 mono_debug_close_symbol_file (symfile);
205                 return NULL;
206         }
207
208         return symfile;
209 }
210
211 void
212 mono_debug_close_symbol_file (MonoDebugSymbolFile *symfile)
213 {
214         if (!symfile)
215                 return;
216
217         if (symfile->raw_contents)
218                 mono_raw_buffer_free (symfile->raw_contents);
219         if (symfile->fd)
220                 close (symfile->fd);
221
222         g_free (symfile->file_name);
223         g_free (symfile->section_offsets);
224         g_free (symfile);
225 }
226
227 static void
228 relocate_variable (MonoDebugVarInfo *var, void *base_ptr)
229 {
230         if (!var) {
231                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
232                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
233                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
234                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
235                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
236                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
237                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
238                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
239                 return;
240         }
241                 
242         /*
243          * Update the location description for a local variable or method parameter.
244          * MCS always reserves 8 bytes for us to do this, if we don't need them all
245          * we just fill up the rest with DW_OP_nop's.
246          */
247
248         switch (var->index & MONO_DEBUG_VAR_ADDRESS_MODE_FLAGS) {
249         case MONO_DEBUG_VAR_ADDRESS_MODE_STACK:
250                 /*
251                  * Variable is on the stack.
252                  *
253                  * If `index' is zero, use the normal frame register.  Otherwise, bits
254                  * 0..4 of `index' contain the frame register.
255                  *
256                  * Both DW_OP_fbreg and DW_OP_breg0 ... DW_OP_breg31 take an ULeb128
257                  * argument - since this has an variable size, we set it to zero and
258                  * manually add a 4 byte constant using DW_OP_plus.
259                  */
260                 if (!var->index)
261                         /* Use the normal frame register (%ebp on the i386). */
262                         * ((guint8 *) base_ptr)++ = DW_OP_fbreg;
263                 else
264                         /* Use a custom frame register. */
265                         * ((guint8 *) base_ptr)++ = DW_OP_breg0 + (var->index & 0x001f);
266                 * ((guint8 *) base_ptr)++ = 0;
267                 * ((guint8 *) base_ptr)++ = DW_OP_const4s;
268                 * ((gint32 *) base_ptr)++ = var->offset;
269                 * ((guint8 *) base_ptr)++ = DW_OP_plus;
270                 break;
271
272         case MONO_DEBUG_VAR_ADDRESS_MODE_REGISTER:
273                 /*
274                  * Variable is in the register whose number is contained in bits 0..4
275                  * of `index'.
276                  *
277                  * We need to write exactly 8 bytes in this location description, so instead
278                  * of filling up the rest with DW_OP_nop's just add the `offset' even if
279                  * it's zero.
280                  */
281                 * ((guint8 *) base_ptr)++ = DW_OP_reg0 + (var->index & 0x001f);
282                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
283                 * ((guint8 *) base_ptr)++ = DW_OP_const4s;
284                 * ((gint32 *) base_ptr)++ = var->offset;
285                 * ((guint8 *) base_ptr)++ = DW_OP_plus;
286                 break;
287
288         case MONO_DEBUG_VAR_ADDRESS_MODE_TWO_REGISTERS:
289                 /*
290                  * Variable is in two registers whose numbers are in bits 0..4 and 5..9 of 
291                  * the `index' field.  Don't add `offset' since we have only two bytes left,
292                  * fill them up with DW_OP_nop's.
293                  */
294                 * ((guint8 *) base_ptr)++ = DW_OP_reg0 + (var->index & 0x001f);
295                 * ((guint8 *) base_ptr)++ = DW_OP_piece;
296                 * ((guint8 *) base_ptr)++ = sizeof (int);
297                 * ((guint8 *) base_ptr)++ = DW_OP_reg0 + ((var->index & 0x1f0) >> 5);
298                 * ((guint8 *) base_ptr)++ = DW_OP_piece;
299                 * ((guint8 *) base_ptr)++ = sizeof (int);
300                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
301                 * ((guint8 *) base_ptr)++ = DW_OP_nop;
302                 break;
303
304         default:
305                 g_assert_not_reached ();
306         }
307 }
308
309 void
310 mono_debug_update_symbol_file (MonoDebugSymbolFile *symfile,
311                                MonoDebugMethodInfoFunc method_info_func,
312                                gpointer  user_data)
313 {
314         const char *reloc_ptr, *reloc_start, *reloc_end;
315         int version, already_relocated = 0;
316         long reloc_size;
317
318         if (!symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset)
319                 return;
320
321         reloc_ptr = reloc_start = symfile->raw_contents +
322                 symfile->section_offsets [MONO_DEBUG_SYMBOL_SECTION_MONO_RELOC_TABLE].file_offset;
323
324         version = *((guint16 *) reloc_ptr)++;
325         if (version != MONO_DEBUG_SYMBOL_FILE_VERSION) {
326                 g_warning ("Symbol file %s has incorrect relocation table version "
327                            "(expected %d, got %d)", symfile->file_name,
328                            MONO_DEBUG_SYMBOL_FILE_VERSION, version);
329                 return;
330         }
331
332         already_relocated = *reloc_ptr;
333         *((char *) reloc_ptr)++ = 1;
334
335         reloc_size = *((guint32 *) reloc_ptr)++;
336         reloc_end = reloc_ptr + reloc_size;
337
338         while (reloc_ptr < reloc_end) {
339                 int type, size, section, offset;
340                 const char *tmp_ptr;
341                 char *base_ptr;
342
343                 type = *reloc_ptr++;
344                 size = * ((guint32 *) reloc_ptr)++;
345
346                 tmp_ptr = reloc_ptr;
347                 reloc_ptr += size;
348
349                 section = *tmp_ptr++;
350                 offset = *((guint32 *) tmp_ptr)++;
351
352                 if (section >= MONO_DEBUG_SYMBOL_SECTION_MAX) {
353                         g_warning ("Symbol file %s contains a relocation entry for unknown section %d",
354                                    symfile->file_name, section);
355                         continue;
356                 }
357
358                 if (!symfile->section_offsets [section].file_offset) {
359                         g_warning ("Symbol file %s contains a relocation entry for non-existing "
360                                    "section %d", symfile->file_name, section);
361                         continue;
362                 }
363
364                 base_ptr = symfile->raw_contents + symfile->section_offsets [section].file_offset;
365                 base_ptr = base_ptr + offset;
366
367                 switch (type) {
368                 case MRT_target_address_size:
369                         * (guint8 *) base_ptr = sizeof (void *);
370                         break;
371                 case MRT_method_start_address: {
372                         int token = *((guint32 *) tmp_ptr)++;
373                         MonoDebugMethodInfo *minfo;
374
375                         minfo = method_info_func (symfile, token, user_data);
376
377                         if (!minfo) {
378                                 * (void **) base_ptr = 0;
379                                 continue;
380                         }
381
382 #if 0
383                         g_message ("Start of `%s' relocated to %p", minfo->method->name, minfo->code_start);
384 #endif
385
386                         * (void **) base_ptr = minfo->code_start;
387
388                         break;
389                 }
390                 case MRT_method_end_address: {
391                         int token = *((guint32 *) tmp_ptr)++;
392                         MonoDebugMethodInfo *minfo;
393
394                         minfo = method_info_func (symfile, token, user_data);
395
396                         if (!minfo) {
397                                 * (void **) base_ptr = 0;
398                                 continue;
399                         }
400
401                         * (void **) base_ptr = (char *)minfo->code_start + minfo->code_size;
402
403                         break;
404                 }
405                 case MRT_il_offset: {
406                         guint32 token = *((guint32 *) tmp_ptr)++;
407                         guint32 original = *((guint32 *) tmp_ptr)++;
408                         MonoDebugMethodInfo *minfo;
409                         guint32 address;
410                         int i;
411
412                         minfo = method_info_func (symfile, token, user_data);
413
414                         if (!minfo) {
415                                 * (void **) base_ptr = 0;
416                                 continue;
417                         }
418
419                         address = minfo->code_size;
420
421                         for (i = 0; i < minfo->num_il_offsets; i++) {
422                                 MonoDebugILOffsetInfo *il = &minfo->il_offsets [i];
423
424                                 if (il->offset >= original) {
425                                         address = il->address;
426                                         break;
427                                 }
428                         }
429
430 #if 0
431                         g_message ("Relocating IL offset %04x in `%s' to %d (%p)",
432                                    original, minfo->method->name, address,
433                                    minfo->code_start + address);
434 #endif
435
436                         * (void **) base_ptr = minfo->code_start + address;
437
438                         break;
439                 }
440                 case MRT_local_variable: {
441                         guint32 token = *((guint32 *) tmp_ptr)++;
442                         guint32 original = *((guint32 *) tmp_ptr)++;
443                         MonoDebugMethodInfo *minfo;
444
445                         minfo = method_info_func (symfile, token, user_data);
446
447                         if (!minfo) {
448                                 relocate_variable (NULL, base_ptr);
449                                 continue;
450                         }
451
452                         if (original > minfo->num_locals) {
453                                 g_warning ("Symbol file %s contains relocation entry for non-existing "
454                                            "local variable %d, but method %s only has %d local variables.",
455                                            symfile->file_name, original, minfo->method->name,
456                                            minfo->num_locals);
457                                 continue;
458                         }
459
460                         relocate_variable (&minfo->locals [original], base_ptr);
461
462                         break;
463                 }
464                 case MRT_method_parameter: {
465                         guint32 token = *((guint32 *) tmp_ptr)++;
466                         guint32 original = *((guint32 *) tmp_ptr)++;
467                         MonoDebugMethodInfo *minfo;
468
469                         minfo = method_info_func (symfile, token, user_data);
470
471                         if (!minfo) {
472                                 relocate_variable (NULL, base_ptr);
473                                 continue;
474                         }
475
476                         if (minfo->method->signature->hasthis) {
477                                 if (original == 0) {
478                                         relocate_variable (minfo->this_var, base_ptr);
479                                         continue;
480                                 }
481
482                                 original--;
483                         }
484
485                         if (original > minfo->num_params) {
486                                 g_warning ("Symbol file %s contains relocation entry for non-existing "
487                                            "parameter %d, but method %s only has %d parameters.",
488                                            symfile->file_name, original, minfo->method->name,
489                                            minfo->num_params);
490                                 continue;
491                         }
492
493                         relocate_variable (&minfo->params [original], base_ptr);
494
495                         break;
496                 }
497                 case MRT_type_sizeof: {
498                         guint32 token = *((guint32 *) tmp_ptr)++;
499                         MonoClass *klass = mono_debug_class_get (symfile, token);
500
501                         if (!klass)
502                                 continue;
503
504                         mono_class_init (klass);
505
506                         if (klass->enumtype || klass->valuetype)
507                                 * (gint8 *) base_ptr = klass->instance_size - sizeof (MonoObject);
508                         else
509                                 * (gint8 *) base_ptr = klass->instance_size;
510
511                         break;
512                 }
513                 case MRT_type_field_offset: {
514                         guint32 token = *((guint32 *) tmp_ptr)++;
515                         guint32 original = *((guint32 *) tmp_ptr)++;
516                         MonoClass *klass = mono_debug_class_get (symfile, token);
517                         guint32 off;
518
519                         if (!klass)
520                                 continue;
521
522                         mono_class_init (klass);
523
524                         if (original > klass->field.count) {
525                                 g_warning ("Symbol file %s contains invalid field offset entry.",
526                                            symfile->file_name);
527                                 continue;
528                         }
529
530                         if (!klass->fields)
531                                 continue;
532
533                         off = klass->fields [original].offset;
534                         if (klass->byval_arg.type == MONO_TYPE_VALUETYPE)
535                                 off -= sizeof (MonoObject);
536
537 #if 0
538                         g_message ("Setting field %d of type %u to offset %d", original,
539                                    token, off);
540 #endif
541
542                         * (guint32 *) base_ptr = off;
543
544                         break;
545                 }
546                 case MRT_mono_string_sizeof:
547                         * (gint8 *) base_ptr = sizeof (MonoString);
548                         break;
549
550                 case MRT_mono_string_offset: {
551                         guint32 idx = *((guint32 *) tmp_ptr)++;
552                         MonoString string;
553                         guint32 off;
554
555                         switch (idx) {
556                         case MRI_string_offset_length:
557                                 off = (guchar *) &string.length - (guchar *) &string;
558                                 break;
559
560                         case MRI_string_offset_vector:
561                                 // fixme: don know how to fix this
562                                 g_assert_not_reached ();
563                                 //off = (guchar *) &string.c_str - (guchar *) &string;
564                                 break;
565
566                         default:
567                                 g_warning ("Symbol file %s contains invalid string offset entry",
568                                            symfile->file_name);
569                                 continue;
570                         }
571
572                         * (guint32 *) base_ptr = off;
573
574                         break;
575                 }
576                 case MRT_mono_array_sizeof:
577                         * (gint8 *) base_ptr = sizeof (MonoArray);
578                         break;
579
580                 case MRT_mono_array_offset: {
581                         guint32 idx = *((guint32 *) tmp_ptr)++;
582                         MonoArray array;
583                         guint32 off;
584
585                         switch (idx) {
586                         case MRI_array_offset_bounds:
587                                 off = (guchar *) &array.bounds - (guchar *) &array;
588                                 break;
589
590                         case MRI_array_offset_max_length:
591                                 off = (guchar *) &array.max_length - (guchar *) &array;
592                                 break;
593
594                         case MRI_array_offset_vector:
595                                 off = (guchar *) &array.vector - (guchar *) &array;
596                                 break;
597
598                         default:
599                                 g_warning ("Symbol file %s contains invalid array offset entry",
600                                            symfile->file_name);
601                                 continue;
602                         }
603
604                         * (guint32 *) base_ptr = off;
605
606                         break;
607                 }
608
609                 case MRT_mono_array_bounds_sizeof:
610                         * (gint8 *) base_ptr = sizeof (MonoArrayBounds);
611                         break;
612
613                 case MRT_mono_array_bounds_offset: {
614                         guint32 idx = *((guint32 *) tmp_ptr)++;
615                         MonoArrayBounds bounds;
616                         guint32 off;
617
618                         switch (idx) {
619                         case MRI_array_bounds_offset_lower:
620                                 off = (guchar *) &bounds.lower_bound - (guchar *) &bounds;
621                                 break;
622
623                         case MRI_array_bounds_offset_length:
624                                 off = (guchar *) &bounds.length - (guchar *) &bounds;
625                                 break;
626
627                         default:
628                                 g_warning ("Symbol file %s contains invalid array bounds offset entry",
629                                            symfile->file_name);
630                                 continue;
631                         }
632
633                         * (guint32 *) base_ptr = off;
634
635                         break;
636                 }
637
638                 case MRT_variable_start_scope:  {
639                         guint32 token = *((guint32 *) tmp_ptr)++;
640                         guint32 original = *((guint32 *) tmp_ptr)++;
641                         MonoDebugMethodInfo *minfo;
642                         gint32 address;
643
644                         minfo = method_info_func (symfile, token, user_data);
645
646                         if (!minfo) {
647                                 * (void **) base_ptr = 0;
648                                 continue;
649                         }
650
651                         if (original > minfo->num_locals) {
652                                 g_warning ("Symbol file %s contains relocation entry for non-existing "
653                                            "local variable %d, but method %s only has %d local variables.",
654                                            symfile->file_name, original, minfo->method->name,
655                                            minfo->num_locals);
656                                 continue;
657                         }
658
659                         address = minfo->locals [original].begin_scope;
660
661                         * (void **) base_ptr = minfo->code_start + address;
662
663                         break;
664                 }
665
666                 case MRT_variable_end_scope:  {
667                         guint32 token = *((guint32 *) tmp_ptr)++;
668                         guint32 original = *((guint32 *) tmp_ptr)++;
669                         MonoDebugMethodInfo *minfo;
670                         gint32 address;
671
672                         minfo = method_info_func (symfile, token, user_data);
673
674                         if (!minfo) {
675                                 * (void **) base_ptr = 0;
676                                 continue;
677                         }
678
679                         if (original > minfo->num_locals) {
680                                 g_warning ("Symbol file %s contains relocation entry for non-existing "
681                                            "local variable %d, but method %s only has %d local variables.",
682                                            symfile->file_name, original, minfo->method->name,
683                                            minfo->num_locals);
684                                 continue;
685                         }
686
687                         address = minfo->locals [original].end_scope;
688
689                         * (void **) base_ptr = minfo->code_start + address;
690
691                         break;
692                 }
693
694                 case MRT_mono_string_fieldsize: {
695                         guint32 idx = *((guint32 *) tmp_ptr)++;
696                         MonoString string;
697                         guint32 fieldsize;
698
699                         switch (idx) {
700                         case MRI_string_offset_length:
701                                 fieldsize = sizeof (string.length);
702                                 break;
703
704                         case MRI_string_offset_vector:
705                                 // fixme:
706                                 //fieldsize = sizeof (string.c_str);
707                                 g_assert_not_reached ();
708                                 break;
709
710                         default:
711                                 g_warning ("Symbol file %s contains invalid string fieldsize entry",
712                                            symfile->file_name);
713                                 continue;
714                         }
715
716                         * (guint32 *) base_ptr = fieldsize;
717
718                         break;
719                 }
720
721                 case MRT_mono_array_fieldsize: {
722                         guint32 idx = *((guint32 *) tmp_ptr)++;
723                         MonoArray array;
724                         guint32 fieldsize;
725
726                         switch (idx) {
727                         case MRI_array_offset_bounds:
728                                 fieldsize = sizeof (array.bounds);
729                                 break;
730
731                         case MRI_array_offset_max_length:
732                                 fieldsize = sizeof (array.max_length);
733                                 break;
734
735                         case MRI_array_offset_vector:
736                                 fieldsize = sizeof (array.vector);
737                                 break;
738
739                         default:
740                                 g_warning ("Symbol file %s contains invalid array fieldsize entry",
741                                            symfile->file_name);
742                                 continue;
743                         }
744
745                         * (guint32 *) base_ptr = fieldsize;
746
747                         break;
748                 }
749
750
751                 default:
752                         g_warning ("Symbol file %s contains unknown relocation entry %d",
753                                    symfile->file_name, type);
754                         break;
755                 }
756         }
757
758         mono_raw_buffer_update (symfile->raw_contents, symfile->raw_contents_size);
759 }
760
761 MonoReflectionType *
762 ves_icall_Debugger_MonoSymbolWriter_get_local_type_from_sig (MonoReflectionAssembly *assembly,
763                                                              MonoArray *signature)
764 {
765         MonoDomain *domain; 
766         MonoImage *image;
767         MonoType *type;
768         const char *ptr;
769         int len = 0;
770
771         MONO_CHECK_ARG_NULL (assembly);
772         MONO_CHECK_ARG_NULL (signature);
773
774         domain = mono_domain_get();
775         image = assembly->assembly->image;
776
777         ptr = mono_array_addr (signature, char, 0);
778         g_assert (*ptr++ == 0x07);
779         len = mono_metadata_decode_value (ptr, &ptr);
780         g_assert (len == 1);
781
782         type = mono_metadata_parse_type (image, MONO_PARSE_LOCAL, 0, ptr, &ptr);
783
784         return mono_type_get_object (domain, type);
785 }
786
787 MonoReflectionMethod *
788 ves_icall_Debugger_MonoSymbolWriter_method_from_token (MonoReflectionAssembly *assembly, guint32 token)
789 {
790         MonoDomain *domain; 
791         MonoImage *image;
792         MonoMethod *method;
793
794         MONO_CHECK_ARG_NULL (assembly);
795
796         domain = mono_domain_get();
797         image = assembly->assembly->image;
798
799         method = mono_get_method (image, token, NULL);
800
801         return mono_method_get_object (domain, method);
802 }
803
804 guint32
805 ves_icall_Debugger_DwarfFileWriter_get_type_token (MonoReflectionType *type)
806 {
807         MonoClass *klass = mono_class_from_mono_type (type->type);
808
809         mono_class_init (klass);
810
811         return klass->type_token;
812 }