2009-04-05 Zoltan Varga <vargaz@gmail.com>
[mono.git] / mono / mini / dwarfwriter.c
1 /*
2  * dwarfwriter.c: Creation of DWARF debug information
3  *
4  * Author:
5  *   Zoltan Varga (vargaz@gmail.com)
6  *
7  * (C) 2008-2009 Novell, Inc.
8  */
9
10 #include "config.h"
11 #include "dwarfwriter.h"
12
13 #include <sys/types.h>
14 #include <ctype.h>
15 #include <string.h>
16 #ifdef HAVE_STDINT_H
17 #include <stdint.h>
18 #endif
19
20 #include <mono/metadata/mono-endian.h>
21 #include <mono/metadata/debug-mono-symfile.h>
22 #include <mono/utils/mono-compiler.h>
23
24 #ifndef PLATFORM_WIN32
25 #include <mono/utils/freebsd-elf32.h>
26 #include <mono/utils/freebsd-elf64.h>
27 #endif
28
29 #include <mono/utils/freebsd-dwarf.h>
30
31 struct _MonoDwarfWriter
32 {
33         MonoImageWriter *w;
34         GHashTable *class_to_die, *class_to_vtype_die, *class_to_pointer_die;
35         int fde_index, tdie_index, line_number_file_index, line_number_dir_index;
36         GHashTable *file_to_index, *dir_to_index;
37         FILE *il_file;
38         int il_file_line_index, loclist_index;
39         GSList *cie_program;
40 };
41
42 /*
43  * mono_dwarf_writer_create:
44  *
45  *   Create a DWARF writer object. WRITER is the underlying image writer this 
46  * writer will emit to. IL_FILE is the file where IL code will be dumped to for
47  * methods which have no line number info. It can be NULL.
48  */
49 MonoDwarfWriter*
50 mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file)
51 {
52         MonoDwarfWriter *w = g_new0 (MonoDwarfWriter, 1);
53         
54         w->w = writer;
55         w->il_file = il_file;
56
57         return w;
58 }
59
60 void
61 mono_dwarf_writer_destroy (MonoDwarfWriter *w)
62 {
63         g_free (w);
64 }
65
66 /* Wrappers around the image writer functions */
67
68 static inline void
69 emit_section_change (MonoDwarfWriter *w, const char *section_name, int subsection_index)
70 {
71         img_writer_emit_section_change (w->w, section_name, subsection_index);
72 }
73
74 static inline void
75 emit_push_section (MonoDwarfWriter *w, const char *section_name, int subsection)
76 {
77         img_writer_emit_push_section (w->w, section_name, subsection);
78 }
79
80 static inline void
81 emit_pop_section (MonoDwarfWriter *w)
82 {
83         img_writer_emit_pop_section (w->w);
84 }
85
86 static inline void
87 emit_local_symbol (MonoDwarfWriter *w, const char *name, const char *end_label, gboolean func) 
88
89         img_writer_emit_local_symbol (w->w, name, end_label, func); 
90 }
91
92 static inline void
93 emit_label (MonoDwarfWriter *w, const char *name) 
94
95         img_writer_emit_label (w->w, name); 
96 }
97
98 static inline void
99 emit_bytes (MonoDwarfWriter *w, const guint8* buf, int size) 
100
101         img_writer_emit_bytes (w->w, buf, size); 
102 }
103
104 static inline void
105 emit_string (MonoDwarfWriter *w, const char *value) 
106
107         img_writer_emit_string (w->w, value); 
108 }
109
110 static inline void
111 emit_line (MonoDwarfWriter *w) 
112
113         img_writer_emit_line (w->w); 
114 }
115
116 static inline void
117 emit_alignment (MonoDwarfWriter *w, int size) 
118
119         img_writer_emit_alignment (w->w, size); 
120 }
121
122 static inline void
123 emit_pointer_unaligned (MonoDwarfWriter *w, const char *target) 
124
125         img_writer_emit_pointer_unaligned (w->w, target); 
126 }
127
128 static inline void
129 emit_pointer (MonoDwarfWriter *w, const char *target) 
130
131         img_writer_emit_pointer (w->w, target); 
132 }
133
134 static inline void
135 emit_int16 (MonoDwarfWriter *w, int value) 
136
137         img_writer_emit_int16 (w->w, value); 
138 }
139
140 static inline void
141 emit_int32 (MonoDwarfWriter *w, int value) 
142
143         img_writer_emit_int32 (w->w, value); 
144 }
145
146 static inline void
147 emit_symbol_diff (MonoDwarfWriter *w, const char *end, const char* start, int offset) 
148
149         img_writer_emit_symbol_diff (w->w, end, start, offset); 
150 }
151
152 static inline void
153 emit_zero_bytes (MonoDwarfWriter *w, int num) 
154
155         img_writer_emit_zero_bytes (w->w, num); 
156 }
157
158 static inline void
159 emit_byte (MonoDwarfWriter *w, guint8 val) 
160
161         img_writer_emit_byte (w->w, val); 
162 }
163
164 static G_GNUC_UNUSED void
165 emit_uleb128 (MonoDwarfWriter *w, guint32 value)
166 {
167         do {
168                 guint8 b = value & 0x7f;
169                 value >>= 7;
170                 if (value != 0) /* more bytes to come */
171                         b |= 0x80;
172                 emit_byte (w, b);
173         } while (value);
174 }
175
176 static G_GNUC_UNUSED void
177 emit_sleb128 (MonoDwarfWriter *w, gint64 value)
178 {
179         gboolean more = 1;
180         gboolean negative = (value < 0);
181         guint32 size = 64;
182         guint8 byte;
183
184         while (more) {
185                 byte = value & 0x7f;
186                 value >>= 7;
187                 /* the following is unnecessary if the
188                  * implementation of >>= uses an arithmetic rather
189                  * than logical shift for a signed left operand
190                  */
191                 if (negative)
192                         /* sign extend */
193                         value |= - ((gint64)1 <<(size - 7));
194                 /* sign bit of byte is second high order bit (0x40) */
195                 if ((value == 0 && !(byte & 0x40)) ||
196                         (value == -1 && (byte & 0x40)))
197                         more = 0;
198                 else
199                         byte |= 0x80;
200                 emit_byte (w, byte);
201         }
202 }
203
204 static G_GNUC_UNUSED void
205 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
206 {
207         guint8 *p = buf;
208
209         do {
210                 guint8 b = value & 0x7f;
211                 value >>= 7;
212                 if (value != 0) /* more bytes to come */
213                         b |= 0x80;
214                 *p ++ = b;
215         } while (value);
216
217         *endbuf = p;
218 }
219
220 static G_GNUC_UNUSED void
221 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
222 {
223         gboolean more = 1;
224         gboolean negative = (value < 0);
225         guint32 size = 32;
226         guint8 byte;
227         guint8 *p = buf;
228
229         while (more) {
230                 byte = value & 0x7f;
231                 value >>= 7;
232                 /* the following is unnecessary if the
233                  * implementation of >>= uses an arithmetic rather
234                  * than logical shift for a signed left operand
235                  */
236                 if (negative)
237                         /* sign extend */
238                         value |= - (1 <<(size - 7));
239                 /* sign bit of byte is second high order bit (0x40) */
240                 if ((value == 0 && !(byte & 0x40)) ||
241                         (value == -1 && (byte & 0x40)))
242                         more = 0;
243                 else
244                         byte |= 0x80;
245                 *p ++= byte;
246         }
247
248         *endbuf = p;
249 }
250
251 static void
252 emit_dwarf_abbrev (MonoDwarfWriter *w, int code, int tag, gboolean has_child,
253                                    int *attrs, int attrs_len)
254 {
255         int i;
256
257         emit_uleb128 (w, code);
258         emit_uleb128 (w, tag);
259         emit_byte (w, has_child);
260
261         for (i = 0; i < attrs_len; i++)
262                 emit_uleb128 (w, attrs [i]);
263         emit_uleb128 (w, 0);
264         emit_uleb128 (w, 0);
265 }
266
267 static void
268 emit_cie (MonoDwarfWriter *w)
269 {
270         emit_section_change (w, ".debug_frame", 0);
271
272         emit_alignment (w, 8);
273
274         /* Emit a CIE */
275         emit_symbol_diff (w, ".Lcie0_end", ".", -4); /* length */
276         emit_int32 (w, 0xffffffff); /* CIE id */
277         emit_byte (w, 3); /* version */
278         emit_string (w, ""); /* augmention */
279         emit_sleb128 (w, 1); /* code alignment factor */
280         emit_sleb128 (w, mono_unwind_get_dwarf_data_align ()); /* data alignment factor */
281         emit_uleb128 (w, mono_unwind_get_dwarf_pc_reg ());
282
283         w->cie_program = w->cie_program;
284         if (w->cie_program) {
285                 guint32 uw_info_len;
286                 guint8 *uw_info = mono_unwind_ops_encode (w->cie_program, &uw_info_len);
287                 emit_bytes (w, uw_info, uw_info_len);
288                 g_free (uw_info);
289         }
290
291         emit_alignment (w, sizeof (gpointer));
292         emit_label (w, ".Lcie0_end");
293 }
294
295 static void
296 emit_pointer_value (MonoDwarfWriter *w, gpointer ptr)
297 {
298         gssize val = (gssize)ptr;
299         emit_bytes (w, (guint8*)&val, sizeof (gpointer));
300 }
301
302 static void
303 emit_fde (MonoDwarfWriter *w, int fde_index, char *start_symbol, char *end_symbol,
304                   guint8 *code, guint32 code_size, GSList *unwind_ops, gboolean use_cie)
305 {
306         char symbol [128];
307         GSList *l;
308         guint8 *uw_info;
309         guint32 uw_info_len;
310
311         emit_section_change (w, ".debug_frame", 0);
312
313         sprintf (symbol, ".Lfde%d_end", fde_index);
314         emit_symbol_diff (w, symbol, ".", -4); /* length */
315         emit_int32 (w, 0); /* CIE_pointer */
316         if (start_symbol) {
317                 emit_pointer (w, start_symbol); /* initial_location */
318                 if (end_symbol)
319                         emit_symbol_diff (w, end_symbol, start_symbol, 0); /* address_range */
320                 else {
321                         g_assert (code_size);
322                         emit_int32 (w, code_size);
323                 }
324         } else {
325                 emit_pointer_value (w, code);
326                 emit_int32 (w, code_size);
327         }
328 #if SIZEOF_VOID_P == 8
329         /* Upper 32 bits of code size */
330         emit_int32 (w, 0);
331 #endif
332
333         l = unwind_ops;
334         if (w->cie_program) {
335                 // FIXME: Check that the ops really begin with the CIE program */
336                 int i;
337
338                 for (i = 0; i < g_slist_length (w->cie_program); ++i)
339                         l = l->next;
340         }
341
342         /* Convert the list of MonoUnwindOps to the format used by DWARF */     
343         uw_info = mono_unwind_ops_encode (l, &uw_info_len);
344         emit_bytes (w, uw_info, uw_info_len);
345         g_free (uw_info);
346
347         emit_alignment (w, sizeof (gpointer));
348         sprintf (symbol, ".Lfde%d_end", fde_index);
349         emit_label (w, symbol);
350 }
351
352 /* Abbrevations */
353 #define ABBREV_COMPILE_UNIT 1
354 #define ABBREV_SUBPROGRAM 2
355 #define ABBREV_PARAM 3
356 #define ABBREV_BASE_TYPE 4
357 #define ABBREV_STRUCT_TYPE 5
358 #define ABBREV_DATA_MEMBER 6
359 #define ABBREV_TYPEDEF 7
360 #define ABBREV_ENUM_TYPE 8
361 #define ABBREV_ENUMERATOR 9
362 #define ABBREV_NAMESPACE 10
363 #define ABBREV_VARIABLE 11
364 #define ABBREV_VARIABLE_LOCLIST 12
365 #define ABBREV_POINTER_TYPE 13
366 #define ABBREV_PARAM_LOCLIST 14
367
368 static int compile_unit_attr [] = {
369         DW_AT_producer     ,DW_FORM_string,
370     DW_AT_name         ,DW_FORM_string,
371     DW_AT_comp_dir     ,DW_FORM_string,
372         DW_AT_language     ,DW_FORM_data1,
373     DW_AT_low_pc       ,DW_FORM_addr,
374     DW_AT_high_pc      ,DW_FORM_addr,
375         DW_AT_stmt_list    ,DW_FORM_data4
376 };
377
378 static int subprogram_attr [] = {
379         DW_AT_name         , DW_FORM_string,
380     DW_AT_low_pc       , DW_FORM_addr,
381     DW_AT_high_pc      , DW_FORM_addr,
382         DW_AT_frame_base   , DW_FORM_block1
383 };
384
385 static int param_attr [] = {
386         DW_AT_name,     DW_FORM_string,
387         DW_AT_type,     DW_FORM_ref4,
388         DW_AT_location, DW_FORM_block1
389 };
390
391 static int param_loclist_attr [] = {
392         DW_AT_name,     DW_FORM_string,
393         DW_AT_type,     DW_FORM_ref4,
394         DW_AT_location, DW_FORM_data4
395 };
396
397 static int base_type_attr [] = {
398         DW_AT_byte_size,   DW_FORM_data1,
399         DW_AT_encoding,    DW_FORM_data1,
400         DW_AT_name,        DW_FORM_string
401 };
402
403 static int struct_type_attr [] = {
404         DW_AT_name,        DW_FORM_string,
405         DW_AT_byte_size,   DW_FORM_udata,
406 };
407
408 static int data_member_attr [] = {
409         DW_AT_name,        DW_FORM_string,
410         DW_AT_type,        DW_FORM_ref4,
411         DW_AT_data_member_location, DW_FORM_block1
412 };
413
414 static int typedef_attr [] = {
415         DW_AT_name,        DW_FORM_string,
416         DW_AT_type,        DW_FORM_ref4
417 };
418
419 static int pointer_type_attr [] = {
420         DW_AT_type,        DW_FORM_ref4,
421 };
422
423 static int enum_type_attr [] = {
424         DW_AT_name,        DW_FORM_string,
425         DW_AT_byte_size,   DW_FORM_udata,
426         DW_AT_type,        DW_FORM_ref4,
427 };
428
429 static int enumerator_attr [] = {
430         DW_AT_name,        DW_FORM_string,
431         DW_AT_const_value, DW_FORM_sdata,
432 };
433
434 static int namespace_attr [] = {
435         DW_AT_name,        DW_FORM_string,
436 };
437
438 static int variable_attr [] = {
439         DW_AT_name,     DW_FORM_string,
440         DW_AT_type,     DW_FORM_ref4,
441         DW_AT_location, DW_FORM_block1
442 };
443
444 static int variable_loclist_attr [] = {
445         DW_AT_name,     DW_FORM_string,
446         DW_AT_type,     DW_FORM_ref4,
447         DW_AT_location, DW_FORM_data4
448 };
449
450 typedef struct DwarfBasicType {
451         const char *die_name, *name;
452         int type;
453         int size;
454         int encoding;
455 } DwarfBasicType;
456
457 static DwarfBasicType basic_types [] = {
458         { ".LDIE_I1", "sbyte", MONO_TYPE_I1, 1, DW_ATE_signed },
459         { ".LDIE_U1", "byte", MONO_TYPE_U1, 1, DW_ATE_unsigned },
460         { ".LDIE_I2", "short", MONO_TYPE_I2, 2, DW_ATE_signed },
461         { ".LDIE_U2", "ushort", MONO_TYPE_U2, 2, DW_ATE_unsigned },
462         { ".LDIE_I4", "int", MONO_TYPE_I4, 4, DW_ATE_signed },
463         { ".LDIE_U4", "uint", MONO_TYPE_U4, 4, DW_ATE_unsigned },
464         { ".LDIE_I8", "long", MONO_TYPE_I8, 8, DW_ATE_signed },
465         { ".LDIE_U8", "ulong", MONO_TYPE_U8, 8, DW_ATE_unsigned },
466         { ".LDIE_I", "intptr", MONO_TYPE_I, SIZEOF_VOID_P, DW_ATE_signed },
467         { ".LDIE_U", "uintptr", MONO_TYPE_U, SIZEOF_VOID_P, DW_ATE_unsigned },
468         { ".LDIE_R4", "float", MONO_TYPE_R4, 4, DW_ATE_float },
469         { ".LDIE_R8", "double", MONO_TYPE_R8, 8, DW_ATE_float },
470         { ".LDIE_BOOLEAN", "boolean", MONO_TYPE_BOOLEAN, 1, DW_ATE_boolean },
471         { ".LDIE_CHAR", "char", MONO_TYPE_CHAR, 2, DW_ATE_unsigned_char },
472         { ".LDIE_STRING", "string", MONO_TYPE_STRING, sizeof (gpointer), DW_ATE_address },
473         { ".LDIE_OBJECT", "object", MONO_TYPE_OBJECT, sizeof (gpointer), DW_ATE_address },
474         { ".LDIE_SZARRAY", "object", MONO_TYPE_SZARRAY, sizeof (gpointer), DW_ATE_address },
475 };
476
477 /* Constants for encoding line number special opcodes */
478 #define OPCODE_BASE 13
479 #define LINE_BASE -5
480 #define LINE_RANGE 14
481
482 /* Subsections of the .debug_line section */
483 #define LINE_SUBSECTION_HEADER 1
484 #define LINE_SUBSECTION_INCLUDES 2
485 #define LINE_SUBSECTION_FILES 3
486 #define LINE_SUBSECTION_DATA 4
487 #define LINE_SUBSECTION_END 5
488
489 static int
490 emit_line_number_file_name (MonoDwarfWriter *w, const char *name,
491                                                         gint64 last_mod_time, gint64 file_size)
492 {
493         int index;
494         int dir_index;
495         char *basename = NULL;
496
497         if (!w->file_to_index)
498                 w->file_to_index = g_hash_table_new (g_str_hash, g_str_equal);
499
500         index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name));
501         if (index > 0)
502                 return index;
503
504         if (g_path_is_absolute (name)) {
505                 char *dir = g_path_get_dirname (name);
506
507                 if (!w->dir_to_index)
508                         w->dir_to_index = g_hash_table_new (g_str_hash, g_str_equal);
509
510                 dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (w->dir_to_index, dir));
511                 if (dir_index == 0) {
512                         emit_section_change (w, ".debug_line", LINE_SUBSECTION_INCLUDES);
513                         emit_string (w, dir);
514
515                         dir_index = ++ w->line_number_dir_index;
516                         g_hash_table_insert (w->dir_to_index, g_strdup (dir), GUINT_TO_POINTER (dir_index));
517                 }
518
519                 g_free (dir);
520
521                 basename = g_path_get_basename (name);
522         } else {
523                 dir_index = 0;
524         }
525
526         emit_section_change (w, ".debug_line", LINE_SUBSECTION_FILES);
527
528         if (basename)
529                 emit_string (w, basename);
530         else
531                 emit_string (w, name);
532         emit_uleb128 (w, dir_index);
533         emit_byte (w, 0);
534         emit_byte (w, 0);
535
536         emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
537
538         if (basename)
539                 g_free (basename);
540
541         index = ++ w->line_number_file_index;
542         g_hash_table_insert (w->file_to_index, g_strdup (name), GUINT_TO_POINTER (index));
543
544         return index;
545 }
546
547 static void
548 emit_line_number_info_begin (MonoDwarfWriter *w)
549 {
550         if (!w->il_file) {
551                 /* FIXME: This doesn't seem to work with !xdebug */
552                 emit_section_change (w, ".debug_line", 0);
553                 emit_label (w, ".Ldebug_line_start");
554                 emit_label (w, ".Ldebug_line_section_start");
555                 return;
556         }
557
558         /* Line number info header */
559         /* 
560          * GAS seems to emit its own data to the end of the first subsection, so we use
561          * subsections 1, 2 etc:
562          * 1 - contains the header
563          * 2 - contains the file names
564          * 3 - contains the end of the header + the data
565          * 4 - the end symbol
566          */
567         emit_section_change (w, ".debug_line", 0);
568         emit_label (w, ".Ldebug_line_section_start");
569         emit_section_change (w, ".debug_line", LINE_SUBSECTION_HEADER);
570         emit_label (w, ".Ldebug_line_start");
571         emit_symbol_diff (w, ".Ldebug_line_end", ".", -4); /* length */
572         emit_int16 (w, 0x2); /* version */
573         emit_symbol_diff (w, ".Ldebug_line_header_end", ".", -4); /* header_length */
574         emit_byte (w, 1); /* minimum_instruction_length */
575         emit_byte (w, 1); /* default_is_stmt */
576         emit_byte (w, LINE_BASE); /* line_base */
577         emit_byte (w, LINE_RANGE); /* line_range */
578         emit_byte (w, OPCODE_BASE); /* opcode_base */
579         emit_byte (w, 0); /* standard_opcode_lengths */
580         emit_byte (w, 1);
581         emit_byte (w, 1);
582         emit_byte (w, 1);
583         emit_byte (w, 1);
584         emit_byte (w, 0);
585         emit_byte (w, 0);
586         emit_byte (w, 0);
587         emit_byte (w, 1);
588         emit_byte (w, 0);
589         emit_byte (w, 0);
590         emit_byte (w, 1);
591
592         /* Includes */
593         emit_section_change (w, ".debug_line", LINE_SUBSECTION_INCLUDES);
594
595         /* End of Includes */
596         emit_section_change (w, ".debug_line", LINE_SUBSECTION_FILES);
597         emit_byte (w, 0);
598
599         /* Files */
600         emit_line_number_file_name (w, "xdb.il", 0, 0);
601
602         /* End of Files */
603         emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
604         emit_byte (w, 0);
605
606         emit_label (w, ".Ldebug_line_header_end");
607
608         /* Emit this into a separate subsection so it gets placed at the end */ 
609         emit_section_change (w, ".debug_line", LINE_SUBSECTION_END);
610
611         emit_byte (w, 0);
612         emit_byte (w, 1);
613         emit_byte (w, DW_LNE_end_sequence);
614
615         emit_label (w, ".Ldebug_line_end");
616 }
617
618 void
619 mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, GSList *base_unwind_program)
620 {
621         char *s, *build_info;
622         int i;
623
624         w->cie_program = base_unwind_program;
625
626         emit_section_change (w, ".debug_abbrev", 0);
627         emit_dwarf_abbrev (w, ABBREV_COMPILE_UNIT, DW_TAG_compile_unit, TRUE, 
628                                            compile_unit_attr, G_N_ELEMENTS (compile_unit_attr));
629         emit_dwarf_abbrev (w, ABBREV_SUBPROGRAM, DW_TAG_subprogram, TRUE, 
630                                            subprogram_attr, G_N_ELEMENTS (subprogram_attr));
631         emit_dwarf_abbrev (w, ABBREV_PARAM, DW_TAG_formal_parameter, FALSE, 
632                                            param_attr, G_N_ELEMENTS (param_attr));
633         emit_dwarf_abbrev (w, ABBREV_PARAM_LOCLIST, DW_TAG_formal_parameter, FALSE, 
634                                            param_loclist_attr, G_N_ELEMENTS (param_loclist_attr));
635         emit_dwarf_abbrev (w, ABBREV_BASE_TYPE, DW_TAG_base_type, FALSE, 
636                                            base_type_attr, G_N_ELEMENTS (base_type_attr));
637         emit_dwarf_abbrev (w, ABBREV_STRUCT_TYPE, DW_TAG_class_type, TRUE, 
638                                            struct_type_attr, G_N_ELEMENTS (struct_type_attr));
639         emit_dwarf_abbrev (w, ABBREV_DATA_MEMBER, DW_TAG_member, FALSE, 
640                                            data_member_attr, G_N_ELEMENTS (data_member_attr));
641         emit_dwarf_abbrev (w, ABBREV_TYPEDEF, DW_TAG_typedef, FALSE, 
642                                            typedef_attr, G_N_ELEMENTS (typedef_attr));
643         emit_dwarf_abbrev (w, ABBREV_ENUM_TYPE, DW_TAG_enumeration_type, TRUE,
644                                            enum_type_attr, G_N_ELEMENTS (enum_type_attr));
645         emit_dwarf_abbrev (w, ABBREV_ENUMERATOR, DW_TAG_enumerator, FALSE,
646                                            enumerator_attr, G_N_ELEMENTS (enumerator_attr));
647         emit_dwarf_abbrev (w, ABBREV_NAMESPACE, DW_TAG_namespace, TRUE,
648                                            namespace_attr, G_N_ELEMENTS (namespace_attr));
649         emit_dwarf_abbrev (w, ABBREV_VARIABLE, DW_TAG_variable, FALSE,
650                                            variable_attr, G_N_ELEMENTS (variable_attr));
651         emit_dwarf_abbrev (w, ABBREV_VARIABLE_LOCLIST, DW_TAG_variable, FALSE,
652                                            variable_loclist_attr, G_N_ELEMENTS (variable_loclist_attr));
653         emit_dwarf_abbrev (w, ABBREV_POINTER_TYPE, DW_TAG_pointer_type, FALSE,
654                                            pointer_type_attr, G_N_ELEMENTS (pointer_type_attr));
655         emit_byte (w, 0);
656
657         emit_section_change (w, ".debug_info", 0);
658         emit_label (w, ".Ldebug_info_start");
659         emit_symbol_diff (w, ".Ldebug_info_end", ".", -4); /* length */
660         emit_int16 (w, 0x2); /* DWARF version 2 */
661         emit_int32 (w, 0); /* .debug_abbrev offset */
662         emit_byte (w, sizeof (gpointer)); /* address size */
663
664         /* Emit this into a separate section so it gets placed at the end */
665         emit_section_change (w, ".debug_info", 1);
666         emit_int32 (w, 0); /* close everything */
667         emit_label (w, ".Ldebug_info_end");
668         emit_section_change (w, ".debug_info", 0);
669
670         /* Compilation unit */
671         emit_uleb128 (w, ABBREV_COMPILE_UNIT);
672         build_info = mono_get_runtime_build_info ();
673         s = g_strdup_printf ("Mono AOT Compiler %s", build_info);
674         emit_string (w, s);
675         g_free (build_info);
676         g_free (s);
677         emit_string (w, "JITted code");
678         emit_string (w, "");
679         emit_byte (w, DW_LANG_C);
680         emit_pointer_value (w, 0);
681         emit_pointer_value (w, 0);
682         /* offset into .debug_line section */
683         emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
684
685         /* Base types */
686         for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
687                 emit_label (w, basic_types [i].die_name);
688                 emit_uleb128 (w, ABBREV_BASE_TYPE);
689                 emit_byte (w, basic_types [i].size);
690                 emit_byte (w, basic_types [i].encoding);
691                 emit_string (w, basic_types [i].name);
692         }
693
694         /* debug_loc section */
695         emit_section_change (w, ".debug_loc", 0);
696         emit_label (w, ".Ldebug_loc_start");
697
698         /* debug_line section */
699         emit_line_number_info_begin (w);
700
701         emit_cie (w);
702 }
703
704 /* Returns the local symbol pointing to the emitted debug info */
705 static char*
706 emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype)
707 {
708         char *die, *pointer_die;
709         char *full_name;
710         gpointer iter;
711         MonoClassField *field;
712         const char *fdie;
713         int k;
714         gboolean emit_namespace = FALSE;
715         GHashTable *cache;
716
717         // FIXME: Appdomains
718         if (!w->class_to_die)
719                 w->class_to_die = g_hash_table_new (NULL, NULL);
720         if (!w->class_to_vtype_die)
721                 w->class_to_vtype_die = g_hash_table_new (NULL, NULL);
722         if (!w->class_to_pointer_die)
723                 w->class_to_pointer_die = g_hash_table_new (NULL, NULL);
724
725         if (vtype)
726                 cache = w->class_to_vtype_die;
727         else
728                 cache = w->class_to_die;
729
730         die = g_hash_table_lookup (cache, klass);
731         if (die)
732                 return die;
733
734         if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype)))
735                 return NULL;
736
737         /*
738          * FIXME: gdb can't handle namespaces in languages it doesn't know about.
739          */
740         /*
741         if (klass->name_space && klass->name_space [0] != '\0')
742                 emit_namespace = TRUE;
743         */
744         if (emit_namespace) {
745                 emit_uleb128 (w, ABBREV_NAMESPACE);
746                 emit_string (w, klass->name_space);
747         }
748
749         full_name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space ? "." : "", klass->name);
750
751         die = g_strdup_printf (".LTDIE_%d", w->tdie_index);
752         emit_label (w, die);
753
754         if (klass->enumtype) {
755                 int size = mono_class_value_size (mono_class_from_mono_type (mono_class_enum_basetype (klass)), NULL);
756
757                 emit_uleb128 (w, ABBREV_ENUM_TYPE);
758                 emit_string (w, full_name);
759                 emit_uleb128 (w, size);
760                 for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
761                         if (basic_types [k].type == mono_class_enum_basetype (klass)->type)
762                                 break;
763                 g_assert (k < G_N_ELEMENTS (basic_types));
764                 emit_symbol_diff (w, basic_types [k].die_name, ".Ldebug_info_start", 0);
765
766                 /* Emit enum values */
767                 iter = NULL;
768                 while ((field = mono_class_get_fields (klass, &iter))) {
769                         const char *p;
770                         int len;
771                         MonoTypeEnum def_type;
772
773                         if (strcmp ("value__", mono_field_get_name (field)) == 0)
774                                 continue;
775                         if (mono_field_is_deleted (field))
776                                 continue;
777
778                         emit_uleb128 (w, ABBREV_ENUMERATOR);
779                         emit_string (w, mono_field_get_name (field));
780
781                         p = mono_class_get_field_default_value (field, &def_type);
782                         len = mono_metadata_decode_blob_size (p, &p);
783                         switch (mono_class_enum_basetype (klass)->type) {
784                         case MONO_TYPE_U1:
785                         case MONO_TYPE_I1:
786                         case MONO_TYPE_BOOLEAN:
787                                 emit_sleb128 (w, *p);
788                                 break;
789                         case MONO_TYPE_U2:
790                         case MONO_TYPE_I2:
791                         case MONO_TYPE_CHAR:
792                                 emit_sleb128 (w, read16 (p));
793                                 break;
794                         case MONO_TYPE_U4:
795                         case MONO_TYPE_I4:
796                                 emit_sleb128 (w, read32 (p));
797                                 break;
798                         case MONO_TYPE_U8:
799                         case MONO_TYPE_I8:
800                                 emit_sleb128 (w, read64 (p));
801                                 break;
802                         case MONO_TYPE_I:
803                         case MONO_TYPE_U:
804 #if SIZEOF_VOID_P == 8
805                                 emit_sleb128 (w, read64 (p));
806 #else
807                                 emit_sleb128 (w, read32 (p));
808 #endif
809                                 break;
810                         default:
811                                 g_assert_not_reached ();
812                         }
813                 }
814         } else {
815                 emit_uleb128 (w, ABBREV_STRUCT_TYPE);
816                 emit_string (w, full_name);
817                 emit_uleb128 (w, klass->instance_size);
818
819                 /* Emit fields */
820                 iter = NULL;
821                 while ((field = mono_class_get_fields (klass, &iter))) {
822                         guint8 buf [128];
823                         guint8 *p;
824
825                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
826                                 continue;
827
828                         for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
829                                 if (basic_types [k].type == field->type->type)
830                                         break;
831                         if (k < G_N_ELEMENTS (basic_types) && field->type->type != MONO_TYPE_SZARRAY && field->type->type != MONO_TYPE_CLASS) {
832                                 fdie = basic_types [k].die_name;
833
834                                 emit_uleb128 (w, ABBREV_DATA_MEMBER);
835                                 emit_string (w, field->name);
836                                 emit_symbol_diff (w, fdie, ".Ldebug_info_start", 0);
837                                 /* location */
838                                 p = buf;
839                                 *p ++= DW_OP_plus_uconst;
840                                 if (klass->valuetype && vtype)
841                                         encode_uleb128 (field->offset - sizeof (MonoObject), p, &p);
842                                 else
843                                         encode_uleb128 (field->offset, p, &p);
844
845                                 emit_byte (w, p - buf);
846                                 emit_bytes (w, buf, p - buf);
847                         }
848                 }
849         }
850
851         /* Type end */
852         emit_uleb128 (w, 0x0);
853
854         /* Add a typedef, so we can reference the type without a 'struct' in gdb */
855         emit_uleb128 (w, ABBREV_TYPEDEF);
856         emit_string (w, full_name);
857         emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
858
859         /* Add a pointer type */
860         pointer_die = g_strdup_printf (".LTDIE_%d_POINTER", w->tdie_index);
861         emit_label (w, pointer_die);
862
863         emit_uleb128 (w, ABBREV_POINTER_TYPE);
864         emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
865
866         g_hash_table_insert (w->class_to_pointer_die, klass, pointer_die);
867
868         g_free (full_name);
869         w->tdie_index ++;
870
871         if (emit_namespace) {
872                 /* Namespace end */
873                 emit_uleb128 (w, 0x0);
874         }
875
876         g_hash_table_insert (cache, klass, die);
877         return die;
878 }
879
880 static const char*
881 emit_type (MonoDwarfWriter *w, MonoType *t)
882 {
883         MonoClass *klass = mono_class_from_mono_type (t);
884         int j;
885         const char *tdie;
886
887         if (t->byref) {
888                 if (t->type == MONO_TYPE_VALUETYPE) {
889                         tdie = emit_class_dwarf_info (w, klass, TRUE);
890                         if (tdie)
891                                 return g_hash_table_lookup (w->class_to_pointer_die, klass);
892                 }
893                 // FIXME:
894                 t = &mono_defaults.int_class->byval_arg;
895         }
896         for (j = 0; j < G_N_ELEMENTS (basic_types); ++j)
897                 if (basic_types [j].type == t->type)
898                         break;
899         if (j < G_N_ELEMENTS (basic_types))
900                 tdie = basic_types [j].die_name;
901         else {
902                 switch (t->type) {
903                 case MONO_TYPE_CLASS:
904                         emit_class_dwarf_info (w, klass, FALSE);
905                         tdie = ".LDIE_OBJECT";
906                         break;
907                 case MONO_TYPE_ARRAY:
908                         tdie = ".LDIE_OBJECT";
909                         break;
910                 case MONO_TYPE_VALUETYPE:
911                         if (klass->enumtype)
912                                 tdie = emit_class_dwarf_info (w, klass, FALSE);
913                         else
914                                 tdie = ".LDIE_I4";
915                         break;
916                 default:
917                         tdie = ".LDIE_I4";
918                         break;
919                 }
920         }
921
922         return tdie;
923 }
924
925 static void
926 emit_var_type (MonoDwarfWriter *w, MonoType *t)
927 {
928         const char *tdie;
929
930         tdie = emit_type (w, t);
931
932         emit_symbol_diff (w, tdie, ".Ldebug_info_start", 0);
933 }
934
935 static void
936 encode_var_location (MonoDwarfWriter *w, MonoInst *ins, guint8 *p, guint8 **endp)
937 {
938         /* location */
939         /* FIXME: This needs a location list, since the args can go from reg->stack */
940         if (!ins || ins->flags & MONO_INST_IS_DEAD) {
941                 /* gdb treats this as optimized out */
942         } else if (ins->opcode == OP_REGVAR) {
943                 *p = DW_OP_reg0 + mono_hw_reg_to_dwarf_reg (ins->dreg);
944                 p ++;
945         } else if (ins->opcode == OP_REGOFFSET) {
946                 *p ++= DW_OP_breg0 + mono_hw_reg_to_dwarf_reg (ins->inst_basereg);
947                 encode_sleb128 (ins->inst_offset, p, &p);
948         } else {
949                 // FIXME:
950                 *p ++ = DW_OP_reg0;
951         }
952
953         *endp = p;
954 }
955
956 static void
957 emit_loclist (MonoDwarfWriter *w, MonoInst *ins,
958                           guint8 *loclist_begin_addr, guint8 *loclist_end_addr,
959                           guint8 *expr, guint32 expr_len)
960 {
961         char label [128];
962
963         emit_push_section (w, ".debug_loc", 0);
964         sprintf (label, ".Lloclist_%d", w->loclist_index ++ );
965         emit_label (w, label);
966
967         emit_pointer_value (w, loclist_begin_addr);
968         emit_pointer_value (w, loclist_end_addr);
969         emit_byte (w, expr_len % 256);
970         emit_byte (w, expr_len / 256);
971         emit_bytes (w, expr, expr_len);
972
973         emit_pointer_value (w, NULL);
974         emit_pointer_value (w, NULL);
975
976         emit_pop_section (w);
977         emit_symbol_diff (w, label, ".Ldebug_loc_start", 0);
978 }
979
980 /* 
981  * MonoDisHelper->tokener doesn't take an IP argument, and we can't add one since 
982  * it is a public header.
983  */
984 static const guint8 *token_handler_ip;
985
986 static char*
987 token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token)
988 {
989         char *res, *desc;
990         MonoMethod *cmethod;
991         MonoClass *klass;
992         MonoClassField *field;
993         gpointer data = NULL;
994
995         if (method->wrapper_type)
996                 data = mono_method_get_wrapper_data (method, token);
997
998         switch (*token_handler_ip) {
999         case CEE_ISINST:
1000         case CEE_CASTCLASS:
1001         case CEE_LDELEMA:
1002                 if (method->wrapper_type)
1003                         klass = data;
1004                 else
1005                         klass = mono_class_get_full (method->klass->image, token, NULL);
1006                 res = g_strdup_printf ("<%s>", klass->name);
1007                 break;
1008         case CEE_NEWOBJ:
1009         case CEE_CALL:
1010         case CEE_CALLVIRT:
1011                 if (method->wrapper_type)
1012                         cmethod = data;
1013                 else
1014                         cmethod = mono_get_method_full (method->klass->image, token, NULL, NULL);
1015                 desc = mono_method_full_name (cmethod, TRUE);
1016                 res = g_strdup_printf ("<%s>", desc);
1017                 g_free (desc);
1018                 break;
1019         case CEE_CALLI:
1020                 if (method->wrapper_type) {
1021                         desc = mono_signature_get_desc (data, FALSE);
1022                         res = g_strdup_printf ("<%s>", desc);
1023                         g_free (desc);
1024                 } else {
1025                         res = g_strdup_printf ("<0x%08x>", token);
1026                 }
1027                 break;
1028         case CEE_LDFLD:
1029         case CEE_LDSFLD:
1030         case CEE_STFLD:
1031         case CEE_STSFLD:
1032                 if (method->wrapper_type)
1033                         field = data;
1034                 else
1035                         field = mono_field_from_token (method->klass->image, token, &klass, NULL);
1036                 desc = mono_field_full_name (field);
1037                 res = g_strdup_printf ("<%s>", desc);
1038                 g_free (desc);
1039                 break;
1040         default:
1041                 res = g_strdup_printf ("<0x%08x>", token);
1042                 break;
1043         }
1044
1045         return res;
1046 }
1047
1048 /*
1049  * disasm_ins:
1050  *
1051  *   Produce a disassembled form of the IL instruction at IP. This is an extension
1052  * of mono_disasm_code_one () which can disasm tokens, handle wrapper methods, and
1053  * CEE_MONO_ opcodes.
1054  */
1055 static char*
1056 disasm_ins (MonoMethod *method, const guchar *ip, const guint8 **endip)
1057 {
1058         char *dis;
1059         MonoDisHelper dh;
1060         MonoMethodHeader *header = mono_method_get_header (method);
1061
1062         memset (&dh, 0, sizeof (dh));
1063         dh.newline = "";
1064         dh.label_format = "IL_%04x: ";
1065         dh.label_target = "IL_%04x";
1066         dh.tokener = token_handler;
1067
1068         token_handler_ip = ip;
1069         if (*ip == MONO_CUSTOM_PREFIX) {
1070                 guint32 token;
1071                 gpointer data;
1072
1073                 switch (ip [1]) {
1074                 case CEE_MONO_ICALL: {
1075                         MonoJitICallInfo *info;
1076
1077                         token = read32 (ip + 2);
1078                         data = mono_method_get_wrapper_data (method, token);
1079                         info = mono_find_jit_icall_by_addr (data);
1080                         g_assert (info);
1081
1082                         dis = g_strdup_printf ("IL_%04x: mono_icall <%s>", (int)(ip - header->code), info->name);
1083                         ip += 6;
1084                         break;
1085                 }
1086                 case CEE_MONO_CLASSCONST: {
1087                         token = read32 (ip + 2);
1088                         data = mono_method_get_wrapper_data (method, token);
1089
1090                         dis = g_strdup_printf ("IL_%04x: mono_classconst <%s>", (int)(ip - header->code), ((MonoClass*)data)->name);
1091                         ip += 6;
1092                         break;
1093                 }
1094                 default:
1095                         dis = mono_disasm_code_one (&dh, method, ip, &ip);
1096                 }
1097         } else {
1098                 dis = mono_disasm_code_one (&dh, method, ip, &ip);
1099         }
1100         token_handler_ip = NULL;
1101
1102         *endip = ip;
1103         return dis;
1104 }
1105
1106 static gint32
1107 il_offset_from_address (MonoMethod *method, MonoDebugMethodJitInfo *jit, 
1108                                                 guint32 native_offset)
1109 {
1110         int i;
1111
1112         if (!jit->line_numbers)
1113                 return -1;
1114
1115         for (i = jit->num_line_numbers - 1; i >= 0; i--) {
1116                 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
1117
1118                 if (lne.native_offset <= native_offset)
1119                         return lne.il_offset;
1120         }
1121
1122         return -1;
1123 }
1124
1125 static int max_special_addr_diff = 0;
1126
1127 static inline void
1128 emit_advance_op (MonoDwarfWriter *w, int line_diff, int addr_diff)
1129 {
1130         gint64 opcode = 0;
1131
1132         /* Use a special opcode if possible */
1133         if (line_diff - LINE_BASE >= 0 && line_diff - LINE_BASE < LINE_RANGE) {
1134                 if (max_special_addr_diff == 0)
1135                         max_special_addr_diff = (255 - OPCODE_BASE) / LINE_RANGE;
1136
1137                 if (addr_diff > max_special_addr_diff && (addr_diff < 2 * max_special_addr_diff)) {
1138                         emit_byte (w, DW_LNS_const_add_pc);
1139                         addr_diff -= max_special_addr_diff;
1140                 }
1141
1142                 opcode = (line_diff - LINE_BASE) + (LINE_RANGE * addr_diff) + OPCODE_BASE;
1143                 if (opcode > 255)
1144                         opcode = 0;
1145         }
1146
1147         if (opcode != 0) {
1148                 emit_byte (w, opcode);
1149         } else {
1150                 emit_byte (w, DW_LNS_advance_line);
1151                 emit_sleb128 (w, line_diff);
1152                 emit_byte (w, DW_LNS_advance_pc);
1153                 emit_sleb128 (w, addr_diff);
1154                 emit_byte (w, DW_LNS_copy);
1155         }
1156 }
1157
1158 static gint
1159 compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
1160 {
1161         if (a->native_offset == b->native_offset)
1162                 return a->il_offset - b->il_offset;
1163         else
1164                 return a->native_offset - b->native_offset;
1165 }
1166
1167 static void
1168 emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, guint8 *code,
1169                                            guint32 code_size, MonoDebugMethodJitInfo *debug_info)
1170 {
1171         guint32 prev_line = 0;
1172         guint32 prev_native_offset = 0;
1173         int i, file_index, il_offset, prev_il_offset;
1174         gboolean first = TRUE;
1175         MonoDebugSourceLocation *loc;
1176         char *prev_file_name = NULL;
1177         MonoMethodHeader *header = mono_method_get_header (method);
1178         MonoDebugMethodInfo *minfo;
1179         GArray *ln_array;
1180         int *native_to_il_offset = NULL;
1181
1182         if (!code)
1183                 // FIXME: The set_address op below only works with xdebug
1184                 return;
1185
1186         minfo = mono_debug_lookup_method (method);
1187
1188         /* Compute the native->IL offset mapping */
1189
1190 #ifndef _EGLIB_MAJOR
1191         ln_array = g_array_sized_new (FALSE, FALSE, sizeof (MonoDebugLineNumberEntry), 
1192                                                                   debug_info->num_line_numbers);
1193         g_array_append_vals (ln_array, debug_info->line_numbers, debug_info->num_line_numbers);
1194         g_array_sort (ln_array, (GCompareFunc)compare_lne);
1195         native_to_il_offset = g_new0 (int, code_size + 1);
1196
1197         for (i = 0; i < debug_info->num_line_numbers; ++i) {
1198                 int j;
1199                 MonoDebugLineNumberEntry lne = g_array_index (ln_array, MonoDebugLineNumberEntry, i);
1200
1201                 if (i == 0) {
1202                         for (j = 0; j < lne.native_offset; ++j)
1203                                 native_to_il_offset [j] = -1;
1204                 }
1205
1206                 if (i < debug_info->num_line_numbers - 1) {
1207                         MonoDebugLineNumberEntry lne_next = g_array_index (ln_array, MonoDebugLineNumberEntry, i + 1);
1208
1209                         for (j = lne.native_offset; j < lne_next.native_offset; ++j)
1210                                 native_to_il_offset [j] = lne.il_offset;
1211                 } else {
1212                         for (j = lne.native_offset; j < code_size; ++j)
1213                                 native_to_il_offset [j] = lne.il_offset;
1214                 }
1215         }
1216         g_array_free (ln_array, TRUE);
1217 #endif
1218
1219         prev_line = 1;
1220         prev_il_offset = -1;
1221
1222         for (i = 0; i < code_size; ++i) {
1223                 if (!minfo)
1224                         continue;
1225
1226                 if (!debug_info->line_numbers)
1227                         continue;
1228
1229                 if (native_to_il_offset)
1230                         il_offset = native_to_il_offset [i];
1231                 else
1232                         il_offset = il_offset_from_address (method, debug_info, i);
1233                 /*
1234                 il_offset = il_offset_from_address (method, debug_info, i);
1235
1236                 g_assert (il_offset == native_to_il_offset [i]);
1237                 */
1238
1239                 il_offset = native_to_il_offset [i];
1240                 if (il_offset < 0)
1241                         continue;
1242
1243                 if (il_offset == prev_il_offset)
1244                         continue;
1245
1246                 prev_il_offset = il_offset;
1247
1248                 loc = mono_debug_symfile_lookup_location (minfo, il_offset);
1249
1250                 if (loc) {
1251                         int line_diff = (gint32)loc->row - (gint32)prev_line;
1252                         int addr_diff = i - prev_native_offset;
1253
1254                         if (first) {    
1255                                 emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
1256
1257                                 emit_byte (w, 0);
1258                                 emit_byte (w, sizeof (gpointer) + 1);
1259                                 emit_byte (w, DW_LNE_set_address);
1260                                 emit_pointer_value (w, code);
1261
1262                                 /* 
1263                                  * The prolog+initlocals region does not have a line number, this
1264                                  * makes them belong to the first line of the method.
1265                                  */
1266                                 emit_byte (w, DW_LNS_advance_line);
1267                                 emit_sleb128 (w, (gint32)loc->row - (gint32)prev_line);
1268                                 prev_line = loc->row;
1269                         }
1270
1271                         if (loc->row != prev_line) {
1272                                 if (!prev_file_name || strcmp (loc->source_file, prev_file_name) != 0) {
1273                                         /* Add an entry to the file table */
1274                                         /* FIXME: Avoid duplicates */
1275                                         file_index = emit_line_number_file_name (w, loc->source_file, 0, 0);
1276                                         g_free (prev_file_name);
1277                                         prev_file_name = g_strdup (loc->source_file);
1278
1279                                         emit_byte (w, DW_LNS_set_file);
1280                                         emit_uleb128 (w, file_index);
1281                                         emit_byte (w, DW_LNS_copy);
1282                                 }
1283
1284                                 //printf ("X: %p(+0x%x) %d %s:%d(+%d)\n", code + i, addr_diff, loc->il_offset, loc->source_file, loc->row, line_diff);
1285
1286                                 emit_advance_op (w, line_diff, addr_diff);
1287
1288                                 prev_line = loc->row;
1289                                 prev_native_offset = i;
1290                         }
1291
1292                         first = FALSE;
1293                         g_free (loc);
1294                 }
1295         }
1296
1297         g_free (prev_file_name);
1298
1299         if (!first) {
1300                 emit_byte (w, DW_LNS_advance_pc);
1301                 emit_sleb128 (w, code_size - prev_native_offset);
1302                 emit_byte (w, DW_LNS_copy);
1303
1304                 emit_byte (w, 0);
1305                 emit_byte (w, 1);
1306                 emit_byte (w, DW_LNE_end_sequence);
1307         } else if (code) {
1308                 /* No debug info, XDEBUG mode */
1309                 char *name, *dis;
1310                 const guint8 *ip = header->code;
1311                 int prev_line, prev_native_offset;
1312                 int *il_to_line;
1313
1314                 /*
1315                  * Emit the IL code into a temporary file and emit line number info
1316                  * referencing that file.
1317                  */
1318
1319                 name = mono_method_full_name (method, TRUE);
1320                 fprintf (w->il_file, "// %s\n", name);
1321                 w->il_file_line_index ++;
1322                 g_free (name);
1323
1324                 il_to_line = g_new0 (int, header->code_size);
1325
1326                 emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
1327                 emit_byte (w, 0);
1328                 emit_byte (w, sizeof (gpointer) + 1);
1329                 emit_byte (w, DW_LNE_set_address);
1330                 emit_pointer_value (w, code);
1331
1332                 // FIXME: Optimize this
1333                 while (ip < header->code + header->code_size) {
1334                         int il_offset = ip - header->code;
1335
1336                         /* Emit IL */
1337                         w->il_file_line_index ++;
1338
1339                         dis = disasm_ins (method, ip, &ip);
1340                         fprintf (w->il_file, "%s\n", dis);
1341                         g_free (dis);
1342
1343                         il_to_line [il_offset] = w->il_file_line_index;
1344                 }
1345
1346                 /* Emit line number info */
1347                 prev_line = 1;
1348                 prev_native_offset = 0;
1349                 for (i = 0; i < debug_info->num_line_numbers; ++i) {
1350                         MonoDebugLineNumberEntry *lne = &debug_info->line_numbers [i];
1351                         int line;
1352
1353                         if (lne->il_offset >= header->code_size)
1354                                 continue;
1355                         line = il_to_line [lne->il_offset];
1356                         if (!line) {
1357                                 /* 
1358                                  * This seems to happen randomly, it looks like il_offset points
1359                                  * into the middle of an instruction.
1360                                  */
1361                                 continue;
1362                                 /*
1363                                 printf ("%s\n", mono_method_full_name (method, TRUE));
1364                                 printf ("%d %d\n", lne->il_offset, header->code_size);
1365                                 g_assert (line);
1366                                 */
1367                         }
1368
1369                         if (line - prev_line != 0) {
1370                                 emit_advance_op (w, line - prev_line, (gint32)lne->native_offset - prev_native_offset);
1371
1372                                 prev_line = line;
1373                                 prev_native_offset = lne->native_offset;
1374                         }
1375                 }
1376
1377                 emit_byte (w, DW_LNS_advance_pc);
1378                 emit_sleb128 (w, code_size - prev_native_offset);
1379                 emit_byte (w, DW_LNS_copy);
1380
1381                 emit_byte (w, 0);
1382                 emit_byte (w, 1);
1383                 emit_byte (w, DW_LNE_end_sequence);
1384
1385                 fflush (w->il_file);
1386                 g_free (il_to_line);
1387         }
1388 }
1389
1390 static MonoMethodVar*
1391 find_vmv (MonoCompile *cfg, MonoInst *ins)
1392 {
1393         int j;
1394
1395         if (cfg->varinfo) {
1396                 for (j = 0; j < cfg->num_varinfo; ++j) {
1397                         if (cfg->varinfo [j] == ins)
1398                                 break;
1399                 }
1400
1401                 if (j < cfg->num_varinfo) {
1402                         return MONO_VARINFO (cfg, j);
1403                 }
1404         }
1405
1406         return NULL;
1407 }
1408
1409 void
1410 mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod *method, char *start_symbol, char *end_symbol, guint8 *code, guint32 code_size, MonoInst **args, MonoInst **locals, GSList *unwind_info, MonoDebugMethodJitInfo *debug_info)
1411 {
1412         char *name;
1413         MonoMethodSignature *sig;
1414         MonoMethodHeader *header;
1415         char **names, **tdies, **local_tdies;
1416         char **local_names;
1417         int *local_indexes;
1418         int i, num_locals;
1419         guint8 buf [128];
1420         guint8 *p;
1421
1422         emit_section_change (w, ".debug_info", 0);
1423
1424         sig = mono_method_signature (method);
1425         header = mono_method_get_header (method);
1426
1427         /* Parameter types */
1428         tdies = g_new0 (char *, sig->param_count + sig->hasthis);
1429         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
1430                 MonoType *t;
1431
1432                 if (i == 0 && sig->hasthis) {
1433                         t = &method->klass->this_arg;
1434                 } else {
1435                         t = sig->params [i - sig->hasthis];
1436                 }
1437
1438                 emit_type (w, t);
1439         }
1440
1441         /* Local types */
1442         local_tdies = g_new0 (char *, header->num_locals);
1443         for (i = 0; i < header->num_locals; ++i) {
1444                 emit_type (w, header->locals [i]);
1445         }
1446
1447         /* Subprogram */
1448         names = g_new0 (char *, sig->param_count);
1449         mono_method_get_param_names (method, (const char **) names);
1450
1451         emit_uleb128 (w, ABBREV_SUBPROGRAM);
1452         name = mono_method_full_name (method, FALSE);
1453         emit_string (w, name);
1454         g_free (name);
1455         if (start_symbol) {
1456                 emit_pointer_unaligned (w, start_symbol);
1457                 emit_pointer_unaligned (w, end_symbol);
1458         } else {
1459                 emit_pointer_value (w, code);
1460                 emit_pointer_value (w, code + code_size);
1461         }
1462         /* frame_base */
1463         emit_byte (w, 2);
1464         emit_byte (w, DW_OP_breg6);
1465         emit_byte (w, 16);
1466
1467         /* Parameters */
1468         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
1469                 MonoInst *arg = args ? args [i] : NULL;
1470                 MonoType *t;
1471                 const char *pname;
1472                 char pname_buf [128];
1473                 MonoMethodVar *vmv = NULL;
1474                 gboolean need_loclist = FALSE;
1475
1476                 vmv = find_vmv (cfg, arg);
1477                 if (code && vmv && (vmv->live_range_start || vmv->live_range_end))
1478                         need_loclist = TRUE;
1479
1480                 if (i == 0 && sig->hasthis) {
1481                         if (method->klass->valuetype)
1482                                 t = &method->klass->this_arg;
1483                         else
1484                                 t = &mono_defaults.object_class->byval_arg;
1485                         pname = "this";
1486                 } else {
1487                         t = sig->params [i - sig->hasthis];
1488                         pname = names [i - sig->hasthis];
1489                 }
1490
1491                 emit_uleb128 (w, need_loclist ? ABBREV_PARAM_LOCLIST : ABBREV_PARAM);
1492                 /* name */
1493                 if (pname[0] == '\0') {
1494                         sprintf (pname_buf, "param%d", i - sig->hasthis);
1495                         pname = pname_buf;
1496                 }
1497                 emit_string (w, pname);
1498                 /* type */
1499                 if (!arg || arg->flags & MONO_INST_IS_DEAD)
1500                         emit_var_type (w, &mono_defaults.int32_class->byval_arg);
1501                 else
1502                         emit_var_type (w, t);
1503
1504                 p = buf;
1505                 encode_var_location (w, arg, p, &p);
1506                 if (need_loclist) {
1507                         vmv->live_range_start = 0;
1508                         if (vmv->live_range_end == 0)
1509                                 /* FIXME: Uses made in calls are not recorded */
1510                                 vmv->live_range_end = code_size;
1511                         emit_loclist (w, arg, code + vmv->live_range_start, code + vmv->live_range_end, buf, p - buf);
1512                 } else {
1513                         emit_byte (w, p - buf);
1514                         emit_bytes (w, buf, p - buf);
1515                 }
1516         }               
1517         g_free (names);
1518
1519         /* Locals */
1520         num_locals = mono_debug_lookup_locals (method, &local_names, &local_indexes);
1521
1522         for (i = 0; i < header->num_locals; ++i) {
1523                 MonoInst *ins = locals [i];
1524                 char name_buf [128];
1525                 int j;
1526                 MonoMethodVar *vmv = NULL;
1527                 gboolean need_loclist = FALSE;
1528
1529                 /* ins->dreg no longer contains the original vreg */
1530                 vmv = find_vmv (cfg, ins);
1531                 if (code && vmv) {
1532                         if (vmv->live_range_start) {
1533                                 /* This variable has a precise live range */
1534                                 need_loclist = TRUE;
1535                         }
1536                 }
1537
1538                 emit_uleb128 (w, need_loclist ? ABBREV_VARIABLE_LOCLIST : ABBREV_VARIABLE);
1539                 /* name */
1540                 for (j = 0; j < num_locals; ++j)
1541                         if (local_indexes [j] == i)
1542                                 break;
1543                 if (j < num_locals) {
1544                         emit_string (w, local_names [j]);
1545                 } else {
1546                         sprintf (name_buf, "V_%d", i);
1547                         emit_string (w, name_buf);
1548                 }
1549                 /* type */
1550                 if (!ins || ins->flags & MONO_INST_IS_DEAD)
1551                         emit_var_type (w, &mono_defaults.int32_class->byval_arg);
1552                 else
1553                         emit_var_type (w, header->locals [i]);
1554
1555                 p = buf;
1556                 encode_var_location (w, ins, p, &p);
1557
1558                 if (need_loclist) {
1559                         if (vmv->live_range_end == 0)
1560                                 /* FIXME: Uses made in calls are not recorded */
1561                                 vmv->live_range_end = code_size;
1562                         emit_loclist (w, ins, code + vmv->live_range_start, code + vmv->live_range_end, buf, p - buf);
1563                 } else {
1564                         emit_byte (w, p - buf);
1565                         emit_bytes (w, buf, p - buf);
1566                 }
1567         }
1568
1569         g_free (local_names);
1570         g_free (local_indexes);
1571
1572         /* Subprogram end */
1573         emit_uleb128 (w, 0x0);
1574
1575         emit_line (w);
1576
1577         /* Emit unwind info */
1578         if (unwind_info) {
1579                 emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
1580                 w->fde_index ++;
1581         }
1582
1583         /* Emit line number info */
1584         if (code && debug_info)
1585                 emit_line_number_info (w, method, code, code_size, debug_info);
1586
1587         emit_line (w);
1588 }
1589
1590 void
1591 mono_dwarf_writer_emit_trampoline (MonoDwarfWriter *w, const char *tramp_name, char *start_symbol, char *end_symbol, guint8 *code, guint32 code_size, GSList *unwind_info)
1592 {
1593         emit_section_change (w, ".debug_info", 0);
1594
1595         /* Subprogram */
1596         emit_uleb128 (w, ABBREV_SUBPROGRAM);
1597         emit_string (w, tramp_name);
1598         emit_pointer_value (w, code);
1599         emit_pointer_value (w, code + code_size);
1600         /* frame_base */
1601         emit_byte (w, 2);
1602         emit_byte (w, DW_OP_breg6);
1603         emit_byte (w, 16);
1604
1605         /* Subprogram end */
1606         emit_uleb128 (w, 0x0);
1607
1608         /* Emit unwind info */
1609         emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, FALSE);
1610         w->fde_index ++;
1611 }