2 * dwarfwriter.c: Creation of DWARF debug information
5 * Zoltan Varga (vargaz@gmail.com)
7 * (C) 2008-2009 Novell, Inc.
11 #include "dwarfwriter.h"
13 #include <sys/types.h>
20 #include <mono/metadata/mono-endian.h>
21 #include <mono/metadata/debug-mono-symfile.h>
22 #include <mono/utils/mono-compiler.h>
24 #ifndef PLATFORM_WIN32
25 #include <mono/utils/freebsd-elf32.h>
26 #include <mono/utils/freebsd-elf64.h>
29 #include <mono/utils/freebsd-dwarf.h>
31 struct _MonoDwarfWriter
34 GHashTable
*class_to_die
;
35 int fde_index
, tdie_index
, line_number_file_index
, line_number_dir_index
;
36 GHashTable
*file_to_index
, *dir_to_index
;
38 int il_file_line_index
, loclist_index
;
43 * mono_dwarf_writer_create:
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.
50 mono_dwarf_writer_create (MonoImageWriter
*writer
, FILE *il_file
)
52 MonoDwarfWriter
*w
= g_new0 (MonoDwarfWriter
, 1);
61 mono_dwarf_writer_destroy (MonoDwarfWriter
*w
)
66 /* Wrappers around the image writer functions */
69 emit_section_change (MonoDwarfWriter
*w
, const char *section_name
, int subsection_index
)
71 img_writer_emit_section_change (w
->w
, section_name
, subsection_index
);
75 emit_push_section (MonoDwarfWriter
*w
, const char *section_name
, int subsection
)
77 img_writer_emit_push_section (w
->w
, section_name
, subsection
);
81 emit_pop_section (MonoDwarfWriter
*w
)
83 img_writer_emit_pop_section (w
->w
);
87 emit_local_symbol (MonoDwarfWriter
*w
, const char *name
, const char *end_label
, gboolean func
)
89 img_writer_emit_local_symbol (w
->w
, name
, end_label
, func
);
93 emit_label (MonoDwarfWriter
*w
, const char *name
)
95 img_writer_emit_label (w
->w
, name
);
99 emit_bytes (MonoDwarfWriter
*w
, const guint8
* buf
, int size
)
101 img_writer_emit_bytes (w
->w
, buf
, size
);
105 emit_string (MonoDwarfWriter
*w
, const char *value
)
107 img_writer_emit_string (w
->w
, value
);
111 emit_line (MonoDwarfWriter
*w
)
113 img_writer_emit_line (w
->w
);
117 emit_alignment (MonoDwarfWriter
*w
, int size
)
119 img_writer_emit_alignment (w
->w
, size
);
123 emit_pointer_unaligned (MonoDwarfWriter
*w
, const char *target
)
125 img_writer_emit_pointer_unaligned (w
->w
, target
);
129 emit_pointer (MonoDwarfWriter
*w
, const char *target
)
131 img_writer_emit_pointer (w
->w
, target
);
135 emit_int16 (MonoDwarfWriter
*w
, int value
)
137 img_writer_emit_int16 (w
->w
, value
);
141 emit_int32 (MonoDwarfWriter
*w
, int value
)
143 img_writer_emit_int32 (w
->w
, value
);
147 emit_symbol_diff (MonoDwarfWriter
*w
, const char *end
, const char* start
, int offset
)
149 img_writer_emit_symbol_diff (w
->w
, end
, start
, offset
);
153 emit_zero_bytes (MonoDwarfWriter
*w
, int num
)
155 img_writer_emit_zero_bytes (w
->w
, num
);
159 emit_byte (MonoDwarfWriter
*w
, guint8 val
)
161 img_writer_emit_byte (w
->w
, val
);
164 static G_GNUC_UNUSED
void
165 emit_uleb128 (MonoDwarfWriter
*w
, guint32 value
)
168 guint8 b
= value
& 0x7f;
170 if (value
!= 0) /* more bytes to come */
176 static G_GNUC_UNUSED
void
177 emit_sleb128 (MonoDwarfWriter
*w
, gint64 value
)
180 gboolean negative
= (value
< 0);
187 /* the following is unnecessary if the
188 * implementation of >>= uses an arithmetic rather
189 * than logical shift for a signed left operand
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)))
204 static G_GNUC_UNUSED
void
205 encode_uleb128 (guint32 value
, guint8
*buf
, guint8
**endbuf
)
210 guint8 b
= value
& 0x7f;
212 if (value
!= 0) /* more bytes to come */
220 static G_GNUC_UNUSED
void
221 encode_sleb128 (gint32 value
, guint8
*buf
, guint8
**endbuf
)
224 gboolean negative
= (value
< 0);
232 /* the following is unnecessary if the
233 * implementation of >>= uses an arithmetic rather
234 * than logical shift for a signed left operand
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)))
252 emit_dwarf_abbrev (MonoDwarfWriter
*w
, int code
, int tag
, gboolean has_child
,
253 int *attrs
, int attrs_len
)
257 emit_uleb128 (w
, code
);
258 emit_uleb128 (w
, tag
);
259 emit_byte (w
, has_child
);
261 for (i
= 0; i
< attrs_len
; i
++)
262 emit_uleb128 (w
, attrs
[i
]);
268 emit_cie (MonoDwarfWriter
*w
)
270 emit_section_change (w
, ".debug_frame", 0);
272 emit_alignment (w
, 8);
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 ());
283 w
->cie_program
= w
->cie_program
;
284 if (w
->cie_program
) {
286 guint8
*uw_info
= mono_unwind_ops_encode (w
->cie_program
, &uw_info_len
);
287 emit_bytes (w
, uw_info
, uw_info_len
);
291 emit_alignment (w
, sizeof (gpointer
));
292 emit_label (w
, ".Lcie0_end");
296 emit_pointer_value (MonoDwarfWriter
*w
, gpointer ptr
)
298 gssize val
= (gssize
)ptr
;
299 emit_bytes (w
, (guint8
*)&val
, sizeof (gpointer
));
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
)
311 emit_section_change (w
, ".debug_frame", 0);
313 sprintf (symbol
, ".Lfde%d_end", fde_index
);
314 emit_symbol_diff (w
, symbol
, ".", -4); /* length */
315 emit_int32 (w
, 0); /* CIE_pointer */
317 emit_pointer (w
, start_symbol
); /* initial_location */
319 emit_symbol_diff (w
, end_symbol
, start_symbol
, 0); /* address_range */
321 g_assert (code_size
);
322 emit_int32 (w
, code_size
);
325 emit_pointer_value (w
, code
);
326 emit_int32 (w
, code_size
);
328 #if SIZEOF_VOID_P == 8
329 /* Upper 32 bits of code size */
334 if (w
->cie_program
) {
335 // FIXME: Check that the ops really begin with the CIE program */
338 for (i
= 0; i
< g_slist_length (w
->cie_program
); ++i
)
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
);
347 emit_alignment (w
, sizeof (gpointer
));
348 sprintf (symbol
, ".Lfde%d_end", fde_index
);
349 emit_label (w
, symbol
);
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
366 static int compile_unit_attr
[] = {
367 DW_AT_producer
,DW_FORM_string
,
368 DW_AT_name
,DW_FORM_string
,
369 DW_AT_comp_dir
,DW_FORM_string
,
370 DW_AT_language
,DW_FORM_data1
,
371 DW_AT_low_pc
,DW_FORM_addr
,
372 DW_AT_high_pc
,DW_FORM_addr
,
373 DW_AT_stmt_list
,DW_FORM_data4
376 static int subprogram_attr
[] = {
377 DW_AT_name
, DW_FORM_string
,
378 DW_AT_low_pc
, DW_FORM_addr
,
379 DW_AT_high_pc
, DW_FORM_addr
,
380 DW_AT_frame_base
, DW_FORM_block1
383 static int param_attr
[] = {
384 DW_AT_name
, DW_FORM_string
,
385 DW_AT_type
, DW_FORM_ref4
,
386 DW_AT_location
, DW_FORM_block1
389 static int base_type_attr
[] = {
390 DW_AT_byte_size
, DW_FORM_data1
,
391 DW_AT_encoding
, DW_FORM_data1
,
392 DW_AT_name
, DW_FORM_string
395 static int struct_type_attr
[] = {
396 DW_AT_name
, DW_FORM_string
,
397 DW_AT_byte_size
, DW_FORM_udata
,
400 static int data_member_attr
[] = {
401 DW_AT_name
, DW_FORM_string
,
402 DW_AT_type
, DW_FORM_ref4
,
403 DW_AT_data_member_location
, DW_FORM_block1
406 static int typedef_attr
[] = {
407 DW_AT_name
, DW_FORM_string
,
408 DW_AT_type
, DW_FORM_ref4
411 static int enum_type_attr
[] = {
412 DW_AT_name
, DW_FORM_string
,
413 DW_AT_byte_size
, DW_FORM_udata
,
414 DW_AT_type
, DW_FORM_ref4
,
417 static int enumerator_attr
[] = {
418 DW_AT_name
, DW_FORM_string
,
419 DW_AT_const_value
, DW_FORM_sdata
,
422 static int namespace_attr
[] = {
423 DW_AT_name
, DW_FORM_string
,
426 static int variable_attr
[] = {
427 DW_AT_name
, DW_FORM_string
,
428 DW_AT_type
, DW_FORM_ref4
,
429 DW_AT_location
, DW_FORM_block1
432 static int variable_loclist_attr
[] = {
433 DW_AT_name
, DW_FORM_string
,
434 DW_AT_type
, DW_FORM_ref4
,
435 DW_AT_location
, DW_FORM_data4
438 typedef struct DwarfBasicType
{
439 const char *die_name
, *name
;
445 static DwarfBasicType basic_types
[] = {
446 { ".LDIE_I1", "sbyte", MONO_TYPE_I1
, 1, DW_ATE_signed
},
447 { ".LDIE_U1", "byte", MONO_TYPE_U1
, 1, DW_ATE_unsigned
},
448 { ".LDIE_I2", "short", MONO_TYPE_I2
, 2, DW_ATE_signed
},
449 { ".LDIE_U2", "ushort", MONO_TYPE_U2
, 2, DW_ATE_unsigned
},
450 { ".LDIE_I4", "int", MONO_TYPE_I4
, 4, DW_ATE_signed
},
451 { ".LDIE_U4", "uint", MONO_TYPE_U4
, 4, DW_ATE_unsigned
},
452 { ".LDIE_I8", "long", MONO_TYPE_I8
, 8, DW_ATE_signed
},
453 { ".LDIE_U8", "ulong", MONO_TYPE_U8
, 8, DW_ATE_unsigned
},
454 { ".LDIE_I", "intptr", MONO_TYPE_I
, SIZEOF_VOID_P
, DW_ATE_signed
},
455 { ".LDIE_U", "uintptr", MONO_TYPE_U
, SIZEOF_VOID_P
, DW_ATE_unsigned
},
456 { ".LDIE_R4", "float", MONO_TYPE_R4
, 4, DW_ATE_float
},
457 { ".LDIE_R8", "double", MONO_TYPE_R8
, 8, DW_ATE_float
},
458 { ".LDIE_BOOLEAN", "boolean", MONO_TYPE_BOOLEAN
, 1, DW_ATE_boolean
},
459 { ".LDIE_CHAR", "char", MONO_TYPE_CHAR
, 2, DW_ATE_unsigned_char
},
460 { ".LDIE_STRING", "string", MONO_TYPE_STRING
, sizeof (gpointer
), DW_ATE_address
},
461 { ".LDIE_OBJECT", "object", MONO_TYPE_OBJECT
, sizeof (gpointer
), DW_ATE_address
},
462 { ".LDIE_SZARRAY", "object", MONO_TYPE_SZARRAY
, sizeof (gpointer
), DW_ATE_address
},
465 /* Constants for encoding line number special opcodes */
466 #define OPCODE_BASE 13
468 #define LINE_RANGE 14
470 /* Subsections of the .debug_line section */
471 #define LINE_SUBSECTION_HEADER 1
472 #define LINE_SUBSECTION_INCLUDES 2
473 #define LINE_SUBSECTION_FILES 3
474 #define LINE_SUBSECTION_DATA 4
475 #define LINE_SUBSECTION_END 5
478 emit_line_number_file_name (MonoDwarfWriter
*w
, const char *name
,
479 gint64 last_mod_time
, gint64 file_size
)
483 char *basename
= NULL
;
485 if (!w
->file_to_index
)
486 w
->file_to_index
= g_hash_table_new (g_str_hash
, g_str_equal
);
488 index
= GPOINTER_TO_UINT (g_hash_table_lookup (w
->file_to_index
, name
));
492 if (g_path_is_absolute (name
)) {
493 char *dir
= g_path_get_dirname (name
);
495 if (!w
->dir_to_index
)
496 w
->dir_to_index
= g_hash_table_new (g_str_hash
, g_str_equal
);
498 dir_index
= GPOINTER_TO_UINT (g_hash_table_lookup (w
->dir_to_index
, dir
));
499 if (dir_index
== 0) {
500 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_INCLUDES
);
501 emit_string (w
, dir
);
503 dir_index
= ++ w
->line_number_dir_index
;
504 g_hash_table_insert (w
->dir_to_index
, g_strdup (dir
), GUINT_TO_POINTER (dir_index
));
509 basename
= g_path_get_basename (name
);
514 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_FILES
);
517 emit_string (w
, basename
);
519 emit_string (w
, name
);
520 emit_uleb128 (w
, dir_index
);
524 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_DATA
);
529 index
= ++ w
->line_number_file_index
;
530 g_hash_table_insert (w
->file_to_index
, g_strdup (name
), GUINT_TO_POINTER (index
));
536 emit_line_number_info_begin (MonoDwarfWriter
*w
)
539 /* FIXME: This doesn't seem to work with !xdebug */
540 emit_section_change (w
, ".debug_line", 0);
541 emit_label (w
, ".Ldebug_line_start");
542 emit_label (w
, ".Ldebug_line_section_start");
546 /* Line number info header */
548 * GAS seems to emit its own data to the end of the first subsection, so we use
549 * subsections 1, 2 etc:
550 * 1 - contains the header
551 * 2 - contains the file names
552 * 3 - contains the end of the header + the data
555 emit_section_change (w
, ".debug_line", 0);
556 emit_label (w
, ".Ldebug_line_section_start");
557 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_HEADER
);
558 emit_label (w
, ".Ldebug_line_start");
559 emit_symbol_diff (w
, ".Ldebug_line_end", ".", -4); /* length */
560 emit_int16 (w
, 0x2); /* version */
561 emit_symbol_diff (w
, ".Ldebug_line_header_end", ".", -4); /* header_length */
562 emit_byte (w
, 1); /* minimum_instruction_length */
563 emit_byte (w
, 1); /* default_is_stmt */
564 emit_byte (w
, LINE_BASE
); /* line_base */
565 emit_byte (w
, LINE_RANGE
); /* line_range */
566 emit_byte (w
, OPCODE_BASE
); /* opcode_base */
567 emit_byte (w
, 0); /* standard_opcode_lengths */
581 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_INCLUDES
);
583 /* End of Includes */
584 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_FILES
);
588 emit_line_number_file_name (w
, "xdb.il", 0, 0);
591 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_DATA
);
594 emit_label (w
, ".Ldebug_line_header_end");
596 /* Emit this into a separate subsection so it gets placed at the end */
597 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_END
);
601 emit_byte (w
, DW_LNE_end_sequence
);
603 emit_label (w
, ".Ldebug_line_end");
607 mono_dwarf_writer_emit_base_info (MonoDwarfWriter
*w
, GSList
*base_unwind_program
)
609 char *s
, *build_info
;
612 w
->cie_program
= base_unwind_program
;
614 emit_section_change (w
, ".debug_abbrev", 0);
615 emit_dwarf_abbrev (w
, ABBREV_COMPILE_UNIT
, DW_TAG_compile_unit
, TRUE
,
616 compile_unit_attr
, G_N_ELEMENTS (compile_unit_attr
));
617 emit_dwarf_abbrev (w
, ABBREV_SUBPROGRAM
, DW_TAG_subprogram
, TRUE
,
618 subprogram_attr
, G_N_ELEMENTS (subprogram_attr
));
619 emit_dwarf_abbrev (w
, ABBREV_PARAM
, DW_TAG_formal_parameter
, FALSE
,
620 param_attr
, G_N_ELEMENTS (param_attr
));
621 emit_dwarf_abbrev (w
, ABBREV_BASE_TYPE
, DW_TAG_base_type
, FALSE
,
622 base_type_attr
, G_N_ELEMENTS (base_type_attr
));
623 emit_dwarf_abbrev (w
, ABBREV_STRUCT_TYPE
, DW_TAG_class_type
, TRUE
,
624 struct_type_attr
, G_N_ELEMENTS (struct_type_attr
));
625 emit_dwarf_abbrev (w
, ABBREV_DATA_MEMBER
, DW_TAG_member
, FALSE
,
626 data_member_attr
, G_N_ELEMENTS (data_member_attr
));
627 emit_dwarf_abbrev (w
, ABBREV_TYPEDEF
, DW_TAG_typedef
, FALSE
,
628 typedef_attr
, G_N_ELEMENTS (typedef_attr
));
629 emit_dwarf_abbrev (w
, ABBREV_ENUM_TYPE
, DW_TAG_enumeration_type
, TRUE
,
630 enum_type_attr
, G_N_ELEMENTS (enum_type_attr
));
631 emit_dwarf_abbrev (w
, ABBREV_ENUMERATOR
, DW_TAG_enumerator
, FALSE
,
632 enumerator_attr
, G_N_ELEMENTS (enumerator_attr
));
633 emit_dwarf_abbrev (w
, ABBREV_NAMESPACE
, DW_TAG_namespace
, TRUE
,
634 namespace_attr
, G_N_ELEMENTS (namespace_attr
));
635 emit_dwarf_abbrev (w
, ABBREV_VARIABLE
, DW_TAG_variable
, FALSE
,
636 variable_attr
, G_N_ELEMENTS (variable_attr
));
637 emit_dwarf_abbrev (w
, ABBREV_VARIABLE_LOCLIST
, DW_TAG_variable
, FALSE
,
638 variable_loclist_attr
, G_N_ELEMENTS (variable_loclist_attr
));
641 emit_section_change (w
, ".debug_info", 0);
642 emit_label (w
, ".Ldebug_info_start");
643 emit_symbol_diff (w
, ".Ldebug_info_end", ".", -4); /* length */
644 emit_int16 (w
, 0x2); /* DWARF version 2 */
645 emit_int32 (w
, 0); /* .debug_abbrev offset */
646 emit_byte (w
, sizeof (gpointer
)); /* address size */
648 /* Emit this into a separate section so it gets placed at the end */
649 emit_section_change (w
, ".debug_info", 1);
650 emit_int32 (w
, 0); /* close everything */
651 emit_label (w
, ".Ldebug_info_end");
652 emit_section_change (w
, ".debug_info", 0);
654 /* Compilation unit */
655 emit_uleb128 (w
, ABBREV_COMPILE_UNIT
);
656 build_info
= mono_get_runtime_build_info ();
657 s
= g_strdup_printf ("Mono AOT Compiler %s", build_info
);
661 emit_string (w
, "JITted code");
663 emit_byte (w
, DW_LANG_C
);
664 emit_pointer_value (w
, 0);
665 emit_pointer_value (w
, 0);
666 /* offset into .debug_line section */
667 emit_symbol_diff (w
, ".Ldebug_line_start", ".Ldebug_line_section_start", 0);
670 for (i
= 0; i
< G_N_ELEMENTS (basic_types
); ++i
) {
671 emit_label (w
, basic_types
[i
].die_name
);
672 emit_uleb128 (w
, ABBREV_BASE_TYPE
);
673 emit_byte (w
, basic_types
[i
].size
);
674 emit_byte (w
, basic_types
[i
].encoding
);
675 emit_string (w
, basic_types
[i
].name
);
678 /* debug_loc section */
679 emit_section_change (w
, ".debug_loc", 0);
680 emit_label (w
, ".Ldebug_loc_start");
682 /* debug_line section */
683 emit_line_number_info_begin (w
);
688 /* Returns the local symbol pointing to the emitted debug info */
690 emit_class_dwarf_info (MonoDwarfWriter
*w
, MonoClass
*klass
)
695 MonoClassField
*field
;
698 gboolean emit_namespace
= FALSE
;
701 if (!w
->class_to_die
)
702 w
->class_to_die
= g_hash_table_new (NULL
, NULL
);
704 die
= g_hash_table_lookup (w
->class_to_die
, klass
);
708 if (!((klass
->byval_arg
.type
== MONO_TYPE_CLASS
) || klass
->enumtype
))
712 * FIXME: gdb can't handle namespaces in languages it doesn't know about.
715 if (klass->name_space && klass->name_space [0] != '\0')
716 emit_namespace = TRUE;
718 if (emit_namespace
) {
719 emit_uleb128 (w
, ABBREV_NAMESPACE
);
720 emit_string (w
, klass
->name_space
);
723 full_name
= g_strdup_printf ("%s%s%s", klass
->name_space
, klass
->name_space
? "." : "", klass
->name
);
725 die
= g_strdup_printf (".LTDIE_%d", w
->tdie_index
);
728 if (klass
->enumtype
) {
729 int size
= mono_class_value_size (mono_class_from_mono_type (mono_class_enum_basetype (klass
)), NULL
);
731 emit_uleb128 (w
, ABBREV_ENUM_TYPE
);
732 emit_string (w
, full_name
);
733 emit_uleb128 (w
, size
);
734 for (k
= 0; k
< G_N_ELEMENTS (basic_types
); ++k
)
735 if (basic_types
[k
].type
== mono_class_enum_basetype (klass
)->type
)
737 g_assert (k
< G_N_ELEMENTS (basic_types
));
738 emit_symbol_diff (w
, basic_types
[k
].die_name
, ".Ldebug_info_start", 0);
740 /* Emit enum values */
742 while ((field
= mono_class_get_fields (klass
, &iter
))) {
745 MonoTypeEnum def_type
;
747 if (strcmp ("value__", mono_field_get_name (field
)) == 0)
749 if (mono_field_is_deleted (field
))
752 emit_uleb128 (w
, ABBREV_ENUMERATOR
);
753 emit_string (w
, mono_field_get_name (field
));
755 p
= mono_class_get_field_default_value (field
, &def_type
);
756 len
= mono_metadata_decode_blob_size (p
, &p
);
757 switch (mono_class_enum_basetype (klass
)->type
) {
760 case MONO_TYPE_BOOLEAN
:
761 emit_sleb128 (w
, *p
);
766 emit_sleb128 (w
, read16 (p
));
770 emit_sleb128 (w
, read32 (p
));
774 emit_sleb128 (w
, read64 (p
));
778 #if SIZEOF_VOID_P == 8
779 emit_sleb128 (w
, read64 (p
));
781 emit_sleb128 (w
, read32 (p
));
785 g_assert_not_reached ();
789 emit_uleb128 (w
, ABBREV_STRUCT_TYPE
);
790 emit_string (w
, full_name
);
791 emit_uleb128 (w
, klass
->instance_size
);
795 while ((field
= mono_class_get_fields (klass
, &iter
))) {
799 if (field
->type
->attrs
& FIELD_ATTRIBUTE_STATIC
)
802 for (k
= 0; k
< G_N_ELEMENTS (basic_types
); ++k
)
803 if (basic_types
[k
].type
== field
->type
->type
)
805 if (k
< G_N_ELEMENTS (basic_types
) && field
->type
->type
!= MONO_TYPE_SZARRAY
&& field
->type
->type
!= MONO_TYPE_CLASS
) {
806 fdie
= basic_types
[k
].die_name
;
808 emit_uleb128 (w
, ABBREV_DATA_MEMBER
);
809 emit_string (w
, field
->name
);
810 emit_symbol_diff (w
, fdie
, ".Ldebug_info_start", 0);
813 *p
++= DW_OP_plus_uconst
;
814 encode_uleb128 (field
->offset
, p
, &p
);
816 emit_byte (w
, p
- buf
);
817 emit_bytes (w
, buf
, p
- buf
);
823 emit_uleb128 (w
, 0x0);
825 /* Add a typedef, so we can reference the type without a 'struct' in gdb */
826 emit_uleb128 (w
, ABBREV_TYPEDEF
);
827 emit_string (w
, full_name
);
828 emit_symbol_diff (w
, die
, ".Ldebug_info_start", 0);
834 if (emit_namespace
) {
836 emit_uleb128 (w
, 0x0);
839 g_hash_table_insert (w
->class_to_die
, klass
, die
);
844 emit_var_type (MonoDwarfWriter
*w
, MonoType
*t
)
846 MonoClass
*klass
= mono_class_from_mono_type (t
);
850 for (j
= 0; j
< G_N_ELEMENTS (basic_types
); ++j
)
851 if (basic_types
[j
].type
== t
->type
)
853 if (j
< G_N_ELEMENTS (basic_types
))
854 tdie
= basic_types
[j
].die_name
;
857 case MONO_TYPE_CLASS
:
858 case MONO_TYPE_ARRAY
:
859 tdie
= ".LDIE_OBJECT";
861 case MONO_TYPE_VALUETYPE
:
863 tdie
= emit_class_dwarf_info (w
, klass
);
875 emit_symbol_diff (w
, tdie
, ".Ldebug_info_start", 0);
879 encode_var_location (MonoDwarfWriter
*w
, MonoInst
*ins
, guint8
*p
, guint8
**endp
)
882 /* FIXME: This needs a location list, since the args can go from reg->stack */
883 if (!ins
|| ins
->flags
& MONO_INST_IS_DEAD
) {
884 /* gdb treats this as optimized out */
885 } else if (ins
->opcode
== OP_REGVAR
) {
886 *p
= DW_OP_reg0
+ mono_hw_reg_to_dwarf_reg (ins
->dreg
);
888 } else if (ins
->opcode
== OP_REGOFFSET
) {
889 *p
++= DW_OP_breg0
+ mono_hw_reg_to_dwarf_reg (ins
->inst_basereg
);
890 encode_sleb128 (ins
->inst_offset
, p
, &p
);
900 emit_loclist (MonoDwarfWriter
*w
, MonoInst
*ins
,
901 guint8
*loclist_begin_addr
, guint8
*loclist_end_addr
,
902 guint8
*expr
, guint32 expr_len
)
906 emit_push_section (w
, ".debug_loc", 0);
907 sprintf (label
, ".Lloclist_%d", w
->loclist_index
++ );
908 emit_label (w
, label
);
910 emit_pointer_value (w
, loclist_begin_addr
);
911 emit_pointer_value (w
, loclist_end_addr
);
912 emit_byte (w
, expr_len
% 256);
913 emit_byte (w
, expr_len
/ 256);
914 emit_bytes (w
, expr
, expr_len
);
916 emit_pointer_value (w
, NULL
);
917 emit_pointer_value (w
, NULL
);
919 emit_pop_section (w
);
920 emit_symbol_diff (w
, label
, ".Ldebug_loc_start", 0);
924 * MonoDisHelper->tokener doesn't take an IP argument, and we can't add one since
925 * it is a public header.
927 static const guint8
*token_handler_ip
;
930 token_handler (MonoDisHelper
*dh
, MonoMethod
*method
, guint32 token
)
935 gpointer data
= NULL
;
937 if (method
->wrapper_type
)
938 data
= mono_method_get_wrapper_data (method
, token
);
940 switch (*token_handler_ip
) {
943 if (method
->wrapper_type
)
946 klass
= mono_class_get_full (method
->klass
->image
, token
, NULL
);
947 res
= g_strdup_printf ("<%s>", klass
->name
);
952 if (method
->wrapper_type
)
955 cmethod
= mono_get_method_full (method
->klass
->image
, token
, NULL
, NULL
);
956 desc
= mono_method_full_name (cmethod
, TRUE
);
957 res
= g_strdup_printf ("<%s>", desc
);
961 if (method
->wrapper_type
) {
962 desc
= mono_signature_get_desc (data
, FALSE
);
963 res
= g_strdup_printf ("<%s>", desc
);
966 res
= g_strdup_printf ("<0x%08x>", token
);
970 res
= g_strdup_printf ("<0x%08x>", token
);
980 * Produce a disassembled form of the IL instruction at IP. This is an extension
981 * of mono_disasm_code_one () which can disasm tokens, handle wrapper methods, and
985 disasm_ins (MonoMethod
*method
, const guchar
*ip
, const guint8
**endip
)
989 MonoMethodHeader
*header
= mono_method_get_header (method
);
991 memset (&dh
, 0, sizeof (dh
));
993 dh
.label_format
= "IL_%04x: ";
994 dh
.label_target
= "IL_%04x";
995 dh
.tokener
= token_handler
;
997 token_handler_ip
= ip
;
998 if (*ip
== MONO_CUSTOM_PREFIX
) {
1003 case CEE_MONO_ICALL
: {
1004 MonoJitICallInfo
*info
;
1006 token
= read32 (ip
+ 2);
1007 data
= mono_method_get_wrapper_data (method
, token
);
1008 info
= mono_find_jit_icall_by_addr (data
);
1011 dis
= g_strdup_printf ("IL_%04x: mono_icall <%s>", (int)(ip
- header
->code
), info
->name
);
1015 case CEE_MONO_CLASSCONST
: {
1016 token
= read32 (ip
+ 2);
1017 data
= mono_method_get_wrapper_data (method
, token
);
1019 dis
= g_strdup_printf ("IL_%04x: mono_classconst <%s>", (int)(ip
- header
->code
), ((MonoClass
*)data
)->name
);
1024 dis
= mono_disasm_code_one (&dh
, method
, ip
, &ip
);
1027 dis
= mono_disasm_code_one (&dh
, method
, ip
, &ip
);
1029 token_handler_ip
= NULL
;
1036 il_offset_from_address (MonoMethod
*method
, MonoDebugMethodJitInfo
*jit
,
1037 guint32 native_offset
)
1041 if (!jit
->line_numbers
)
1044 for (i
= jit
->num_line_numbers
- 1; i
>= 0; i
--) {
1045 MonoDebugLineNumberEntry lne
= jit
->line_numbers
[i
];
1047 if (lne
.native_offset
<= native_offset
)
1048 return lne
.il_offset
;
1054 static int max_special_addr_diff
= 0;
1057 emit_advance_op (MonoDwarfWriter
*w
, int line_diff
, int addr_diff
)
1061 /* Use a special opcode if possible */
1062 if (line_diff
- LINE_BASE
>= 0 && line_diff
- LINE_BASE
< LINE_RANGE
) {
1063 if (max_special_addr_diff
== 0)
1064 max_special_addr_diff
= (255 - OPCODE_BASE
) / LINE_RANGE
;
1066 if (addr_diff
> max_special_addr_diff
&& (addr_diff
< 2 * max_special_addr_diff
)) {
1067 emit_byte (w
, DW_LNS_const_add_pc
);
1068 addr_diff
-= max_special_addr_diff
;
1071 opcode
= (line_diff
- LINE_BASE
) + (LINE_RANGE
* addr_diff
) + OPCODE_BASE
;
1077 emit_byte (w
, opcode
);
1079 emit_byte (w
, DW_LNS_advance_line
);
1080 emit_sleb128 (w
, line_diff
);
1081 emit_byte (w
, DW_LNS_advance_pc
);
1082 emit_sleb128 (w
, addr_diff
);
1083 emit_byte (w
, DW_LNS_copy
);
1088 emit_line_number_info (MonoDwarfWriter
*w
, MonoMethod
*method
, guint8
*code
,
1089 guint32 code_size
, MonoDebugMethodJitInfo
*debug_info
)
1091 guint32 prev_line
= 0;
1092 guint32 prev_native_offset
= 0;
1093 int i
, file_index
, il_offset
, prev_il_offset
;
1094 gboolean first
= TRUE
;
1095 MonoDebugSourceLocation
*loc
;
1096 char *prev_file_name
= NULL
;
1097 MonoMethodHeader
*header
= mono_method_get_header (method
);
1098 MonoDebugMethodInfo
*minfo
;
1101 // FIXME: The set_address op below only works with xdebug
1104 minfo
= mono_debug_lookup_method (method
);
1106 /* FIXME: Avoid quadratic behavior */
1109 prev_il_offset
= -1;
1111 for (i
= 0; i
< code_size
; ++i
) {
1115 if (!debug_info
->line_numbers
)
1119 * FIXME: Its hard to optimize this, since the line number info is not
1120 * sorted by il offset or native offset
1122 il_offset
= il_offset_from_address (method
, debug_info
, i
);
1127 if (il_offset
== prev_il_offset
)
1130 prev_il_offset
= il_offset
;
1132 loc
= mono_debug_symfile_lookup_location (minfo
, il_offset
);
1135 int line_diff
= (gint32
)loc
->row
- (gint32
)prev_line
;
1136 int addr_diff
= i
- prev_native_offset
;
1139 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_DATA
);
1142 emit_byte (w
, sizeof (gpointer
) + 1);
1143 emit_byte (w
, DW_LNE_set_address
);
1144 emit_pointer_value (w
, code
);
1147 * The prolog+initlocals region does not have a line number, this
1148 * makes them belong to the first line of the method.
1150 emit_byte (w
, DW_LNS_advance_line
);
1151 emit_sleb128 (w
, (gint32
)loc
->row
- (gint32
)prev_line
);
1152 prev_line
= loc
->row
;
1155 if (loc
->row
!= prev_line
) {
1156 if (!prev_file_name
|| strcmp (loc
->source_file
, prev_file_name
) != 0) {
1157 /* Add an entry to the file table */
1158 /* FIXME: Avoid duplicates */
1159 file_index
= emit_line_number_file_name (w
, loc
->source_file
, 0, 0);
1160 g_free (prev_file_name
);
1161 prev_file_name
= g_strdup (loc
->source_file
);
1163 emit_byte (w
, DW_LNS_set_file
);
1164 emit_uleb128 (w
, file_index
);
1165 emit_byte (w
, DW_LNS_copy
);
1168 //printf ("X: %p(+0x%x) %d %s:%d(+%d)\n", code + i, addr_diff, loc->il_offset, loc->source_file, loc->row, line_diff);
1170 emit_advance_op (w
, line_diff
, addr_diff
);
1172 prev_line
= loc
->row
;
1173 prev_native_offset
= i
;
1181 g_free (prev_file_name
);
1184 emit_byte (w
, DW_LNS_advance_pc
);
1185 emit_sleb128 (w
, code_size
- prev_native_offset
);
1186 emit_byte (w
, DW_LNS_copy
);
1190 emit_byte (w
, DW_LNE_end_sequence
);
1192 /* No debug info, XDEBUG mode */
1194 const guint8
*ip
= header
->code
;
1195 int prev_line
, prev_native_offset
;
1199 * Emit the IL code into a temporary file and emit line number info
1200 * referencing that file.
1203 name
= mono_method_full_name (method
, TRUE
);
1204 fprintf (w
->il_file
, "// %s\n", name
);
1205 w
->il_file_line_index
++;
1208 il_to_line
= g_new0 (int, header
->code_size
);
1210 emit_section_change (w
, ".debug_line", LINE_SUBSECTION_DATA
);
1212 emit_byte (w
, sizeof (gpointer
) + 1);
1213 emit_byte (w
, DW_LNE_set_address
);
1214 emit_pointer_value (w
, code
);
1216 // FIXME: Optimize this
1217 while (ip
< header
->code
+ header
->code_size
) {
1218 int il_offset
= ip
- header
->code
;
1221 w
->il_file_line_index
++;
1223 dis
= disasm_ins (method
, ip
, &ip
);
1224 fprintf (w
->il_file
, "%s\n", dis
);
1227 il_to_line
[il_offset
] = w
->il_file_line_index
;
1230 /* Emit line number info */
1232 prev_native_offset
= 0;
1233 for (i
= 0; i
< debug_info
->num_line_numbers
; ++i
) {
1234 MonoDebugLineNumberEntry
*lne
= &debug_info
->line_numbers
[i
];
1237 if (lne
->il_offset
>= header
->code_size
)
1239 line
= il_to_line
[lne
->il_offset
];
1241 /* To help debugging */
1242 printf ("%s\n", mono_method_full_name (method
, TRUE
));
1243 printf ("%d %d\n", lne
->il_offset
, header
->code_size
);
1247 if (line
- prev_line
!= 0) {
1248 emit_advance_op (w
, line
- prev_line
, (gint32
)lne
->native_offset
- prev_native_offset
);
1251 prev_native_offset
= lne
->native_offset
;
1255 emit_byte (w
, DW_LNS_advance_pc
);
1256 emit_sleb128 (w
, code_size
- prev_native_offset
);
1257 emit_byte (w
, DW_LNS_copy
);
1261 emit_byte (w
, DW_LNE_end_sequence
);
1263 fflush (w
->il_file
);
1264 g_free (il_to_line
);
1269 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
)
1272 MonoMethodSignature
*sig
;
1273 MonoMethodHeader
*header
;
1274 char **names
, **tdies
, **local_tdies
;
1281 emit_section_change (w
, ".debug_info", 0);
1283 sig
= mono_method_signature (method
);
1284 header
= mono_method_get_header (method
);
1286 /* Parameter types */
1287 tdies
= g_new0 (char *, sig
->param_count
+ sig
->hasthis
);
1288 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
1291 if (i
== 0 && sig
->hasthis
) {
1292 t
= &method
->klass
->this_arg
;
1294 t
= sig
->params
[i
- sig
->hasthis
];
1297 emit_class_dwarf_info (w
, mono_class_from_mono_type (t
));
1301 local_tdies
= g_new0 (char *, header
->num_locals
);
1302 for (i
= 0; i
< header
->num_locals
; ++i
) {
1303 emit_class_dwarf_info (w
, mono_class_from_mono_type (header
->locals
[i
]));
1307 names
= g_new0 (char *, sig
->param_count
);
1308 mono_method_get_param_names (method
, (const char **) names
);
1310 emit_uleb128 (w
, ABBREV_SUBPROGRAM
);
1311 name
= mono_method_full_name (method
, FALSE
);
1312 emit_string (w
, name
);
1315 emit_pointer_unaligned (w
, start_symbol
);
1316 emit_pointer_unaligned (w
, end_symbol
);
1318 emit_pointer_value (w
, code
);
1319 emit_pointer_value (w
, code
+ code_size
);
1323 emit_byte (w
, DW_OP_breg6
);
1327 for (i
= 0; i
< sig
->param_count
+ sig
->hasthis
; ++i
) {
1328 MonoInst
*arg
= args
? args
[i
] : NULL
;
1331 char pname_buf
[128];
1333 if (i
== 0 && sig
->hasthis
) {
1334 t
= &mono_defaults
.object_class
->byval_arg
;
1337 t
= sig
->params
[i
- sig
->hasthis
];
1338 pname
= names
[i
- sig
->hasthis
];
1341 emit_uleb128 (w
, ABBREV_PARAM
);
1343 if (pname
[0] == '\0') {
1344 sprintf (pname_buf
, "param%d", i
- sig
->hasthis
);
1347 emit_string (w
, pname
);
1349 if (!arg
|| arg
->flags
& MONO_INST_IS_DEAD
)
1350 emit_var_type (w
, &mono_defaults
.int32_class
->byval_arg
);
1352 emit_var_type (w
, t
);
1355 encode_var_location (w
, arg
, p
, &p
);
1356 emit_byte (w
, p
- buf
);
1357 emit_bytes (w
, buf
, p
- buf
);
1362 num_locals
= mono_debug_lookup_locals (method
, &local_names
, &local_indexes
);
1364 for (i
= 0; i
< header
->num_locals
; ++i
) {
1365 MonoInst
*ins
= locals
[i
];
1366 char name_buf
[128];
1368 MonoMethodVar
*vmv
= NULL
;
1369 gboolean need_loclist
= FALSE
;
1371 /* ins->dreg no longer contains the original vreg */
1373 for (j
= 0; j
< cfg
->num_varinfo
; ++j
) {
1374 if (cfg
->varinfo
[j
] == ins
)
1378 if (code
&& j
< cfg
->num_varinfo
) {
1379 vmv
= MONO_VARINFO (cfg
, j
);
1380 if (vmv
->live_range_start
) {
1381 /* This variable has a precise live range */
1382 need_loclist
= TRUE
;
1388 emit_uleb128 (w
, ABBREV_VARIABLE_LOCLIST
);
1390 emit_uleb128 (w
, ABBREV_VARIABLE
);
1392 for (j
= 0; j
< num_locals
; ++j
)
1393 if (local_indexes
[j
] == i
)
1395 if (j
< num_locals
) {
1396 emit_string (w
, local_names
[j
]);
1398 sprintf (name_buf
, "V_%d", i
);
1399 emit_string (w
, name_buf
);
1402 if (!ins
|| ins
->flags
& MONO_INST_IS_DEAD
)
1403 emit_var_type (w
, &mono_defaults
.int32_class
->byval_arg
);
1405 emit_var_type (w
, header
->locals
[i
]);
1408 encode_var_location (w
, ins
, p
, &p
);
1411 if (vmv
->live_range_end
== 0)
1412 /* FIXME: Uses made in calls are not recorded */
1413 vmv
->live_range_end
= code_size
;
1414 emit_loclist (w
, ins
, code
+ vmv
->live_range_start
, code
+ vmv
->live_range_end
, buf
, p
- buf
);
1416 emit_byte (w
, p
- buf
);
1417 emit_bytes (w
, buf
, p
- buf
);
1421 g_free (local_names
);
1422 g_free (local_indexes
);
1424 /* Subprogram end */
1425 emit_uleb128 (w
, 0x0);
1429 /* Emit unwind info */
1430 emit_fde (w
, w
->fde_index
, start_symbol
, end_symbol
, code
, code_size
, unwind_info
, TRUE
);
1433 /* Emit line number info */
1434 if (code
&& debug_info
)
1435 emit_line_number_info (w
, method
, code
, code_size
, debug_info
);
1441 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
)
1443 emit_section_change (w
, ".debug_info", 0);
1446 emit_uleb128 (w
, ABBREV_SUBPROGRAM
);
1447 emit_string (w
, tramp_name
);
1448 emit_pointer_value (w
, code
);
1449 emit_pointer_value (w
, code
+ code_size
);
1452 emit_byte (w
, DW_OP_breg6
);
1455 /* Subprogram end */
1456 emit_uleb128 (w
, 0x0);
1458 /* Emit unwind info */
1459 emit_fde (w
, w
->fde_index
, start_symbol
, end_symbol
, code
, code_size
, unwind_info
, FALSE
);