[corlib] Assume UTC if no $TZ set. Fixes #30360
[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
12 #if !defined(DISABLE_AOT) && !defined(DISABLE_JIT)
13 #include "dwarfwriter.h"
14
15 #include <sys/types.h>
16 #include <ctype.h>
17 #include <string.h>
18 #ifdef HAVE_STDINT_H
19 #include <stdint.h>
20 #endif
21
22 #include <mono/metadata/mono-endian.h>
23 #include <mono/metadata/debug-mono-symfile.h>
24 #include <mono/metadata/mono-debug-debugger.h>
25 #include <mono/utils/mono-compiler.h>
26
27 #ifndef HOST_WIN32
28 #include <mono/utils/freebsd-elf32.h>
29 #include <mono/utils/freebsd-elf64.h>
30 #endif
31
32 #include <mono/utils/freebsd-dwarf.h>
33
34 #define DW_AT_MIPS_linkage_name 0x2007
35 #define DW_LNE_set_prologue_end 0x0a
36
37 typedef struct {
38         MonoMethod *method;
39         char *start_symbol, *end_symbol;
40         guint8 *code;
41         guint32 code_size;
42 } MethodLineNumberInfo;
43
44 struct _MonoDwarfWriter
45 {
46         MonoImageWriter *w;
47         GHashTable *class_to_die, *class_to_vtype_die, *class_to_pointer_die;
48         GHashTable *class_to_reference_die;
49         int fde_index, tdie_index, line_number_file_index, line_number_dir_index;
50         GHashTable *file_to_index, *index_to_file, *dir_to_index;
51         FILE *il_file;
52         int il_file_line_index, loclist_index;
53         GSList *cie_program;
54         FILE *fp;
55         const char *temp_prefix;
56         gboolean emit_line, appending, collect_line_info;
57         GSList *line_info;
58         int cur_file_index;
59 };
60
61 static void
62 emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, 
63                                            char *start_symbol, char *end_symbol,
64                                            guint8 *code, guint32 code_size,
65                                            MonoDebugMethodJitInfo *debug_info);
66
67 /*
68  * mono_dwarf_writer_create:
69  *
70  *   Create a DWARF writer object. WRITER is the underlying image writer this 
71  * writer will emit to. IL_FILE is the file where IL code will be dumped to for
72  * methods which have no line number info. It can be NULL.
73  * If APPENDING is TRUE, the output file will be in assembleable state after each
74  * call to the _emit_ functions. This is used for XDEBUG. If APPENDING is FALSE,
75  * a separate mono_dwarf_writer_close () call is needed to finish the emission of
76  * debug information.
77  */
78 MonoDwarfWriter*
79 mono_dwarf_writer_create (MonoImageWriter *writer, FILE *il_file, int il_file_start_line, gboolean appending, gboolean emit_line_numbers)
80 {
81         MonoDwarfWriter *w = g_new0 (MonoDwarfWriter, 1);
82         
83         /*
84          * The appending flag is needed because we use subsections to order things in 
85          * the debug info, and:
86          * - apple's assembler doesn't support them
87          * - the binary writer has problems with subsections+alignment
88          * So instead of subsections, we use the _close () function in AOT mode,
89          * which writes out things in order.
90          */
91
92         w->w = writer;
93         w->il_file = il_file;
94         w->il_file_line_index = il_file_start_line;
95         w->appending = appending;
96
97         if (appending)
98                 g_assert (mono_img_writer_subsections_supported (w->w));
99
100         w->emit_line = TRUE;
101
102         if (appending) {
103                 if (!mono_img_writer_subsections_supported (w->w))
104                         /* Can't emit line number info without subsections */
105                         w->emit_line = FALSE;
106         } else {
107                 /* Collect line number info and emit it at once */
108                 w->collect_line_info = TRUE;
109         }
110
111         if (!emit_line_numbers) {
112                 w->emit_line = FALSE;
113                 w->collect_line_info = FALSE;
114         }
115
116         w->fp = mono_img_writer_get_fp (w->w);
117         w->temp_prefix = mono_img_writer_get_temp_label_prefix (w->w);
118
119         w->class_to_die = g_hash_table_new (NULL, NULL);
120         w->class_to_vtype_die = g_hash_table_new (NULL, NULL);
121         w->class_to_pointer_die = g_hash_table_new (NULL, NULL);
122         w->class_to_reference_die = g_hash_table_new (NULL, NULL);
123         w->cur_file_index = -1;
124
125         return w;
126 }
127
128 void
129 mono_dwarf_writer_destroy (MonoDwarfWriter *w)
130 {
131         g_free (w);
132 }
133
134 int
135 mono_dwarf_writer_get_il_file_line_index (MonoDwarfWriter *w)
136 {
137         return w->il_file_line_index;
138 }
139
140 /* Wrappers around the image writer functions */
141
142 static inline void
143 emit_section_change (MonoDwarfWriter *w, const char *section_name, int subsection_index)
144 {
145         mono_img_writer_emit_section_change (w->w, section_name, subsection_index);
146 }
147
148 static inline void
149 emit_push_section (MonoDwarfWriter *w, const char *section_name, int subsection)
150 {
151         mono_img_writer_emit_push_section (w->w, section_name, subsection);
152 }
153
154 static inline void
155 emit_pop_section (MonoDwarfWriter *w)
156 {
157         mono_img_writer_emit_pop_section (w->w);
158 }
159
160 static inline void
161 emit_label (MonoDwarfWriter *w, const char *name) 
162
163         mono_img_writer_emit_label (w->w, name); 
164 }
165
166 static inline void
167 emit_bytes (MonoDwarfWriter *w, const guint8* buf, int size) 
168
169         mono_img_writer_emit_bytes (w->w, buf, size); 
170 }
171
172 static inline void
173 emit_string (MonoDwarfWriter *w, const char *value) 
174
175         mono_img_writer_emit_string (w->w, value); 
176 }
177
178 static inline void
179 emit_line (MonoDwarfWriter *w) 
180
181         mono_img_writer_emit_line (w->w); 
182 }
183
184 static inline void
185 emit_alignment (MonoDwarfWriter *w, int size) 
186
187         mono_img_writer_emit_alignment (w->w, size); 
188 }
189
190 static inline void
191 emit_pointer_unaligned (MonoDwarfWriter *w, const char *target) 
192
193         mono_img_writer_emit_pointer_unaligned (w->w, target); 
194 }
195
196 static inline void
197 emit_pointer (MonoDwarfWriter *w, const char *target) 
198
199         mono_img_writer_emit_pointer (w->w, target); 
200 }
201
202 static inline void
203 emit_int16 (MonoDwarfWriter *w, int value) 
204
205         mono_img_writer_emit_int16 (w->w, value); 
206 }
207
208 static inline void
209 emit_int32 (MonoDwarfWriter *w, int value) 
210
211         mono_img_writer_emit_int32 (w->w, value); 
212 }
213
214 static inline void
215 emit_symbol_diff (MonoDwarfWriter *w, const char *end, const char* start, int offset) 
216
217         mono_img_writer_emit_symbol_diff (w->w, end, start, offset); 
218 }
219
220 static inline void
221 emit_byte (MonoDwarfWriter *w, guint8 val) 
222
223         mono_img_writer_emit_byte (w->w, val); 
224 }
225
226 static G_GNUC_UNUSED void
227 emit_uleb128 (MonoDwarfWriter *w, guint32 value)
228 {
229         do {
230                 guint8 b = value & 0x7f;
231                 value >>= 7;
232                 if (value != 0) /* more bytes to come */
233                         b |= 0x80;
234                 emit_byte (w, b);
235         } while (value);
236 }
237
238 static G_GNUC_UNUSED void
239 emit_sleb128 (MonoDwarfWriter *w, gint64 value)
240 {
241         gboolean more = 1;
242         gboolean negative = (value < 0);
243         guint32 size = 64;
244         guint8 byte;
245
246         while (more) {
247                 byte = value & 0x7f;
248                 value >>= 7;
249                 /* the following is unnecessary if the
250                  * implementation of >>= uses an arithmetic rather
251                  * than logical shift for a signed left operand
252                  */
253                 if (negative)
254                         /* sign extend */
255                         value |= - ((gint64)1 <<(size - 7));
256                 /* sign bit of byte is second high order bit (0x40) */
257                 if ((value == 0 && !(byte & 0x40)) ||
258                         (value == -1 && (byte & 0x40)))
259                         more = 0;
260                 else
261                         byte |= 0x80;
262                 emit_byte (w, byte);
263         }
264 }
265
266 static G_GNUC_UNUSED void
267 encode_uleb128 (guint32 value, guint8 *buf, guint8 **endbuf)
268 {
269         guint8 *p = buf;
270
271         do {
272                 guint8 b = value & 0x7f;
273                 value >>= 7;
274                 if (value != 0) /* more bytes to come */
275                         b |= 0x80;
276                 *p ++ = b;
277         } while (value);
278
279         *endbuf = p;
280 }
281
282 static G_GNUC_UNUSED void
283 encode_sleb128 (gint32 value, guint8 *buf, guint8 **endbuf)
284 {
285         gboolean more = 1;
286         gboolean negative = (value < 0);
287         guint32 size = 32;
288         guint8 byte;
289         guint8 *p = buf;
290
291         while (more) {
292                 byte = value & 0x7f;
293                 value >>= 7;
294                 /* the following is unnecessary if the
295                  * implementation of >>= uses an arithmetic rather
296                  * than logical shift for a signed left operand
297                  */
298                 if (negative)
299                         /* sign extend */
300                         value |= - (1 <<(size - 7));
301                 /* sign bit of byte is second high order bit (0x40) */
302                 if ((value == 0 && !(byte & 0x40)) ||
303                         (value == -1 && (byte & 0x40)))
304                         more = 0;
305                 else
306                         byte |= 0x80;
307                 *p ++= byte;
308         }
309
310         *endbuf = p;
311 }
312
313 static void
314 emit_dwarf_abbrev (MonoDwarfWriter *w, int code, int tag, gboolean has_child,
315                                    int *attrs, int attrs_len)
316 {
317         int i;
318
319         emit_uleb128 (w, code);
320         emit_uleb128 (w, tag);
321         emit_byte (w, has_child);
322
323         for (i = 0; i < attrs_len; i++)
324                 emit_uleb128 (w, attrs [i]);
325         emit_uleb128 (w, 0);
326         emit_uleb128 (w, 0);
327 }
328
329 static void
330 emit_cie (MonoDwarfWriter *w)
331 {
332         emit_section_change (w, ".debug_frame", 0);
333
334         emit_alignment (w, 8);
335
336         /* Emit a CIE */
337         emit_symbol_diff (w, ".Lcie0_end", ".Lcie0_start", 0); /* length */
338         emit_label (w, ".Lcie0_start");
339         emit_int32 (w, 0xffffffff); /* CIE id */
340         emit_byte (w, 3); /* version */
341         emit_string (w, ""); /* augmention */
342         emit_sleb128 (w, 1); /* code alignment factor */
343         emit_sleb128 (w, mono_unwind_get_dwarf_data_align ()); /* data alignment factor */
344         emit_uleb128 (w, mono_unwind_get_dwarf_pc_reg ());
345
346         w->cie_program = w->cie_program;
347         if (w->cie_program) {
348                 guint32 uw_info_len;
349                 guint8 *uw_info = mono_unwind_ops_encode (w->cie_program, &uw_info_len);
350                 emit_bytes (w, uw_info, uw_info_len);
351                 g_free (uw_info);
352         }
353
354         emit_alignment (w, sizeof (gpointer));
355         emit_label (w, ".Lcie0_end");
356 }
357
358 static void
359 emit_pointer_value (MonoDwarfWriter *w, gpointer ptr)
360 {
361         gssize val = (gssize)ptr;
362         emit_bytes (w, (guint8*)&val, sizeof (gpointer));
363 }
364
365 static void
366 emit_fde (MonoDwarfWriter *w, int fde_index, char *start_symbol, char *end_symbol,
367                   guint8 *code, guint32 code_size, GSList *unwind_ops, gboolean use_cie)
368 {
369         char symbol1 [128];
370         char symbol2 [128];
371         GSList *l;
372         guint8 *uw_info;
373         guint32 uw_info_len;
374
375         emit_section_change (w, ".debug_frame", 0);
376
377         sprintf (symbol1, ".Lfde%d_start", fde_index);
378         sprintf (symbol2, ".Lfde%d_end", fde_index);
379         emit_symbol_diff (w, symbol2, symbol1, 0); /* length */
380         emit_label (w, symbol1);
381         emit_int32 (w, 0); /* CIE_pointer */
382         if (start_symbol) {
383                 emit_pointer (w, start_symbol); /* initial_location */
384                 if (end_symbol)
385                         emit_symbol_diff (w, end_symbol, start_symbol, 0); /* address_range */
386                 else {
387                         g_assert (code_size);
388                         emit_int32 (w, code_size);
389                 }
390         } else {
391                 emit_pointer_value (w, code);
392                 emit_int32 (w, code_size);
393         }
394 #if SIZEOF_VOID_P == 8
395         /* Upper 32 bits of code size */
396         emit_int32 (w, 0);
397 #endif
398
399         l = unwind_ops;
400         if (w->cie_program) {
401                 // FIXME: Check that the ops really begin with the CIE program */
402                 int i;
403
404                 for (i = 0; i < g_slist_length (w->cie_program); ++i)
405                         if (l)
406                                 l = l->next;
407         }
408
409         /* Convert the list of MonoUnwindOps to the format used by DWARF */     
410         uw_info = mono_unwind_ops_encode (l, &uw_info_len);
411         emit_bytes (w, uw_info, uw_info_len);
412         g_free (uw_info);
413
414         emit_alignment (w, sizeof (mgreg_t));
415         emit_label (w, symbol2);
416 }
417
418 /* Abbrevations */
419 #define ABBREV_COMPILE_UNIT 1
420 #define ABBREV_SUBPROGRAM 2
421 #define ABBREV_PARAM 3
422 #define ABBREV_BASE_TYPE 4
423 #define ABBREV_STRUCT_TYPE 5
424 #define ABBREV_DATA_MEMBER 6
425 #define ABBREV_TYPEDEF 7
426 #define ABBREV_ENUM_TYPE 8
427 #define ABBREV_ENUMERATOR 9
428 #define ABBREV_NAMESPACE 10
429 #define ABBREV_VARIABLE 11
430 #define ABBREV_VARIABLE_LOCLIST 12
431 #define ABBREV_POINTER_TYPE 13
432 #define ABBREV_REFERENCE_TYPE 14
433 #define ABBREV_PARAM_LOCLIST 15
434 #define ABBREV_INHERITANCE 16
435 #define ABBREV_STRUCT_TYPE_NOCHILDREN 17
436 #define ABBREV_TRAMP_SUBPROGRAM 18
437
438 static int compile_unit_attr [] = {
439         DW_AT_producer     ,DW_FORM_string,
440     DW_AT_name         ,DW_FORM_string,
441     DW_AT_comp_dir     ,DW_FORM_string,
442         DW_AT_language     ,DW_FORM_data1,
443     DW_AT_low_pc       ,DW_FORM_addr,
444     DW_AT_high_pc      ,DW_FORM_addr,
445         DW_AT_stmt_list    ,DW_FORM_data4
446 };
447
448 static int subprogram_attr [] = {
449         DW_AT_name         , DW_FORM_string,
450         DW_AT_MIPS_linkage_name, DW_FORM_string,
451         DW_AT_decl_file    , DW_FORM_udata,
452         DW_AT_decl_line    , DW_FORM_udata,
453 #ifndef TARGET_IOS
454         DW_AT_description  , DW_FORM_string,
455 #endif
456     DW_AT_low_pc       , DW_FORM_addr,
457     DW_AT_high_pc      , DW_FORM_addr,
458         DW_AT_frame_base   , DW_FORM_block1
459 };
460
461 static int tramp_subprogram_attr [] = {
462         DW_AT_name         , DW_FORM_string,
463     DW_AT_low_pc       , DW_FORM_addr,
464     DW_AT_high_pc      , DW_FORM_addr,
465 };
466
467 static int param_attr [] = {
468         DW_AT_name,     DW_FORM_string,
469         DW_AT_type,     DW_FORM_ref4,
470         DW_AT_location, DW_FORM_block1
471 };
472
473 static int param_loclist_attr [] = {
474         DW_AT_name,     DW_FORM_string,
475         DW_AT_type,     DW_FORM_ref4,
476         DW_AT_location, DW_FORM_data4
477 };
478
479 static int base_type_attr [] = {
480         DW_AT_byte_size,   DW_FORM_data1,
481         DW_AT_encoding,    DW_FORM_data1,
482         DW_AT_name,        DW_FORM_string
483 };
484
485 static int struct_type_attr [] = {
486         DW_AT_name,        DW_FORM_string,
487         DW_AT_byte_size,   DW_FORM_udata,
488 };
489
490 static int data_member_attr [] = {
491         DW_AT_name,        DW_FORM_string,
492         DW_AT_type,        DW_FORM_ref4,
493         DW_AT_data_member_location, DW_FORM_block1
494 };
495
496 static int typedef_attr [] = {
497         DW_AT_name,        DW_FORM_string,
498         DW_AT_type,        DW_FORM_ref4
499 };
500
501 static int pointer_type_attr [] = {
502         DW_AT_type,        DW_FORM_ref4,
503 };
504
505 static int reference_type_attr [] = {
506         DW_AT_type,        DW_FORM_ref4,
507 };
508
509 static int enum_type_attr [] = {
510         DW_AT_name,        DW_FORM_string,
511         DW_AT_byte_size,   DW_FORM_udata,
512         DW_AT_type,        DW_FORM_ref4,
513 };
514
515 static int enumerator_attr [] = {
516         DW_AT_name,        DW_FORM_string,
517         DW_AT_const_value, DW_FORM_sdata,
518 };
519
520 static int namespace_attr [] = {
521         DW_AT_name,        DW_FORM_string,
522 };
523
524 static int variable_attr [] = {
525         DW_AT_name,     DW_FORM_string,
526         DW_AT_type,     DW_FORM_ref4,
527         DW_AT_location, DW_FORM_block1
528 };
529
530 static int variable_loclist_attr [] = {
531         DW_AT_name,     DW_FORM_string,
532         DW_AT_type,     DW_FORM_ref4,
533         DW_AT_location, DW_FORM_data4
534 };
535  
536 static int inheritance_attr [] = {
537         DW_AT_type,        DW_FORM_ref4,
538         DW_AT_data_member_location, DW_FORM_block1
539 };
540
541 typedef struct DwarfBasicType {
542         const char *die_name, *name;
543         int type;
544         int size;
545         int encoding;
546 } DwarfBasicType;
547
548 static DwarfBasicType basic_types [] = {
549         { ".LDIE_I1", "sbyte", MONO_TYPE_I1, 1, DW_ATE_signed },
550         { ".LDIE_U1", "byte", MONO_TYPE_U1, 1, DW_ATE_unsigned },
551         { ".LDIE_I2", "short", MONO_TYPE_I2, 2, DW_ATE_signed },
552         { ".LDIE_U2", "ushort", MONO_TYPE_U2, 2, DW_ATE_unsigned },
553         { ".LDIE_I4", "int", MONO_TYPE_I4, 4, DW_ATE_signed },
554         { ".LDIE_U4", "uint", MONO_TYPE_U4, 4, DW_ATE_unsigned },
555         { ".LDIE_I8", "long", MONO_TYPE_I8, 8, DW_ATE_signed },
556         { ".LDIE_U8", "ulong", MONO_TYPE_U8, 8, DW_ATE_unsigned },
557         { ".LDIE_I", "intptr", MONO_TYPE_I, SIZEOF_VOID_P, DW_ATE_signed },
558         { ".LDIE_U", "uintptr", MONO_TYPE_U, SIZEOF_VOID_P, DW_ATE_unsigned },
559         { ".LDIE_R4", "float", MONO_TYPE_R4, 4, DW_ATE_float },
560         { ".LDIE_R8", "double", MONO_TYPE_R8, 8, DW_ATE_float },
561         { ".LDIE_BOOLEAN", "boolean", MONO_TYPE_BOOLEAN, 1, DW_ATE_boolean },
562         { ".LDIE_CHAR", "char", MONO_TYPE_CHAR, 2, DW_ATE_unsigned_char },
563         { ".LDIE_STRING", "string", MONO_TYPE_STRING, sizeof (gpointer), DW_ATE_address },
564         { ".LDIE_OBJECT", "object", MONO_TYPE_OBJECT, sizeof (gpointer), DW_ATE_address },
565         { ".LDIE_SZARRAY", "object", MONO_TYPE_SZARRAY, sizeof (gpointer), DW_ATE_address },
566 };
567
568 /* Constants for encoding line number special opcodes */
569 #define OPCODE_BASE 13
570 #define LINE_BASE -5
571 #define LINE_RANGE 14
572
573 /* Subsections of the .debug_line section */
574 #define LINE_SUBSECTION_HEADER 1
575 #define LINE_SUBSECTION_INCLUDES 2
576 #define LINE_SUBSECTION_FILES 3
577 #define LINE_SUBSECTION_DATA 4
578 #define LINE_SUBSECTION_END 5
579
580 static int
581 emit_line_number_file_name (MonoDwarfWriter *w, const char *name,
582                                                         gint64 last_mod_time, gint64 file_size)
583 {
584         int index;
585         int dir_index;
586         char *basename = NULL;
587
588         if (!w->file_to_index)
589                 w->file_to_index = g_hash_table_new (g_str_hash, g_str_equal);
590
591         index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name));
592         if (index > 0)
593                 return index;
594
595         if (g_path_is_absolute (name)) {
596                 char *dir = g_path_get_dirname (name);
597
598                 if (!w->dir_to_index)
599                         w->dir_to_index = g_hash_table_new (g_str_hash, g_str_equal);
600
601                 dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (w->dir_to_index, dir));
602                 if (dir_index == 0) {
603                         emit_section_change (w, ".debug_line", LINE_SUBSECTION_INCLUDES);
604                         emit_string (w, dir);
605
606                         dir_index = ++ w->line_number_dir_index;
607                         g_hash_table_insert (w->dir_to_index, g_strdup (dir), GUINT_TO_POINTER (dir_index));
608                 }
609
610                 g_free (dir);
611
612                 basename = g_path_get_basename (name);
613         } else {
614                 dir_index = 0;
615         }
616
617         emit_section_change (w, ".debug_line", LINE_SUBSECTION_FILES);
618
619         if (basename)
620                 emit_string (w, basename);
621         else
622                 emit_string (w, name);
623         emit_uleb128 (w, dir_index);
624         emit_byte (w, 0);
625         emit_byte (w, 0);
626
627         emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
628
629         if (basename)
630                 g_free (basename);
631
632         index = ++ w->line_number_file_index;
633         g_hash_table_insert (w->file_to_index, g_strdup (name), GUINT_TO_POINTER (index));
634
635         return index;
636 }
637
638 static int
639 get_line_number_file_name (MonoDwarfWriter *w, const char *name)
640 {
641         int index;
642
643         g_assert (w->file_to_index);
644         index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name));
645         g_assert (index > 0);
646         return index - 1;
647 }
648
649 static int
650 add_line_number_file_name (MonoDwarfWriter *w, const char *name,
651                                                    gint64 last_mod_time, gint64 file_size)
652 {
653         int index;
654         char *copy;
655
656         if (!w->file_to_index) {
657                 w->file_to_index = g_hash_table_new (g_str_hash, g_str_equal);
658                 w->index_to_file = g_hash_table_new (NULL, NULL);
659         }
660
661         index = GPOINTER_TO_UINT (g_hash_table_lookup (w->file_to_index, name));
662         if (index > 0)
663                 return index - 1;
664         index = w->line_number_file_index;
665         w->line_number_file_index ++;
666         copy = g_strdup (name);
667         g_hash_table_insert (w->file_to_index, copy, GUINT_TO_POINTER (index + 1));
668         g_hash_table_insert (w->index_to_file, GUINT_TO_POINTER (index + 1), copy);
669
670         return index;
671 }
672
673 char *
674 mono_dwarf_escape_path (const char *name)
675 {
676         if (strchr (name, '\\')) {
677                 char *s;
678                 int len, i, j;
679
680                 len = strlen (name);
681                 s = g_malloc0 ((len + 1) * 2);
682                 j = 0;
683                 for (i = 0; i < len; ++i) {
684                         if (name [i] == '\\') {
685                                 s [j ++] = '\\';
686                                 s [j ++] = '\\';
687                         } else {
688                                 s [j ++] = name [i];
689                         }
690                 }
691                 return s;
692         }
693         return g_strdup (name);
694 }
695
696 static void
697 emit_all_line_number_info (MonoDwarfWriter *w)
698 {
699         int i;
700         GHashTable *dir_to_index, *index_to_dir;
701         GSList *l;
702         GSList *info_list;
703
704         g_assert (w->collect_line_info);
705
706         add_line_number_file_name (w, "<unknown>", 0, 0);
707
708         /* Collect files */
709         info_list = g_slist_reverse (w->line_info);
710         for (l = info_list; l; l = l->next) {
711                 MethodLineNumberInfo *info = l->data;
712                 MonoDebugMethodInfo *minfo;
713                 GPtrArray *source_file_list;
714
715                 // FIXME: Free stuff
716                 minfo = mono_debug_lookup_method (info->method);
717                 if (!minfo)
718                         continue;
719
720                 mono_debug_get_seq_points (minfo, NULL, &source_file_list, NULL, NULL, NULL);
721                 for (i = 0; i < source_file_list->len; ++i) {
722                         MonoDebugSourceInfo *sinfo = g_ptr_array_index (source_file_list, i);
723                         add_line_number_file_name (w, sinfo->source_file, 0, 0);
724                 }
725         }               
726
727         /* Preprocess files */
728         dir_to_index = g_hash_table_new (g_str_hash, g_str_equal);
729         index_to_dir = g_hash_table_new (NULL, NULL);
730         for (i = 0; i < w->line_number_file_index; ++i) {
731                 char *name = g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1));
732                 char *copy;
733                 int dir_index = 0;
734
735                 if (g_path_is_absolute (name)) {
736                         char *dir = g_path_get_dirname (name);
737
738                         dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (dir_to_index, dir));
739                         if (dir_index == 0) {
740                                 dir_index = w->line_number_dir_index;
741                                 w->line_number_dir_index ++;
742                                 copy = g_strdup (dir);
743                                 g_hash_table_insert (dir_to_index, copy, GUINT_TO_POINTER (dir_index + 1));
744                                 g_hash_table_insert (index_to_dir, GUINT_TO_POINTER (dir_index + 1), copy);
745                         } else {
746                                 dir_index --;
747                         }
748
749                         g_free (dir);
750                 }
751         }
752
753         /* Line number info header */
754         emit_section_change (w, ".debug_line", 0);
755         emit_label (w, ".Ldebug_line_section_start");
756         emit_label (w, ".Ldebug_line_start");
757         emit_symbol_diff (w, ".Ldebug_line_end", ".", -4); /* length */
758         emit_int16 (w, 0x2); /* version */
759         emit_symbol_diff (w, ".Ldebug_line_header_end", ".", -4); /* header_length */
760         emit_byte (w, 1); /* minimum_instruction_length */
761         emit_byte (w, 1); /* default_is_stmt */
762         emit_byte (w, LINE_BASE); /* line_base */
763         emit_byte (w, LINE_RANGE); /* line_range */
764         emit_byte (w, OPCODE_BASE); /* opcode_base */
765         emit_byte (w, 0); /* standard_opcode_lengths */
766         emit_byte (w, 1);
767         emit_byte (w, 1);
768         emit_byte (w, 1);
769         emit_byte (w, 1);
770         emit_byte (w, 0);
771         emit_byte (w, 0);
772         emit_byte (w, 0);
773         emit_byte (w, 1);
774         emit_byte (w, 0);
775         emit_byte (w, 0);
776         emit_byte (w, 1);
777
778         /* Includes */
779         emit_section_change (w, ".debug_line", 0);
780         for (i = 0; i < w->line_number_dir_index; ++i) {
781                 char *dir = g_hash_table_lookup (index_to_dir, GUINT_TO_POINTER (i + 1));
782
783                 emit_string (w, mono_dwarf_escape_path (dir));
784         }
785         /* End of Includes */
786         emit_byte (w, 0);
787
788         /* Files */
789         for (i = 0; i < w->line_number_file_index; ++i) {
790                 char *name = g_hash_table_lookup (w->index_to_file, GUINT_TO_POINTER (i + 1));
791                 char *basename = NULL, *dir;
792                 int dir_index = 0;
793
794                 if (g_path_is_absolute (name)) {
795                         dir = g_path_get_dirname (name);
796
797                         dir_index = GPOINTER_TO_UINT (g_hash_table_lookup (dir_to_index, dir));
798                         basename = g_path_get_basename (name);
799                 }
800                                                                                          
801                 if (basename)
802                         emit_string (w, basename);
803                 else
804                         emit_string (w, mono_dwarf_escape_path (name));
805                 emit_uleb128 (w, dir_index);
806                 emit_byte (w, 0);
807                 emit_byte (w, 0);
808         }
809
810         /* End of Files */
811         emit_byte (w, 0);
812
813         emit_label (w, ".Ldebug_line_header_end");
814
815         /* Emit line number table */
816         for (l = info_list; l; l = l->next) {
817                 MethodLineNumberInfo *info = l->data;
818                 MonoDebugMethodJitInfo *dmji;
819
820                 dmji = mono_debug_find_method (info->method, mono_domain_get ());;
821                 emit_line_number_info (w, info->method, info->start_symbol, info->end_symbol, info->code, info->code_size, dmji);
822                 mono_debug_free_method_jit_info (dmji);
823         }
824         g_slist_free (info_list);
825
826         emit_byte (w, 0);
827         emit_byte (w, 1);
828         emit_byte (w, DW_LNE_end_sequence);
829
830         emit_label (w, ".Ldebug_line_end");
831 }
832
833 /*
834  * Some assemblers like apple's do not support subsections, so we can't place
835  * .Ldebug_info_end at the end of the section using subsections. Instead, we 
836  * define it every time something gets added to the .debug_info section.
837  * The apple assember seems to use the last definition.
838  */
839 static void
840 emit_debug_info_end (MonoDwarfWriter *w)
841 {
842         /* This doesn't seem to work/required with recent iphone sdk versions */
843 #if 0
844         if (!mono_img_writer_subsections_supported (w->w))
845                 fprintf (w->fp, "\n.set %sdebug_info_end,.\n", w->temp_prefix);
846 #endif
847 }
848
849 void
850 mono_dwarf_writer_emit_base_info (MonoDwarfWriter *w, const char *cu_name, GSList *base_unwind_program)
851 {
852         char *s, *build_info;
853         int i;
854
855         w->cie_program = base_unwind_program;
856
857         emit_section_change (w, ".debug_abbrev", 0);
858         emit_dwarf_abbrev (w, ABBREV_COMPILE_UNIT, DW_TAG_compile_unit, TRUE, 
859                                            compile_unit_attr, G_N_ELEMENTS (compile_unit_attr));
860         emit_dwarf_abbrev (w, ABBREV_SUBPROGRAM, DW_TAG_subprogram, TRUE, 
861                                            subprogram_attr, G_N_ELEMENTS (subprogram_attr));
862         emit_dwarf_abbrev (w, ABBREV_PARAM, DW_TAG_formal_parameter, FALSE, 
863                                            param_attr, G_N_ELEMENTS (param_attr));
864         emit_dwarf_abbrev (w, ABBREV_PARAM_LOCLIST, DW_TAG_formal_parameter, FALSE, 
865                                            param_loclist_attr, G_N_ELEMENTS (param_loclist_attr));
866         emit_dwarf_abbrev (w, ABBREV_BASE_TYPE, DW_TAG_base_type, FALSE, 
867                                            base_type_attr, G_N_ELEMENTS (base_type_attr));
868         emit_dwarf_abbrev (w, ABBREV_STRUCT_TYPE, DW_TAG_class_type, TRUE, 
869                                            struct_type_attr, G_N_ELEMENTS (struct_type_attr));
870         emit_dwarf_abbrev (w, ABBREV_STRUCT_TYPE_NOCHILDREN, DW_TAG_class_type, FALSE, 
871                                            struct_type_attr, G_N_ELEMENTS (struct_type_attr));
872         emit_dwarf_abbrev (w, ABBREV_DATA_MEMBER, DW_TAG_member, FALSE, 
873                                            data_member_attr, G_N_ELEMENTS (data_member_attr));
874         emit_dwarf_abbrev (w, ABBREV_TYPEDEF, DW_TAG_typedef, FALSE, 
875                                            typedef_attr, G_N_ELEMENTS (typedef_attr));
876         emit_dwarf_abbrev (w, ABBREV_ENUM_TYPE, DW_TAG_enumeration_type, TRUE,
877                                            enum_type_attr, G_N_ELEMENTS (enum_type_attr));
878         emit_dwarf_abbrev (w, ABBREV_ENUMERATOR, DW_TAG_enumerator, FALSE,
879                                            enumerator_attr, G_N_ELEMENTS (enumerator_attr));
880         emit_dwarf_abbrev (w, ABBREV_NAMESPACE, DW_TAG_namespace, TRUE,
881                                            namespace_attr, G_N_ELEMENTS (namespace_attr));
882         emit_dwarf_abbrev (w, ABBREV_VARIABLE, DW_TAG_variable, FALSE,
883                                            variable_attr, G_N_ELEMENTS (variable_attr));
884         emit_dwarf_abbrev (w, ABBREV_VARIABLE_LOCLIST, DW_TAG_variable, FALSE,
885                                            variable_loclist_attr, G_N_ELEMENTS (variable_loclist_attr));
886         emit_dwarf_abbrev (w, ABBREV_POINTER_TYPE, DW_TAG_pointer_type, FALSE,
887                                            pointer_type_attr, G_N_ELEMENTS (pointer_type_attr));
888         emit_dwarf_abbrev (w, ABBREV_REFERENCE_TYPE, DW_TAG_reference_type, FALSE,
889                                            reference_type_attr, G_N_ELEMENTS (reference_type_attr));
890         emit_dwarf_abbrev (w, ABBREV_INHERITANCE, DW_TAG_inheritance, FALSE,
891                                            inheritance_attr, G_N_ELEMENTS (inheritance_attr));
892         emit_dwarf_abbrev (w, ABBREV_TRAMP_SUBPROGRAM, DW_TAG_subprogram, FALSE,
893                                            tramp_subprogram_attr, G_N_ELEMENTS (tramp_subprogram_attr));
894         emit_byte (w, 0);
895
896         emit_section_change (w, ".debug_info", 0);
897         emit_label (w, ".Ldebug_info_start");
898         emit_symbol_diff (w, ".Ldebug_info_end", ".Ldebug_info_begin", 0); /* length */
899         emit_label (w, ".Ldebug_info_begin");
900         emit_int16 (w, 0x2); /* DWARF version 2 */
901         emit_int32 (w, 0); /* .debug_abbrev offset */
902         emit_byte (w, sizeof (gpointer)); /* address size */
903
904         if (mono_img_writer_subsections_supported (w->w) && w->appending) {
905                 /* Emit this into a separate section so it gets placed at the end */
906                 emit_section_change (w, ".debug_info", 1);
907                 emit_byte (w, 0); /* close COMPILE_UNIT */
908                 emit_label (w, ".Ldebug_info_end");
909                 emit_section_change (w, ".debug_info", 0);
910         }
911
912         /* Compilation unit */
913         emit_uleb128 (w, ABBREV_COMPILE_UNIT);
914         build_info = mono_get_runtime_build_info ();
915         s = g_strdup_printf ("Mono AOT Compiler %s", build_info);
916         emit_string (w, s);
917         g_free (build_info);
918         g_free (s);
919         emit_string (w, cu_name);
920         emit_string (w, "");
921         emit_byte (w, DW_LANG_C);
922         emit_pointer_value (w, 0);
923         emit_pointer_value (w, 0);
924         /* offset into .debug_line section */
925         if (w->emit_line)
926                 emit_symbol_diff (w, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
927         else
928                 emit_pointer_value (w, 0);
929
930         /* Base types */
931         for (i = 0; i < G_N_ELEMENTS (basic_types); ++i) {
932                 emit_label (w, basic_types [i].die_name);
933                 emit_uleb128 (w, ABBREV_BASE_TYPE);
934                 emit_byte (w, basic_types [i].size);
935                 emit_byte (w, basic_types [i].encoding);
936                 emit_string (w, basic_types [i].name);
937         }
938
939         emit_debug_info_end (w);
940
941         /* debug_loc section */
942         emit_section_change (w, ".debug_loc", 0);
943         emit_label (w, ".Ldebug_loc_start");
944
945         emit_cie (w);
946 }
947
948 /*
949  * mono_dwarf_writer_close:
950  *
951  *   Finalize the emitted debugging info.
952  */
953 void
954 mono_dwarf_writer_close (MonoDwarfWriter *w)
955 {
956         if (!w->appending) {
957                 emit_section_change (w, ".debug_info", 0);
958                 emit_byte (w, 0); /* close COMPILE_UNIT */
959                 emit_label (w, ".Ldebug_info_end");
960         }
961
962         if (w->collect_line_info)
963                 emit_all_line_number_info (w);
964 }
965
966 static void emit_type (MonoDwarfWriter *w, MonoType *t);
967 static const char* get_type_die (MonoDwarfWriter *w, MonoType *t);
968
969 static const char*
970 get_class_die (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype)
971 {
972         GHashTable *cache;
973
974         if (vtype)
975                 cache = w->class_to_vtype_die;
976         else
977                 cache = w->class_to_die;
978
979         return g_hash_table_lookup (cache, klass);
980 }
981
982 /* Returns the local symbol pointing to the emitted debug info */
983 static char*
984 emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype)
985 {
986         char *die, *pointer_die, *reference_die;
987         char *full_name, *p;
988         gpointer iter;
989         MonoClassField *field;
990         const char *fdie;
991         int k;
992         gboolean emit_namespace = FALSE, has_children;
993         GHashTable *cache;
994
995         if (vtype)
996                 cache = w->class_to_vtype_die;
997         else
998                 cache = w->class_to_die;
999
1000         die = g_hash_table_lookup (cache, klass);
1001         if (die)
1002                 return die;
1003
1004         if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || (klass->byval_arg.type == MONO_TYPE_OBJECT) || klass->byval_arg.type == MONO_TYPE_GENERICINST || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype) ||
1005                   (klass->byval_arg.type >= MONO_TYPE_BOOLEAN && klass->byval_arg.type <= MONO_TYPE_R8 && !vtype)))
1006                 return NULL;
1007
1008         /*
1009          * FIXME: gdb can't handle namespaces in languages it doesn't know about.
1010          */
1011         /*
1012         if (klass->name_space && klass->name_space [0] != '\0')
1013                 emit_namespace = TRUE;
1014         */
1015         if (emit_namespace) {
1016                 emit_uleb128 (w, ABBREV_NAMESPACE);
1017                 emit_string (w, klass->name_space);
1018         }
1019
1020         full_name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space ? "." : "", klass->name);
1021         /* 
1022          * gdb doesn't support namespaces for non-C++ dwarf objects, so use _
1023          * to separate components.
1024          */
1025         for (p = full_name; *p; p ++)
1026                 if (*p == '.')
1027                         *p = '_';
1028
1029         die = g_strdup_printf (".LTDIE_%d", w->tdie_index);
1030         pointer_die = g_strdup_printf (".LTDIE_%d_POINTER", w->tdie_index);
1031         reference_die = g_strdup_printf (".LTDIE_%d_REFERENCE", w->tdie_index);
1032         w->tdie_index ++;
1033
1034         g_hash_table_insert (w->class_to_pointer_die, klass, pointer_die);
1035         g_hash_table_insert (w->class_to_reference_die, klass, reference_die);
1036         g_hash_table_insert (cache, klass, die);
1037
1038         if (klass->enumtype) {
1039                 int size = mono_class_value_size (mono_class_from_mono_type (mono_class_enum_basetype (klass)), NULL);
1040
1041                 emit_label (w, die);
1042
1043                 emit_uleb128 (w, ABBREV_ENUM_TYPE);
1044                 emit_string (w, full_name);
1045                 emit_uleb128 (w, size);
1046                 for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
1047                         if (basic_types [k].type == mono_class_enum_basetype (klass)->type)
1048                                 break;
1049                 g_assert (k < G_N_ELEMENTS (basic_types));
1050                 emit_symbol_diff (w, basic_types [k].die_name, ".Ldebug_info_start", 0);
1051
1052                 /* Emit enum values */
1053                 iter = NULL;
1054                 while ((field = mono_class_get_fields (klass, &iter))) {
1055                         const char *p;
1056                         MonoTypeEnum def_type;
1057
1058                         if (strcmp ("value__", mono_field_get_name (field)) == 0)
1059                                 continue;
1060                         if (mono_field_is_deleted (field))
1061                                 continue;
1062
1063                         emit_uleb128 (w, ABBREV_ENUMERATOR);
1064                         emit_string (w, mono_field_get_name (field));
1065
1066                         p = mono_class_get_field_default_value (field, &def_type);
1067                         /* len = */ mono_metadata_decode_blob_size (p, &p);
1068                         switch (mono_class_enum_basetype (klass)->type) {
1069                         case MONO_TYPE_U1:
1070                         case MONO_TYPE_I1:
1071                         case MONO_TYPE_BOOLEAN:
1072                                 emit_sleb128 (w, *p);
1073                                 break;
1074                         case MONO_TYPE_U2:
1075                         case MONO_TYPE_I2:
1076                         case MONO_TYPE_CHAR:
1077                                 emit_sleb128 (w, read16 (p));
1078                                 break;
1079                         case MONO_TYPE_U4:
1080                         case MONO_TYPE_I4:
1081                                 emit_sleb128 (w, read32 (p));
1082                                 break;
1083                         case MONO_TYPE_U8:
1084                         case MONO_TYPE_I8:
1085                                 emit_sleb128 (w, read64 (p));
1086                                 break;
1087                         case MONO_TYPE_I:
1088                         case MONO_TYPE_U:
1089 #if SIZEOF_VOID_P == 8
1090                                 emit_sleb128 (w, read64 (p));
1091 #else
1092                                 emit_sleb128 (w, read32 (p));
1093 #endif
1094                                 break;
1095                         default:
1096                                 g_assert_not_reached ();
1097                         }
1098                 }
1099
1100                 has_children = TRUE;
1101         } else {
1102                 guint8 buf [128];
1103                 guint8 *p;
1104                 char *parent_die;
1105
1106                 if (klass->parent)
1107                         parent_die = emit_class_dwarf_info (w, klass->parent, FALSE);
1108                 else
1109                         parent_die = NULL;
1110
1111                 /* Emit field types */
1112                 iter = NULL;
1113                 while ((field = mono_class_get_fields (klass, &iter))) {
1114                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1115                                 continue;
1116
1117                         emit_type (w, field->type);
1118                 }
1119
1120                 iter = NULL;
1121                 has_children = parent_die || mono_class_get_fields (klass, &iter);
1122
1123                 emit_label (w, die);
1124
1125                 emit_uleb128 (w, has_children ? ABBREV_STRUCT_TYPE : ABBREV_STRUCT_TYPE_NOCHILDREN);
1126                 emit_string (w, full_name);
1127                 emit_uleb128 (w, klass->instance_size);
1128
1129                 if (parent_die) {
1130                         emit_uleb128 (w, ABBREV_INHERITANCE);
1131                         emit_symbol_diff (w, parent_die, ".Ldebug_info_start", 0);
1132
1133                         p = buf;
1134                         *p ++= DW_OP_plus_uconst;
1135                         encode_uleb128 (0, p, &p);
1136                         emit_byte (w, p - buf);
1137                         emit_bytes (w, buf, p - buf);
1138                 }
1139
1140                 /* Emit fields */
1141                 iter = NULL;
1142                 while ((field = mono_class_get_fields (klass, &iter))) {
1143                         if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1144                                 continue;
1145
1146                         fdie = get_type_die (w, field->type);
1147                         if (fdie) {
1148                                 emit_uleb128 (w, ABBREV_DATA_MEMBER);
1149                                 emit_string (w, field->name);
1150                                 emit_symbol_diff (w, fdie, ".Ldebug_info_start", 0);
1151                                 /* location */
1152                                 p = buf;
1153                                 *p ++= DW_OP_plus_uconst;
1154                                 if (klass->valuetype && vtype)
1155                                         encode_uleb128 (field->offset - sizeof (MonoObject), p, &p);
1156                                 else
1157                                         encode_uleb128 (field->offset, p, &p);
1158
1159                                 emit_byte (w, p - buf);
1160                                 emit_bytes (w, buf, p - buf);
1161                         }
1162                 }
1163         }
1164
1165         /* Type end */
1166         if (has_children)
1167                 emit_uleb128 (w, 0x0);
1168
1169         /* Add a typedef, so we can reference the type without a 'struct' in gdb */
1170         emit_uleb128 (w, ABBREV_TYPEDEF);
1171         emit_string (w, full_name);
1172         emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
1173
1174         /* Add a pointer type */
1175         emit_label (w, pointer_die);
1176
1177         emit_uleb128 (w, ABBREV_POINTER_TYPE);
1178         emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
1179
1180         /* Add a reference type */
1181         emit_label (w, reference_die);
1182
1183         emit_uleb128 (w, ABBREV_REFERENCE_TYPE);
1184         emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
1185
1186         g_free (full_name);
1187
1188         if (emit_namespace) {
1189                 /* Namespace end */
1190                 emit_uleb128 (w, 0x0);
1191         }
1192
1193         return die;
1194 }
1195
1196 static gboolean base_types_emitted [64];
1197
1198 static const char*
1199 get_type_die (MonoDwarfWriter *w, MonoType *t)
1200 {
1201         MonoClass *klass = mono_class_from_mono_type (t);
1202         int j;
1203         const char *tdie;
1204
1205         if (t->byref) {
1206                 if (t->type == MONO_TYPE_VALUETYPE) {
1207                         tdie = g_hash_table_lookup (w->class_to_pointer_die, klass);
1208                 }
1209                 else {
1210                         tdie = get_class_die (w, klass, FALSE);
1211                         /* Should return a pointer type to a reference */
1212                 }
1213                 // FIXME:
1214                 t = &mono_defaults.int_class->byval_arg;
1215         }
1216         for (j = 0; j < G_N_ELEMENTS (basic_types); ++j)
1217                 if (basic_types [j].type == t->type)
1218                         break;
1219         if (j < G_N_ELEMENTS (basic_types)) {
1220                 tdie = basic_types [j].die_name;
1221         } else {
1222                 switch (t->type) {
1223                 case MONO_TYPE_CLASS:
1224                         tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
1225                         //tdie = ".LDIE_OBJECT";
1226                         break;
1227                 case MONO_TYPE_ARRAY:
1228                         tdie = ".LDIE_OBJECT";
1229                         break;
1230                 case MONO_TYPE_VALUETYPE:
1231                         if (klass->enumtype)
1232                                 tdie = get_class_die (w, klass, FALSE);
1233                         else
1234                                 tdie = ".LDIE_I4";
1235                         break;
1236                 case MONO_TYPE_GENERICINST:
1237                         if (!MONO_TYPE_ISSTRUCT (t)) {
1238                                 tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
1239                         } else {
1240                                 tdie = ".LDIE_I4";
1241                         }
1242                         break;
1243                 case MONO_TYPE_PTR:
1244                         tdie = ".LDIE_I";
1245                         break;
1246                 default:
1247                         tdie = ".LDIE_I4";
1248                         break;
1249                 }
1250         }
1251
1252         g_assert (tdie);
1253
1254         return tdie;
1255 }
1256
1257 static void
1258 emit_type (MonoDwarfWriter *w, MonoType *t)
1259 {
1260         MonoClass *klass = mono_class_from_mono_type (t);
1261         int j;
1262         const char *tdie;
1263
1264         if (t->byref) {
1265                 if (t->type == MONO_TYPE_VALUETYPE) {
1266                         tdie = emit_class_dwarf_info (w, klass, TRUE);
1267                         if (tdie)
1268                                 return;
1269                 }
1270                 else {
1271                         emit_class_dwarf_info (w, klass, FALSE);
1272                 }
1273                 // FIXME:
1274                 t = &mono_defaults.int_class->byval_arg;
1275         }
1276         for (j = 0; j < G_N_ELEMENTS (basic_types); ++j)
1277                 if (basic_types [j].type == t->type)
1278                         break;
1279         if (j < G_N_ELEMENTS (basic_types)) {
1280                 /* Emit a boxed version of base types */
1281                 if (j < 64 && !base_types_emitted [j]) {
1282                         emit_class_dwarf_info (w, klass, FALSE);
1283                         base_types_emitted [j] = TRUE;
1284                 }
1285         } else {
1286                 switch (t->type) {
1287                 case MONO_TYPE_CLASS:
1288                         emit_class_dwarf_info (w, klass, FALSE);
1289                         break;
1290                 case MONO_TYPE_ARRAY:
1291                         break;
1292                 case MONO_TYPE_VALUETYPE:
1293                         if (klass->enumtype)
1294                                 emit_class_dwarf_info (w, klass, FALSE);
1295                         break;
1296                 case MONO_TYPE_GENERICINST:
1297                         if (!MONO_TYPE_ISSTRUCT (t))
1298                                 emit_class_dwarf_info (w, klass, FALSE);
1299                         break;
1300                 case MONO_TYPE_PTR:
1301                         break;
1302                 default:
1303                         break;
1304                 }
1305         }
1306 }
1307
1308 static void
1309 emit_var_type (MonoDwarfWriter *w, MonoType *t)
1310 {
1311         const char *tdie;
1312
1313         tdie = get_type_die (w, t);
1314
1315         emit_symbol_diff (w, tdie, ".Ldebug_info_start", 0);
1316 }
1317
1318 static void
1319 encode_var_location (MonoDwarfWriter *w, MonoInst *ins, guint8 *p, guint8 **endp)
1320 {
1321         /* location */
1322         /* FIXME: This needs a location list, since the args can go from reg->stack */
1323         if (!ins || ins->flags & MONO_INST_IS_DEAD) {
1324                 /* gdb treats this as optimized out */
1325         } else if (ins->opcode == OP_REGVAR) {
1326                 *p = DW_OP_reg0 + mono_hw_reg_to_dwarf_reg (ins->dreg);
1327                 p ++;
1328         } else if (ins->opcode == OP_REGOFFSET) {
1329                 *p ++= DW_OP_breg0 + mono_hw_reg_to_dwarf_reg (ins->inst_basereg);
1330                 encode_sleb128 (ins->inst_offset, p, &p);
1331         } else {
1332                 // FIXME:
1333                 *p ++ = DW_OP_reg0;
1334         }
1335
1336         *endp = p;
1337 }
1338
1339 static void
1340 emit_loclist (MonoDwarfWriter *w, MonoInst *ins,
1341                           guint8 *loclist_begin_addr, guint8 *loclist_end_addr,
1342                           guint8 *expr, guint32 expr_len)
1343 {
1344         char label [128];
1345
1346         emit_push_section (w, ".debug_loc", 0);
1347         sprintf (label, ".Lloclist_%d", w->loclist_index ++ );
1348         emit_label (w, label);
1349
1350         emit_pointer_value (w, loclist_begin_addr);
1351         emit_pointer_value (w, loclist_end_addr);
1352         emit_byte (w, expr_len % 256);
1353         emit_byte (w, expr_len / 256);
1354         emit_bytes (w, expr, expr_len);
1355
1356         emit_pointer_value (w, NULL);
1357         emit_pointer_value (w, NULL);
1358
1359         emit_pop_section (w);
1360         emit_symbol_diff (w, label, ".Ldebug_loc_start", 0);
1361 }
1362
1363 /* 
1364  * MonoDisHelper->tokener doesn't take an IP argument, and we can't add one since 
1365  * it is a public header.
1366  */
1367 static const guint8 *token_handler_ip;
1368
1369 static char*
1370 token_handler (MonoDisHelper *dh, MonoMethod *method, guint32 token)
1371 {
1372         MonoError error;
1373         char *res, *desc;
1374         MonoMethod *cmethod;
1375         MonoClass *klass;
1376         MonoClassField *field;
1377         gpointer data = NULL;
1378
1379         if (method->wrapper_type)
1380                 data = mono_method_get_wrapper_data (method, token);
1381
1382         switch (*token_handler_ip) {
1383         case CEE_ISINST:
1384         case CEE_CASTCLASS:
1385         case CEE_LDELEMA:
1386                 if (method->wrapper_type) {
1387                         klass = data;
1388                 } else {
1389                         klass = mono_class_get_checked (method->klass->image, token, &error);
1390                         g_assert (mono_error_ok (&error)); /* FIXME error handling */
1391                 }
1392                 res = g_strdup_printf ("<%s>", klass->name);
1393                 break;
1394         case CEE_NEWOBJ:
1395         case CEE_CALL:
1396         case CEE_CALLVIRT:
1397                 if (method->wrapper_type)
1398                         cmethod = data;
1399                 else
1400                         cmethod = mono_get_method_full (method->klass->image, token, NULL, NULL);
1401                 desc = mono_method_full_name (cmethod, TRUE);
1402                 res = g_strdup_printf ("<%s>", desc);
1403                 g_free (desc);
1404                 break;
1405         case CEE_CALLI:
1406                 if (method->wrapper_type) {
1407                         desc = mono_signature_get_desc (data, FALSE);
1408                         res = g_strdup_printf ("<%s>", desc);
1409                         g_free (desc);
1410                 } else {
1411                         res = g_strdup_printf ("<0x%08x>", token);
1412                 }
1413                 break;
1414         case CEE_LDFLD:
1415         case CEE_LDSFLD:
1416         case CEE_STFLD:
1417         case CEE_STSFLD:
1418                 if (method->wrapper_type) {
1419                         field = data;
1420                 } else {
1421                         field = mono_field_from_token_checked (method->klass->image, token, &klass, NULL,  &error);
1422                         g_assert (mono_error_ok (&error)); /* FIXME error handling */
1423                 }
1424                 desc = mono_field_full_name (field);
1425                 res = g_strdup_printf ("<%s>", desc);
1426                 g_free (desc);
1427                 break;
1428         default:
1429                 res = g_strdup_printf ("<0x%08x>", token);
1430                 break;
1431         }
1432
1433         return res;
1434 }
1435
1436 /*
1437  * disasm_ins:
1438  *
1439  *   Produce a disassembled form of the IL instruction at IP. This is an extension
1440  * of mono_disasm_code_one () which can disasm tokens, handle wrapper methods, and
1441  * CEE_MONO_ opcodes.
1442  */
1443 static char*
1444 disasm_ins (MonoMethod *method, const guchar *ip, const guint8 **endip)
1445 {
1446         char *dis;
1447         MonoDisHelper dh;
1448         MonoMethodHeader *header = mono_method_get_header (method);
1449
1450         memset (&dh, 0, sizeof (dh));
1451         dh.newline = "";
1452         dh.label_format = "IL_%04x: ";
1453         dh.label_target = "IL_%04x";
1454         dh.tokener = token_handler;
1455
1456         token_handler_ip = ip;
1457         if (*ip == MONO_CUSTOM_PREFIX) {
1458                 guint32 token;
1459                 gpointer data;
1460
1461                 switch (ip [1]) {
1462                 case CEE_MONO_ICALL: {
1463                         MonoJitICallInfo *info;
1464
1465                         token = read32 (ip + 2);
1466                         data = mono_method_get_wrapper_data (method, token);
1467                         info = mono_find_jit_icall_by_addr (data);
1468                         g_assert (info);
1469
1470                         dis = g_strdup_printf ("IL_%04x: mono_icall <%s>", (int)(ip - header->code), info->name);
1471                         ip += 6;
1472                         break;
1473                 }
1474                 case CEE_MONO_CLASSCONST: {
1475                         token = read32 (ip + 2);
1476                         data = mono_method_get_wrapper_data (method, token);
1477
1478                         dis = g_strdup_printf ("IL_%04x: mono_classconst <%s>", (int)(ip - header->code), ((MonoClass*)data)->name);
1479                         ip += 6;
1480                         break;
1481                 }
1482                 default:
1483                         dis = mono_disasm_code_one (&dh, method, ip, &ip);
1484                 }
1485         } else {
1486                 dis = mono_disasm_code_one (&dh, method, ip, &ip);
1487         }
1488         token_handler_ip = NULL;
1489
1490         *endip = ip;
1491         mono_metadata_free_mh (header);
1492         return dis;
1493 }
1494
1495 static gint32
1496 il_offset_from_address (MonoMethod *method, MonoDebugMethodJitInfo *jit, 
1497                                                 guint32 native_offset)
1498 {
1499         int i;
1500
1501         if (!jit->line_numbers)
1502                 return -1;
1503
1504         for (i = jit->num_line_numbers - 1; i >= 0; i--) {
1505                 MonoDebugLineNumberEntry lne = jit->line_numbers [i];
1506
1507                 if (lne.native_offset <= native_offset)
1508                         return lne.il_offset;
1509         }
1510
1511         return -1;
1512 }
1513
1514 static int max_special_addr_diff = 0;
1515
1516 static inline void
1517 emit_advance_op (MonoDwarfWriter *w, int line_diff, int addr_diff)
1518 {
1519         gint64 opcode = 0;
1520
1521         /* Use a special opcode if possible */
1522         if (line_diff - LINE_BASE >= 0 && line_diff - LINE_BASE < LINE_RANGE) {
1523                 if (max_special_addr_diff == 0)
1524                         max_special_addr_diff = (255 - OPCODE_BASE) / LINE_RANGE;
1525
1526                 if (addr_diff > max_special_addr_diff && (addr_diff < 2 * max_special_addr_diff)) {
1527                         emit_byte (w, DW_LNS_const_add_pc);
1528                         addr_diff -= max_special_addr_diff;
1529                 }
1530
1531                 opcode = (line_diff - LINE_BASE) + (LINE_RANGE * addr_diff) + OPCODE_BASE;
1532                 if (opcode > 255)
1533                         opcode = 0;
1534         }
1535
1536         if (opcode != 0) {
1537                 emit_byte (w, opcode);
1538         } else {
1539                 //printf ("large: %d %d %d\n", line_diff, addr_diff, max_special_addr_diff);
1540                 emit_byte (w, DW_LNS_advance_line);
1541                 emit_sleb128 (w, line_diff);
1542                 emit_byte (w, DW_LNS_advance_pc);
1543                 emit_sleb128 (w, addr_diff);
1544                 emit_byte (w, DW_LNS_copy);
1545         }
1546 }
1547
1548 static gint
1549 compare_lne (MonoDebugLineNumberEntry *a, MonoDebugLineNumberEntry *b)
1550 {
1551         if (a->native_offset == b->native_offset)
1552                 return a->il_offset - b->il_offset;
1553         else
1554                 return a->native_offset - b->native_offset;
1555 }
1556
1557 static void
1558 emit_line_number_info (MonoDwarfWriter *w, MonoMethod *method, 
1559                                            char *start_symbol, char *end_symbol,
1560                                            guint8 *code, guint32 code_size,
1561                                            MonoDebugMethodJitInfo *debug_info)
1562 {
1563         guint32 prev_line = 0;
1564         guint32 prev_native_offset = 0;
1565         int i, file_index, il_offset, prev_il_offset;
1566         gboolean first = TRUE;
1567         MonoDebugSourceLocation *loc;
1568         char *prev_file_name = NULL;
1569         MonoMethodHeader *header = mono_method_get_header (method);
1570         MonoDebugMethodInfo *minfo;
1571         MonoDebugLineNumberEntry *ln_array;
1572         int *native_to_il_offset = NULL;
1573         
1574         if (!w->emit_line) {
1575                 mono_metadata_free_mh (header);
1576                 return;
1577         }
1578
1579         minfo = mono_debug_lookup_method (method);
1580
1581         /* Compute the native->IL offset mapping */
1582
1583         g_assert (code_size);
1584
1585         ln_array = g_new0 (MonoDebugLineNumberEntry, debug_info->num_line_numbers);
1586         memcpy (ln_array, debug_info->line_numbers, debug_info->num_line_numbers * sizeof (MonoDebugLineNumberEntry));
1587
1588         qsort (ln_array, debug_info->num_line_numbers, sizeof (MonoDebugLineNumberEntry), (gpointer)compare_lne);
1589
1590         native_to_il_offset = g_new0 (int, code_size + 1);
1591
1592         for (i = 0; i < debug_info->num_line_numbers; ++i) {
1593                 int j;
1594                 MonoDebugLineNumberEntry *lne = &ln_array [i];
1595
1596                 if (i == 0) {
1597                         for (j = 0; j < lne->native_offset; ++j)
1598                                 native_to_il_offset [j] = -1;
1599                 }
1600
1601                 if (i < debug_info->num_line_numbers - 1) {
1602                         MonoDebugLineNumberEntry *lne_next = &ln_array [i + 1];
1603
1604                         for (j = lne->native_offset; j < lne_next->native_offset; ++j)
1605                                 native_to_il_offset [j] = lne->il_offset;
1606                 } else {
1607                         for (j = lne->native_offset; j < code_size; ++j)
1608                                 native_to_il_offset [j] = lne->il_offset;
1609                 }
1610         }
1611         g_free (ln_array);
1612
1613         prev_line = 1;
1614         prev_il_offset = -1;
1615
1616         w->cur_file_index = -1;
1617         for (i = 0; i < code_size; ++i) {
1618                 int line_diff, addr_diff;
1619
1620                 if (!minfo)
1621                         continue;
1622
1623                 if (!debug_info->line_numbers)
1624                         continue;
1625
1626                 if (native_to_il_offset)
1627                         il_offset = native_to_il_offset [i];
1628                 else
1629                         il_offset = il_offset_from_address (method, debug_info, i);
1630                 /*
1631                 il_offset = il_offset_from_address (method, debug_info, i);
1632
1633                 g_assert (il_offset == native_to_il_offset [i]);
1634                 */
1635
1636                 il_offset = native_to_il_offset [i];
1637                 if (il_offset < 0)
1638                         continue;
1639
1640                 if (il_offset == prev_il_offset)
1641                         continue;
1642
1643                 prev_il_offset = il_offset;
1644
1645                 loc = mono_debug_symfile_lookup_location (minfo, il_offset);
1646                 if (!(loc && loc->source_file))
1647                         continue;
1648
1649                 line_diff = (gint32)loc->row - (gint32)prev_line;
1650                 addr_diff = i - prev_native_offset;
1651
1652                 if (first) {    
1653                         emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
1654
1655                         emit_byte (w, 0);
1656                         emit_byte (w, sizeof (gpointer) + 1);
1657                         emit_byte (w, DW_LNE_set_address);
1658                         if (start_symbol)
1659                                 emit_pointer_unaligned (w, start_symbol);
1660                         else
1661                                 emit_pointer_value (w, code);
1662                         first = FALSE;
1663                 }
1664
1665                 if (loc->row != prev_line) {
1666                         if (!prev_file_name || strcmp (loc->source_file, prev_file_name) != 0) {
1667                                 /* Add an entry to the file table */
1668                                 /* FIXME: Avoid duplicates */
1669                                 if (w->collect_line_info)
1670                                         file_index = get_line_number_file_name (w, loc->source_file) + 1;
1671                                 else
1672                                         file_index = emit_line_number_file_name (w, loc->source_file, 0, 0);
1673                                 g_free (prev_file_name);
1674                                 prev_file_name = g_strdup (loc->source_file);
1675
1676                                 if (w->cur_file_index != file_index) {
1677                                         emit_byte (w, DW_LNS_set_file);
1678                                         emit_uleb128 (w, file_index);
1679                                         emit_byte (w, DW_LNS_copy);
1680                                         w->cur_file_index = file_index;
1681                                 }                                       
1682                         }
1683                 }
1684
1685                 if (loc->row != prev_line) {
1686                         if (prev_native_offset == 0)
1687                                 emit_byte (w, DW_LNE_set_prologue_end);
1688
1689                         //printf ("X: %p(+0x%x) %d %s:%d(+%d)\n", code + i, addr_diff, loc->il_offset, loc->source_file, loc->row, line_diff);
1690                         emit_advance_op (w, line_diff, addr_diff);
1691
1692                         prev_line = loc->row;
1693                         prev_native_offset = i;
1694                 }
1695
1696                 mono_debug_symfile_free_location (loc);
1697                 first = FALSE;
1698         }
1699
1700         g_free (native_to_il_offset);
1701         g_free (prev_file_name);
1702
1703         if (!first) {
1704                 emit_byte (w, DW_LNS_advance_pc);
1705                 emit_sleb128 (w, code_size - prev_native_offset);
1706                 emit_byte (w, DW_LNS_copy);
1707
1708                 emit_byte (w, 0);
1709                 emit_byte (w, 1);
1710                 emit_byte (w, DW_LNE_end_sequence);
1711         } else if (!start_symbol) {
1712                 /* No debug info, XDEBUG mode */
1713                 char *name, *dis;
1714                 const guint8 *ip = header->code;
1715                 int prev_line, prev_native_offset;
1716                 int *il_to_line;
1717
1718                 /*
1719                  * Emit the IL code into a temporary file and emit line number info
1720                  * referencing that file.
1721                  */
1722
1723                 name = mono_method_full_name (method, TRUE);
1724                 fprintf (w->il_file, "// %s\n", name);
1725                 w->il_file_line_index ++;
1726                 g_free (name);
1727
1728                 il_to_line = g_new0 (int, header->code_size);
1729
1730                 emit_section_change (w, ".debug_line", LINE_SUBSECTION_DATA);
1731                 emit_byte (w, 0);
1732                 emit_byte (w, sizeof (gpointer) + 1);
1733                 emit_byte (w, DW_LNE_set_address);
1734                 emit_pointer_value (w, code);
1735
1736                 // FIXME: Optimize this
1737                 while (ip < header->code + header->code_size) {
1738                         int il_offset = ip - header->code;
1739
1740                         /* Emit IL */
1741                         w->il_file_line_index ++;
1742
1743                         dis = disasm_ins (method, ip, &ip);
1744                         fprintf (w->il_file, "%s\n", dis);
1745                         g_free (dis);
1746
1747                         il_to_line [il_offset] = w->il_file_line_index;
1748                 }
1749
1750                 /* Emit line number info */
1751                 prev_line = 1;
1752                 prev_native_offset = 0;
1753                 for (i = 0; i < debug_info->num_line_numbers; ++i) {
1754                         MonoDebugLineNumberEntry *lne = &debug_info->line_numbers [i];
1755                         int line;
1756
1757                         if (lne->il_offset >= header->code_size)
1758                                 continue;
1759                         line = il_to_line [lne->il_offset];
1760                         if (!line) {
1761                                 /* 
1762                                  * This seems to happen randomly, it looks like il_offset points
1763                                  * into the middle of an instruction.
1764                                  */
1765                                 continue;
1766                                 /*
1767                                 printf ("%s\n", mono_method_full_name (method, TRUE));
1768                                 printf ("%d %d\n", lne->il_offset, header->code_size);
1769                                 g_assert (line);
1770                                 */
1771                         }
1772
1773                         if (line - prev_line != 0) {
1774                                 emit_advance_op (w, line - prev_line, (gint32)lne->native_offset - prev_native_offset);
1775
1776                                 prev_line = line;
1777                                 prev_native_offset = lne->native_offset;
1778                         }
1779                 }
1780
1781                 emit_byte (w, DW_LNS_advance_pc);
1782                 emit_sleb128 (w, code_size - prev_native_offset);
1783                 emit_byte (w, DW_LNS_copy);
1784
1785                 emit_byte (w, 0);
1786                 emit_byte (w, 1);
1787                 emit_byte (w, DW_LNE_end_sequence);
1788
1789                 fflush (w->il_file);
1790                 g_free (il_to_line);
1791         }
1792         mono_metadata_free_mh (header);
1793 }
1794
1795 static MonoMethodVar*
1796 find_vmv (MonoCompile *cfg, MonoInst *ins)
1797 {
1798         int j;
1799
1800         if (cfg->varinfo) {
1801                 for (j = 0; j < cfg->num_varinfo; ++j) {
1802                         if (cfg->varinfo [j] == ins)
1803                                 break;
1804                 }
1805
1806                 if (j < cfg->num_varinfo) {
1807                         return MONO_VARINFO (cfg, j);
1808                 }
1809         }
1810
1811         return NULL;
1812 }
1813
1814 void
1815 mono_dwarf_writer_emit_method (MonoDwarfWriter *w, MonoCompile *cfg, MonoMethod *method, char *start_symbol, char *end_symbol, char *linkage_name,
1816                                                            guint8 *code, guint32 code_size, MonoInst **args, MonoInst **locals, GSList *unwind_info, MonoDebugMethodJitInfo *debug_info)
1817 {
1818         char *name;
1819         MonoMethodSignature *sig;
1820         MonoMethodHeader *header;
1821         char **names;
1822         MonoDebugLocalsInfo *locals_info;
1823         MonoDebugMethodInfo *minfo;
1824         MonoDebugSourceLocation *loc = NULL;
1825         int i;
1826         guint8 buf [128];
1827         guint8 *p;
1828
1829         emit_section_change (w, ".debug_info", 0);
1830
1831         sig = mono_method_signature (method);
1832         header = mono_method_get_header (method);
1833
1834         /* Parameter types */
1835         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
1836                 MonoType *t;
1837
1838                 if (i == 0 && sig->hasthis) {
1839                         if (method->klass->valuetype)
1840                                 t = &method->klass->this_arg;
1841                         else
1842                                 t = &method->klass->byval_arg;
1843                 } else {
1844                         t = sig->params [i - sig->hasthis];
1845                 }
1846
1847                 emit_type (w, t);
1848         }
1849         //emit_type (w, &mono_defaults.int32_class->byval_arg);
1850
1851         /* Local types */
1852         for (i = 0; i < header->num_locals; ++i) {
1853                 emit_type (w, header->locals [i]);
1854         }
1855
1856         minfo = mono_debug_lookup_method (method);
1857         if (minfo)
1858                 loc = mono_debug_symfile_lookup_location (minfo, 0);
1859
1860         /* Subprogram */
1861         names = g_new0 (char *, sig->param_count);
1862         mono_method_get_param_names (method, (const char **) names);
1863
1864         emit_uleb128 (w, ABBREV_SUBPROGRAM);
1865         /* DW_AT_name */
1866         name = mono_method_full_name (method, FALSE);
1867         emit_string (w, name);
1868         /* DW_AT_MIPS_linkage_name */
1869         if (linkage_name)
1870                 emit_string (w, linkage_name);
1871         else
1872                 emit_string (w, "");
1873         /* DW_AT_decl_file/DW_AT_decl_line */
1874         if (loc) {
1875                 int file_index = add_line_number_file_name (w, loc->source_file, 0, 0);
1876                 emit_uleb128 (w, file_index + 1);
1877                 emit_uleb128 (w, loc->row);
1878         } else {
1879                 emit_uleb128 (w, 0);
1880                 emit_uleb128 (w, 0);
1881         }
1882 #ifndef TARGET_IOS
1883         emit_string (w, name);
1884 #endif
1885         g_free (name);
1886         if (start_symbol) {
1887                 emit_pointer_unaligned (w, start_symbol);
1888                 emit_pointer_unaligned (w, end_symbol);
1889         } else {
1890                 emit_pointer_value (w, code);
1891                 emit_pointer_value (w, code + code_size);
1892         }
1893         /* frame_base */
1894         emit_byte (w, 2);
1895         emit_byte (w, DW_OP_breg6);
1896         emit_byte (w, 16);
1897
1898         /* Parameters */
1899         for (i = 0; i < sig->param_count + sig->hasthis; ++i) {
1900                 MonoInst *arg = args ? args [i] : NULL;
1901                 MonoType *t;
1902                 const char *pname;
1903                 char pname_buf [128];
1904                 MonoMethodVar *vmv = NULL;
1905                 gboolean need_loclist = FALSE;
1906
1907                 vmv = find_vmv (cfg, arg);
1908                 if (code && vmv && (vmv->live_range_start || vmv->live_range_end))
1909                         need_loclist = TRUE;
1910
1911                 if (i == 0 && sig->hasthis) {
1912                         if (method->klass->valuetype)
1913                                 t = &method->klass->this_arg;
1914                         else
1915                                 t = &method->klass->byval_arg;
1916                         pname = "this";
1917                 } else {
1918                         t = sig->params [i - sig->hasthis];
1919                         pname = names [i - sig->hasthis];
1920                 }
1921
1922                 emit_uleb128 (w, need_loclist ? ABBREV_PARAM_LOCLIST : ABBREV_PARAM);
1923                 /* name */
1924                 if (pname[0] == '\0') {
1925                         sprintf (pname_buf, "param%d", i - sig->hasthis);
1926                         pname = pname_buf;
1927                 }
1928                 emit_string (w, pname);
1929                 /* type */
1930                 if (!arg || arg->flags & MONO_INST_IS_DEAD)
1931                         emit_var_type (w, &mono_defaults.int32_class->byval_arg);
1932                 else
1933                         emit_var_type (w, t);
1934
1935                 p = buf;
1936                 encode_var_location (w, arg, p, &p);
1937                 if (need_loclist) {
1938                         vmv->live_range_start = 0;
1939                         if (vmv->live_range_end == 0)
1940                                 /* FIXME: Uses made in calls are not recorded */
1941                                 vmv->live_range_end = code_size;
1942                         emit_loclist (w, arg, code + vmv->live_range_start, code + vmv->live_range_end, buf, p - buf);
1943                 } else {
1944                         emit_byte (w, p - buf);
1945                         emit_bytes (w, buf, p - buf);
1946                 }
1947         }               
1948         g_free (names);
1949
1950         /* Locals */
1951         locals_info = mono_debug_lookup_locals (method);
1952
1953         for (i = 0; i < header->num_locals; ++i) {
1954                 MonoInst *ins = locals [i];
1955                 char name_buf [128];
1956                 int j;
1957                 MonoMethodVar *vmv = NULL;
1958                 gboolean need_loclist = FALSE;
1959                 char *lname;
1960
1961                 /* ins->dreg no longer contains the original vreg */
1962                 vmv = find_vmv (cfg, ins);
1963                 if (code && vmv) {
1964                         if (vmv->live_range_start) {
1965                                 /* This variable has a precise live range */
1966                                 need_loclist = TRUE;
1967                         }
1968                 }
1969
1970                 emit_uleb128 (w, need_loclist ? ABBREV_VARIABLE_LOCLIST : ABBREV_VARIABLE);
1971                 /* name */
1972                 lname = NULL;
1973                 if (locals_info) {
1974                         for (j = 0; j < locals_info->num_locals; ++j)
1975                                 if (locals_info->locals [j].index == i)
1976                                         break;
1977                         if (j < locals_info->num_locals)
1978                                 lname = locals_info->locals [j].name;
1979                 }
1980                 if (lname) {
1981                         emit_string (w, lname);
1982                 } else {
1983                         sprintf (name_buf, "V_%d", i);
1984                         emit_string (w, name_buf);
1985                 }
1986                 /* type */
1987                 if (!ins || ins->flags & MONO_INST_IS_DEAD)
1988                         emit_var_type (w, &mono_defaults.int32_class->byval_arg);
1989                 else
1990                         emit_var_type (w, header->locals [i]);
1991
1992                 p = buf;
1993                 encode_var_location (w, ins, p, &p);
1994
1995                 if (need_loclist) {
1996                         if (vmv->live_range_end == 0)
1997                                 /* FIXME: Uses made in calls are not recorded */
1998                                 vmv->live_range_end = code_size;
1999                         emit_loclist (w, ins, code + vmv->live_range_start, code + vmv->live_range_end, buf, p - buf);
2000                 } else {
2001                         emit_byte (w, p - buf);
2002                         emit_bytes (w, buf, p - buf);
2003                 }
2004         }
2005
2006         if (locals_info)
2007                 mono_debug_free_locals (locals_info);
2008
2009         /* Subprogram end */
2010         emit_uleb128 (w, 0x0);
2011
2012         emit_line (w);
2013
2014         emit_debug_info_end (w);
2015
2016         /* Emit unwind info */
2017         if (unwind_info) {
2018                 emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
2019                 w->fde_index ++;
2020         }
2021
2022         /* Emit line number info */
2023         /* != could happen when using --regression */
2024         if (debug_info && (debug_info->code_start == code)) {
2025                 if (w->collect_line_info) {
2026                         MethodLineNumberInfo *info;
2027
2028                         /* Save the information needed to emit the line number info later at once */
2029                         info = g_new0 (MethodLineNumberInfo, 1);
2030                         info->method = method;
2031                         info->start_symbol = g_strdup (start_symbol);
2032                         info->end_symbol = g_strdup (end_symbol);
2033                         info->code = code;
2034                         info->code_size = code_size;
2035                         w->line_info = g_slist_prepend (w->line_info, info);
2036                 } else {
2037                         emit_line_number_info (w, method, start_symbol, end_symbol, code, code_size, debug_info);
2038                 }
2039         }
2040
2041         emit_line (w);
2042         mono_metadata_free_mh (header);
2043 }
2044
2045 void
2046 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)
2047 {
2048         emit_section_change (w, ".debug_info", 0);
2049
2050         /* Subprogram */
2051         emit_uleb128 (w, ABBREV_TRAMP_SUBPROGRAM);
2052         emit_string (w, tramp_name);
2053         emit_pointer_value (w, code);
2054         emit_pointer_value (w, code + code_size);
2055
2056         /* Subprogram end */
2057         emit_uleb128 (w, 0x0);
2058
2059         emit_debug_info_end (w);
2060
2061         /* Emit unwind info */
2062         emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, FALSE);
2063         w->fde_index ++;
2064 }
2065 #endif /* End of: !defined(DISABLE_AOT) && !defined(DISABLE_JIT) */