{
MonoImageWriter *w;
GHashTable *class_to_die, *class_to_vtype_die, *class_to_pointer_die;
+ GHashTable *class_to_reference_die;
int fde_index, tdie_index, line_number_file_index, line_number_dir_index;
GHashTable *file_to_index, *dir_to_index;
FILE *il_file;
#define ABBREV_VARIABLE 11
#define ABBREV_VARIABLE_LOCLIST 12
#define ABBREV_POINTER_TYPE 13
-#define ABBREV_PARAM_LOCLIST 14
+#define ABBREV_REFERENCE_TYPE 14
+#define ABBREV_PARAM_LOCLIST 15
+#define ABBREV_INHERITANCE 16
static int compile_unit_attr [] = {
DW_AT_producer ,DW_FORM_string,
DW_AT_type, DW_FORM_ref4,
};
+static int reference_type_attr [] = {
+ DW_AT_type, DW_FORM_ref4,
+};
+
static int enum_type_attr [] = {
DW_AT_name, DW_FORM_string,
DW_AT_byte_size, DW_FORM_udata,
DW_AT_type, DW_FORM_ref4,
DW_AT_location, DW_FORM_data4
};
+
+static int inheritance_attr [] = {
+ DW_AT_type, DW_FORM_ref4,
+ DW_AT_data_member_location, DW_FORM_block1
+};
typedef struct DwarfBasicType {
const char *die_name, *name;
variable_loclist_attr, G_N_ELEMENTS (variable_loclist_attr));
emit_dwarf_abbrev (w, ABBREV_POINTER_TYPE, DW_TAG_pointer_type, FALSE,
pointer_type_attr, G_N_ELEMENTS (pointer_type_attr));
+ emit_dwarf_abbrev (w, ABBREV_REFERENCE_TYPE, DW_TAG_reference_type, FALSE,
+ reference_type_attr, G_N_ELEMENTS (reference_type_attr));
+ emit_dwarf_abbrev (w, ABBREV_INHERITANCE, DW_TAG_inheritance, FALSE,
+ inheritance_attr, G_N_ELEMENTS (inheritance_attr));
emit_byte (w, 0);
emit_section_change (w, ".debug_info", 0);
emit_cie (w);
}
+static const char* emit_type (MonoDwarfWriter *w, MonoType *t);
+
/* Returns the local symbol pointing to the emitted debug info */
static char*
emit_class_dwarf_info (MonoDwarfWriter *w, MonoClass *klass, gboolean vtype)
{
- char *die, *pointer_die;
- char *full_name;
+ char *die, *pointer_die, *reference_die;
+ char *full_name, *p;
gpointer iter;
MonoClassField *field;
const char *fdie;
w->class_to_vtype_die = g_hash_table_new (NULL, NULL);
if (!w->class_to_pointer_die)
w->class_to_pointer_die = g_hash_table_new (NULL, NULL);
+ if (!w->class_to_reference_die)
+ w->class_to_reference_die = g_hash_table_new (NULL, NULL);
if (vtype)
cache = w->class_to_vtype_die;
if (die)
return die;
- if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype)))
+ if (!((klass->byval_arg.type == MONO_TYPE_CLASS) || (klass->byval_arg.type == MONO_TYPE_OBJECT) || klass->enumtype || (klass->byval_arg.type == MONO_TYPE_VALUETYPE && vtype)))
return NULL;
/*
}
full_name = g_strdup_printf ("%s%s%s", klass->name_space, klass->name_space ? "." : "", klass->name);
+ /*
+ * gdb doesn't support namespaces for non-C++ dwarf objects, so use _
+ * to separate components.
+ */
+ for (p = full_name; *p; p ++)
+ if (*p == '.')
+ *p = '_';
die = g_strdup_printf (".LTDIE_%d", w->tdie_index);
- emit_label (w, die);
+ pointer_die = g_strdup_printf (".LTDIE_%d_POINTER", w->tdie_index);
+ reference_die = g_strdup_printf (".LTDIE_%d_REFERENCE", w->tdie_index);
+ w->tdie_index ++;
+
+ g_hash_table_insert (w->class_to_pointer_die, klass, pointer_die);
+ g_hash_table_insert (w->class_to_reference_die, klass, reference_die);
+ g_hash_table_insert (cache, klass, die);
if (klass->enumtype) {
int size = mono_class_value_size (mono_class_from_mono_type (mono_class_enum_basetype (klass)), NULL);
+ emit_label (w, die);
+
emit_uleb128 (w, ABBREV_ENUM_TYPE);
emit_string (w, full_name);
emit_uleb128 (w, size);
}
}
} else {
+ guint8 buf [128];
+ guint8 *p;
+ char *parent_die;
+
+ if (klass->parent)
+ parent_die = emit_class_dwarf_info (w, klass->parent, FALSE);
+ else
+ parent_die = NULL;
+
+ /* Emit field types */
+ iter = NULL;
+ while ((field = mono_class_get_fields (klass, &iter))) {
+ if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
+ continue;
+
+ emit_type (w, field->type);
+ }
+
+ emit_label (w, die);
+
emit_uleb128 (w, ABBREV_STRUCT_TYPE);
emit_string (w, full_name);
emit_uleb128 (w, klass->instance_size);
+ if (parent_die) {
+ emit_uleb128 (w, ABBREV_INHERITANCE);
+ emit_symbol_diff (w, parent_die, ".Ldebug_info_start", 0);
+
+ p = buf;
+ *p ++= DW_OP_plus_uconst;
+ encode_uleb128 (0, p, &p);
+ emit_byte (w, p - buf);
+ emit_bytes (w, buf, p - buf);
+ }
+
/* Emit fields */
iter = NULL;
while ((field = mono_class_get_fields (klass, &iter))) {
- guint8 buf [128];
- guint8 *p;
-
if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
continue;
- for (k = 0; k < G_N_ELEMENTS (basic_types); ++k)
- if (basic_types [k].type == field->type->type)
- break;
- if (k < G_N_ELEMENTS (basic_types) && field->type->type != MONO_TYPE_SZARRAY && field->type->type != MONO_TYPE_CLASS) {
- fdie = basic_types [k].die_name;
-
+ fdie = emit_type (w, field->type);
+ if (fdie) {
emit_uleb128 (w, ABBREV_DATA_MEMBER);
emit_string (w, field->name);
emit_symbol_diff (w, fdie, ".Ldebug_info_start", 0);
emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
/* Add a pointer type */
- pointer_die = g_strdup_printf (".LTDIE_%d_POINTER", w->tdie_index);
emit_label (w, pointer_die);
emit_uleb128 (w, ABBREV_POINTER_TYPE);
emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
- g_hash_table_insert (w->class_to_pointer_die, klass, pointer_die);
+ /* Add a reference type */
+ emit_label (w, reference_die);
+
+ emit_uleb128 (w, ABBREV_REFERENCE_TYPE);
+ emit_symbol_diff (w, die, ".Ldebug_info_start", 0);
g_free (full_name);
- w->tdie_index ++;
if (emit_namespace) {
/* Namespace end */
emit_uleb128 (w, 0x0);
}
- g_hash_table_insert (cache, klass, die);
return die;
}
if (tdie)
return g_hash_table_lookup (w->class_to_pointer_die, klass);
}
+ else {
+ tdie = emit_class_dwarf_info (w, klass, FALSE);
+ /* Should return a pointer type to a reference */
+ }
// FIXME:
t = &mono_defaults.int_class->byval_arg;
}
else {
switch (t->type) {
case MONO_TYPE_CLASS:
+ emit_class_dwarf_info (w, klass, FALSE);
+ tdie = g_hash_table_lookup (w->class_to_reference_die, klass);
+ //tdie = ".LDIE_OBJECT";
+ break;
case MONO_TYPE_ARRAY:
tdie = ".LDIE_OBJECT";
break;
MonoType *t;
if (i == 0 && sig->hasthis) {
- t = &method->klass->this_arg;
+ if (method->klass->valuetype)
+ t = &method->klass->this_arg;
+ else
+ t = &method->klass->byval_arg;
} else {
t = sig->params [i - sig->hasthis];
}
if (method->klass->valuetype)
t = &method->klass->this_arg;
else
- t = &mono_defaults.object_class->byval_arg;
+ t = &method->klass->byval_arg;
pname = "this";
} else {
t = sig->params [i - sig->hasthis];
/* ins->dreg no longer contains the original vreg */
vmv = find_vmv (cfg, ins);
if (code && vmv) {
- vmv = MONO_VARINFO (cfg, j);
if (vmv->live_range_start) {
/* This variable has a precise live range */
need_loclist = TRUE;
emit_line (w);
/* Emit unwind info */
- emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
- w->fde_index ++;
+ if (unwind_info) {
+ emit_fde (w, w->fde_index, start_symbol, end_symbol, code, code_size, unwind_info, TRUE);
+ w->fde_index ++;
+ }
/* Emit line number info */
if (code && debug_info)