https://gcc.gnu.org/g:14d706ed0e90373c98a0ce223ffeea8846f6d9bc
commit r15-5433-g14d706ed0e90373c98a0ce223ffeea8846f6d9bc Author: Mark Harmstone <m...@harmstone.com> Date: Tue Nov 19 00:46:45 2024 +0000 Produce CodeView info about nested types If the DIE for a struct, class, or union contains a nested type, add a LF_NESTTYPE entry to its field list recording this. Plus if we use a nested type, make sure that its parent also gets defined. This may entail adding a forward definition and creating a deferred type, so we need to call flush_deferred_types in codeview_debug_finish as well. gcc/ * dwarf2codeview.cc (enum cv_leaf_type): Add LF_NESTTYPE. (struct codeview_subtype): Add lf_nesttype to union. (flush_deferred_types): Add declaration. (write_lf_fieldlist): Handle LF_NESTTYPE. (codeview_debug_finish): Call flush_deferred_types. (add_struct_nested_type): New function. (get_type_num_struct): Call add_struct_nested_type, and if nested make that parent is added. Diff: --- gcc/dwarf2codeview.cc | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc index 5e8a4ab39e7d..ccb1109611c9 100644 --- a/gcc/dwarf2codeview.cc +++ b/gcc/dwarf2codeview.cc @@ -111,6 +111,7 @@ enum cv_leaf_type { LF_MEMBER = 0x150d, LF_STMEMBER = 0x150e, LF_METHOD = 0x150f, + LF_NESTTYPE = 0x1510, LF_ONEMETHOD = 0x1511, LF_FUNC_ID = 0x1601, LF_MFUNC_ID = 0x1602, @@ -1249,6 +1250,11 @@ struct codeview_subtype uint32_t base_class_type; codeview_integer offset; } lf_bclass; + struct + { + uint32_t type; + char *name; + } lf_nesttype; }; }; @@ -1432,6 +1438,7 @@ static uint32_t get_type_num_subroutine_type (dw_die_ref type, bool in_struct, uint32_t this_type, int32_t this_adjustment); static void write_cv_padding (size_t padding); +static void flush_deferred_types (void); /* Record new line number against the current function. */ @@ -3904,6 +3911,40 @@ write_lf_fieldlist (codeview_custom_type *t) write_cv_padding (4 - (leaf_len % 4)); break; + case LF_NESTTYPE: + /* This is lf_nest_type in binutils and lfNestType in Microsoft's + cvinfo.h: + + struct lf_nest_type + { + uint16_t kind; + uint16_t padding; + uint32_t type; + char name[]; + } ATTRIBUTE_PACKED; + */ + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, LF_NESTTYPE); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (2, false), asm_out_file); + fprint_whex (asm_out_file, 0); + putc ('\n', asm_out_file); + + fputs (integer_asm_op (4, false), asm_out_file); + fprint_whex (asm_out_file, v->lf_nesttype.type); + putc ('\n', asm_out_file); + + name_len = strlen (v->lf_nesttype.name) + 1; + ASM_OUTPUT_ASCII (asm_out_file, v->lf_nesttype.name, name_len); + + leaf_len = 8 + name_len; + write_cv_padding (4 - (leaf_len % 4)); + + free (v->lf_nesttype.name); + break; + default: break; } @@ -4673,6 +4714,12 @@ codeview_debug_finish (void) write_line_numbers (); write_codeview_symbols (); + /* If we reference a nested struct but not its parent, add_deferred_type + gets called if we create a forward reference for this, even though we've + already flushed this in codeview_debug_early_finish. In this case we will + need to flush this list again. */ + flush_deferred_types (); + if (custom_types) write_custom_types (); @@ -5638,6 +5685,32 @@ is_templated_func (dw_die_ref die) return false; } +/* Create a field list subtype that records that a struct has a nested type + contained within it. */ + +static void +add_struct_nested_type (dw_die_ref c, codeview_subtype **el, size_t *el_len) +{ + const char *name = get_AT_string (c, DW_AT_name); + size_t name_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_len = 9 + name_len; + + if (*el_len % 4) + *el_len += 4 - (*el_len % 4); +} + /* Process a DW_TAG_structure_type, DW_TAG_class_type, or DW_TAG_union_type DIE, add an LF_FIELDLIST and an LF_STRUCTURE / LF_CLASS / LF_UNION type, and return the number of the latter. */ @@ -5645,11 +5718,18 @@ is_templated_func (dw_die_ref die) static uint32_t get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref) { - dw_die_ref first_child; + dw_die_ref parent, first_child; codeview_custom_type *ct; uint16_t num_members = 0; uint32_t last_type = 0; + parent = dw_get_die_parent(type); + + if (parent && (dw_get_die_tag (parent) == DW_TAG_structure_type + || dw_get_die_tag (parent) == DW_TAG_class_type + || dw_get_die_tag (parent) == DW_TAG_union_type)) + get_type_num (parent, true, false); + if ((in_struct && get_AT_string (type, DW_AT_name)) || get_AT_flag (type, DW_AT_declaration)) { @@ -5769,6 +5849,13 @@ get_type_num_struct (dw_die_ref type, bool in_struct, bool *is_fwd_ref) add_struct_inheritance (c, accessibility, &el, &el_len); 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); + break; + default: break; }