aboutsummaryrefslogtreecommitdiff
path: root/gcc/dwarf2codeview.cc
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2024-11-10 00:23:49 +0000
committerMark Harmstone <mark@harmstone.com>2024-11-19 01:06:38 +0000
commitf1f8d4c5115975875b5b1a15adbac50bc28a3922 (patch)
tree515470c89f05932c33379385abdc2a9b3e5da3f8 /gcc/dwarf2codeview.cc
parent14d706ed0e90373c98a0ce223ffeea8846f6d9bc (diff)
downloadgcc-f1f8d4c5115975875b5b1a15adbac50bc28a3922.zip
gcc-f1f8d4c5115975875b5b1a15adbac50bc28a3922.tar.gz
gcc-f1f8d4c5115975875b5b1a15adbac50bc28a3922.tar.bz2
Flatten anonymous structs in CodeView types
If a CodeView struct, class, or union has as a member an anonymous struct, class, or union, this gets flattened. The sub-struct's members will appear as if they were part of their parent. For this, we move part of get_type_num_struct into a new function add_to_fieldlist, which also handles creating an LF_INDEX overflow item if an LF_FIELDLIST grows too large. This is because add_struct_member now calls itself recursively, and so needs to handle overflows itself. gcc/ * dwarf2codeview.cc (add_to_fieldlist): New function. (add_struct_member): Call recursively to flatten structs, and call add_to_fieldlist. (add_struct_static_member): Call add_to_fieldlist. (add_struct_function): Call add_to_fieldlist. (add_struct_inheritance): Call add_to_fieldlist. (add_struct_nested_type): Call add_to_fieldlist. (get_type_num_struct): Move code to add_to_fieldlist, and move responsibility for this to subfunctions.
Diffstat (limited to 'gcc/dwarf2codeview.cc')
-rw-r--r--gcc/dwarf2codeview.cc280
1 files changed, 167 insertions, 113 deletions
diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index ccb1109..650e83f 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -5404,6 +5404,52 @@ add_struct_forward_def (dw_die_ref type)
return ct->num;
}
+/* Add a new subtype to an LF_FIELDLIST type, and handle overflows if
+ necessary. */
+
+static void
+add_to_fieldlist (codeview_custom_type **ct, uint16_t *num_members,
+ codeview_subtype *el, size_t el_len)
+{
+ /* Add an LF_INDEX subtype if everything's too big for one
+ LF_FIELDLIST. */
+
+ if ((*ct)->lf_fieldlist.length + el_len > MAX_FIELDLIST_SIZE)
+ {
+ codeview_subtype *idx;
+ codeview_custom_type *ct2;
+
+ idx = (codeview_subtype *) xmalloc (sizeof (*idx));
+ idx->next = NULL;
+ idx->kind = LF_INDEX;
+ idx->lf_index.type_num = 0;
+
+ (*ct)->lf_fieldlist.last_subtype->next = idx;
+ (*ct)->lf_fieldlist.last_subtype = idx;
+
+ ct2 = (codeview_custom_type *)
+ xmalloc (sizeof (codeview_custom_type));
+
+ ct2->next = *ct;
+ ct2->kind = LF_FIELDLIST;
+ ct2->lf_fieldlist.length = 0;
+ ct2->lf_fieldlist.subtypes = NULL;
+ ct2->lf_fieldlist.last_subtype = NULL;
+
+ *ct = ct2;
+ }
+
+ (*ct)->lf_fieldlist.length += el_len;
+
+ if ((*ct)->lf_fieldlist.last_subtype)
+ (*ct)->lf_fieldlist.last_subtype->next = el;
+ else
+ (*ct)->lf_fieldlist.subtypes = el;
+
+ (*ct)->lf_fieldlist.last_subtype = el;
+ (*num_members)++;
+}
+
/* Add an LF_BITFIELD type, returning its number. DWARF represents bitfields
as members in a struct with a DW_AT_data_bit_offset attribute, whereas in
CodeView they're a distinct type. */
@@ -5436,36 +5482,69 @@ create_bitfield (dw_die_ref c)
static void
add_struct_member (dw_die_ref c, uint16_t accessibility,
- codeview_subtype **el, size_t *el_len)
+ codeview_custom_type **ct, uint16_t *num_members,
+ unsigned int base_offset)
{
- *el = (codeview_subtype *) xmalloc (sizeof (**el));
- (*el)->next = NULL;
- (*el)->kind = LF_MEMBER;
- (*el)->lf_member.attributes = accessibility;
+ codeview_subtype *el;
+ size_t el_len;
+ dw_die_ref type = get_AT_ref (c, DW_AT_type);
+ unsigned int offset;
+
+ offset = base_offset + get_AT_unsigned (c, DW_AT_data_member_location);
+
+ /* If the data member is actually an anonymous struct, class, or union,
+ follow MSVC by flattening this into its parent. */
+ if (!get_AT_string (c, DW_AT_name) && type
+ && (dw_get_die_tag (type) == DW_TAG_structure_type
+ || dw_get_die_tag (type) == DW_TAG_class_type
+ || dw_get_die_tag (type) == DW_TAG_union_type))
+ {
+ dw_die_ref c2, first_child;
+
+ first_child = dw_get_die_child (type);
+ c2 = first_child;
+
+ do
+ {
+ c2 = dw_get_die_sib (c2);
+
+ if (dw_get_die_tag (c2) == DW_TAG_member)
+ add_struct_member (c2, accessibility, ct, num_members, offset);
+ }
+ while (c2 != first_child);
+
+ return;
+ }
+
+ el = (codeview_subtype *) xmalloc (sizeof (*el));
+ el->next = NULL;
+ el->kind = LF_MEMBER;
+ el->lf_member.attributes = accessibility;
if (get_AT (c, DW_AT_data_bit_offset))
- (*el)->lf_member.type = create_bitfield (c);
+ el->lf_member.type = create_bitfield (c);
else
- (*el)->lf_member.type = get_type_num (get_AT_ref (c, DW_AT_type),
- true, false);
+ el->lf_member.type = get_type_num (type, true, false);
- (*el)->lf_member.offset.neg = false;
- (*el)->lf_member.offset.num = get_AT_unsigned (c, DW_AT_data_member_location);
+ el->lf_member.offset.neg = false;
+ el->lf_member.offset.num = offset;
- *el_len = 11 + cv_integer_len (&(*el)->lf_member.offset);
+ el_len = 11 + cv_integer_len (&el->lf_member.offset);
if (get_AT_string (c, DW_AT_name))
{
- (*el)->lf_member.name = xstrdup (get_AT_string (c, DW_AT_name));
- *el_len += strlen ((*el)->lf_member.name);
+ el->lf_member.name = xstrdup (get_AT_string (c, DW_AT_name));
+ el_len += strlen (el->lf_member.name);
}
else
{
- (*el)->lf_member.name = NULL;
+ el->lf_member.name = NULL;
}
- if (*el_len % 4)
- *el_len += 4 - (*el_len % 4);
+ if (el_len % 4)
+ el_len += 4 - (el_len % 4);
+
+ add_to_fieldlist (ct, num_members, el, el_len);
}
/* Create an LF_STMEMBER field list subtype for a static struct member,
@@ -5473,20 +5552,25 @@ add_struct_member (dw_die_ref c, uint16_t accessibility,
static void
add_struct_static_member (dw_die_ref c, uint16_t accessibility,
- codeview_subtype **el, size_t *el_len)
+ codeview_custom_type **ct, uint16_t *num_members)
{
- *el = (codeview_subtype *) xmalloc (sizeof (**el));
- (*el)->next = NULL;
- (*el)->kind = LF_STMEMBER;
- (*el)->lf_static_member.attributes = accessibility;
- (*el)->lf_static_member.type = get_type_num (get_AT_ref (c, DW_AT_type),
- true, false);
- (*el)->lf_static_member.name = xstrdup (get_AT_string (c, DW_AT_name));
-
- *el_len = 9 + strlen ((*el)->lf_static_member.name);
-
- if (*el_len % 4)
- *el_len += 4 - (*el_len % 4);
+ codeview_subtype *el;
+ size_t el_len;
+
+ el = (codeview_subtype *) xmalloc (sizeof (*el));
+ el->next = NULL;
+ el->kind = LF_STMEMBER;
+ el->lf_static_member.attributes = accessibility;
+ el->lf_static_member.type = get_type_num (get_AT_ref (c, DW_AT_type),
+ true, false);
+ el->lf_static_member.name = xstrdup (get_AT_string (c, DW_AT_name));
+
+ el_len = 9 + strlen (el->lf_static_member.name);
+
+ if (el_len % 4)
+ el_len += 4 - (el_len % 4);
+
+ add_to_fieldlist (ct, num_members, el, el_len);
}
/* Create a field list subtype for a struct function, returning its pointer in
@@ -5497,10 +5581,12 @@ add_struct_static_member (dw_die_ref c, uint16_t accessibility,
static void
add_struct_function (dw_die_ref c, hash_table<method_hasher> *method_htab,
- codeview_subtype **el, size_t *el_len)
+ codeview_custom_type **ct, uint16_t *num_members)
{
const char *name = get_AT_string (c, DW_AT_name);
codeview_method **slot, *meth;
+ codeview_subtype *el;
+ size_t el_len;
slot = method_htab->find_slot_with_hash (name, htab_hash_string (name),
NO_INSERT);
@@ -5509,17 +5595,17 @@ add_struct_function (dw_die_ref c, hash_table<method_hasher> *method_htab,
meth = *slot;
- *el = (codeview_subtype *) xmalloc (sizeof (**el));
- (*el)->next = NULL;
+ el = (codeview_subtype *) xmalloc (sizeof (*el));
+ el->next = NULL;
if (meth->count == 1)
{
- (*el)->kind = LF_ONEMETHOD;
- (*el)->lf_onemethod.method_attribute = meth->attribute;
- (*el)->lf_onemethod.method_type = meth->type;
- (*el)->lf_onemethod.name = xstrdup (name);
+ el->kind = LF_ONEMETHOD;
+ el->lf_onemethod.method_attribute = meth->attribute;
+ el->lf_onemethod.method_type = meth->type;
+ el->lf_onemethod.name = xstrdup (name);
- *el_len = 9 + strlen ((*el)->lf_onemethod.name);
+ el_len = 9 + strlen (el->lf_onemethod.name);
}
else
{
@@ -5544,16 +5630,18 @@ add_struct_function (dw_die_ref c, hash_table<method_hasher> *method_htab,
add_custom_type (ct);
- (*el)->kind = LF_METHOD;
- (*el)->lf_method.count = meth->count;
- (*el)->lf_method.method_list = ct->num;
- (*el)->lf_method.name = xstrdup (name);
+ el->kind = LF_METHOD;
+ el->lf_method.count = meth->count;
+ el->lf_method.method_list = ct->num;
+ el->lf_method.name = xstrdup (name);
- *el_len = 9 + strlen ((*el)->lf_method.name);
+ el_len = 9 + strlen (el->lf_method.name);
}
- if (*el_len % 4)
- *el_len += 4 - (*el_len % 4);
+ if (el_len % 4)
+ el_len += 4 - (el_len % 4);
+
+ add_to_fieldlist (ct, num_members, el, el_len);
method_htab->remove_elt_with_hash (name, htab_hash_string (name));
@@ -5572,27 +5660,32 @@ add_struct_function (dw_die_ref c, hash_table<method_hasher> *method_htab,
static void
add_struct_inheritance (dw_die_ref c, uint16_t accessibility,
- codeview_subtype **el, size_t *el_len)
+ codeview_custom_type **ct, uint16_t *num_members)
{
+ codeview_subtype *el;
+ size_t el_len;
+
/* FIXME: if DW_AT_virtuality is DW_VIRTUALITY_virtual this is a virtual
base class, and we should be issuing an LF_VBCLASS record
instead. */
if (get_AT_unsigned (c, DW_AT_virtuality) == DW_VIRTUALITY_virtual)
return;
- *el = (codeview_subtype *) xmalloc (sizeof (**el));
- (*el)->next = NULL;
- (*el)->kind = LF_BCLASS;
- (*el)->lf_bclass.attributes = accessibility;
- (*el)->lf_bclass.base_class_type = get_type_num (get_AT_ref (c, DW_AT_type),
+ el = (codeview_subtype *) xmalloc (sizeof (*el));
+ el->next = NULL;
+ el->kind = LF_BCLASS;
+ el->lf_bclass.attributes = accessibility;
+ el->lf_bclass.base_class_type = get_type_num (get_AT_ref (c, DW_AT_type),
true, false);
- (*el)->lf_bclass.offset.neg = false;
- (*el)->lf_bclass.offset.num = get_AT_unsigned (c, DW_AT_data_member_location);
+ el->lf_bclass.offset.neg = false;
+ el->lf_bclass.offset.num = get_AT_unsigned (c, DW_AT_data_member_location);
- *el_len = 10 + cv_integer_len (&(*el)->lf_bclass.offset);
+ el_len = 10 + cv_integer_len (&el->lf_bclass.offset);
- if (*el_len % 4)
- *el_len += 4 - (*el_len % 4);
+ if (el_len % 4)
+ el_len += 4 - (el_len % 4);
+
+ add_to_fieldlist (ct, num_members, el, el_len);
}
/* Create a new LF_MFUNCTION type for a struct function, add it to the
@@ -5689,26 +5782,30 @@ is_templated_func (dw_die_ref die)
contained within it. */
static void
-add_struct_nested_type (dw_die_ref c, codeview_subtype **el, size_t *el_len)
+add_struct_nested_type (dw_die_ref c, codeview_custom_type **ct,
+ uint16_t *num_members)
{
const char *name = get_AT_string (c, DW_AT_name);
- size_t name_len;
+ codeview_subtype *el;
+ size_t name_len, el_len;
if (!name)
return;
name_len = strlen (name);
- *el = (codeview_subtype *) xmalloc (sizeof (**el));
- (*el)->next = NULL;
- (*el)->kind = LF_NESTTYPE;
- (*el)->lf_nesttype.type = get_type_num (c, true, false);
- (*el)->lf_nesttype.name = xstrdup (name);
+ el = (codeview_subtype *) xmalloc (sizeof (*el));
+ el->next = NULL;
+ el->kind = LF_NESTTYPE;
+ el->lf_nesttype.type = get_type_num (c, true, false);
+ el->lf_nesttype.name = xstrdup (name);
- *el_len = 9 + name_len;
+ el_len = 9 + name_len;
- if (*el_len % 4)
- *el_len += 4 - (*el_len % 4);
+ if (el_len % 4)
+ el_len += 4 - (el_len % 4);
+
+ add_to_fieldlist (ct, num_members, el, el_len);
}
/* Process a DW_TAG_structure_type, DW_TAG_class_type, or DW_TAG_union_type
@@ -5822,8 +5919,6 @@ get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref)
c = first_child;
do
{
- codeview_subtype *el;
- size_t el_len = 0;
uint16_t accessibility;
c = dw_get_die_sib (c);
@@ -5833,73 +5928,32 @@ get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref)
switch (dw_get_die_tag (c))
{
case DW_TAG_member:
- add_struct_member (c, accessibility, &el, &el_len);
+ add_struct_member (c, accessibility, &ct, &num_members, 0);
break;
case DW_TAG_variable:
- add_struct_static_member (c, accessibility, &el, &el_len);
+ add_struct_static_member (c, accessibility, &ct, &num_members);
break;
case DW_TAG_subprogram:
if (!is_templated_func (c))
- add_struct_function (c, method_htab, &el, &el_len);
+ add_struct_function (c, method_htab, &ct, &num_members);
break;
case DW_TAG_inheritance:
- add_struct_inheritance (c, accessibility, &el, &el_len);
+ add_struct_inheritance (c, accessibility, &ct, &num_members);
break;
case DW_TAG_structure_type:
case DW_TAG_class_type:
case DW_TAG_union_type:
case DW_TAG_enumeration_type:
- add_struct_nested_type (c, &el, &el_len);
+ add_struct_nested_type (c, &ct, &num_members);
break;
default:
break;
}
-
- if (el_len == 0)
- continue;
-
- /* Add an LF_INDEX subtype if everything's too big for one
- LF_FIELDLIST. */
-
- if (ct->lf_fieldlist.length + el_len > MAX_FIELDLIST_SIZE)
- {
- codeview_subtype *idx;
- codeview_custom_type *ct2;
-
- idx = (codeview_subtype *) xmalloc (sizeof (*idx));
- idx->next = NULL;
- idx->kind = LF_INDEX;
- idx->lf_index.type_num = 0;
-
- ct->lf_fieldlist.last_subtype->next = idx;
- ct->lf_fieldlist.last_subtype = idx;
-
- ct2 = (codeview_custom_type *)
- xmalloc (sizeof (codeview_custom_type));
-
- ct2->next = ct;
- ct2->kind = LF_FIELDLIST;
- ct2->lf_fieldlist.length = 0;
- ct2->lf_fieldlist.subtypes = NULL;
- ct2->lf_fieldlist.last_subtype = NULL;
-
- ct = ct2;
- }
-
- ct->lf_fieldlist.length += el_len;
-
- if (ct->lf_fieldlist.last_subtype)
- ct->lf_fieldlist.last_subtype->next = el;
- else
- ct->lf_fieldlist.subtypes = el;
-
- ct->lf_fieldlist.last_subtype = el;
- num_members++;
}
while (c != first_child);