aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorMark Harmstone <mark@harmstone.com>2024-08-26 22:16:11 +0100
committerMark Harmstone <mark@harmstone.com>2024-08-29 02:53:09 +0100
commit155da081706e0e0527f01ad565b1cd6c217f5880 (patch)
treeb31fea04397cb890c91cc301b517da0ac09482ac /gcc
parentc5043d89449758ecf6a3f1475e027a73976f58c3 (diff)
downloadgcc-155da081706e0e0527f01ad565b1cd6c217f5880.zip
gcc-155da081706e0e0527f01ad565b1cd6c217f5880.tar.gz
gcc-155da081706e0e0527f01ad565b1cd6c217f5880.tar.bz2
Write LF_MFUNC_ID types for CodeView struct member functions
If recording the definition of a struct member function, write an LF_MFUNC_ID type rather than an LF_FUNC_ID. This links directly to the struct type, rather than to an LF_STRING_ID with its name. gcc/ * dwarf2codeview.cc (enum cv_leaf_type): Add LF_MFUNC_ID. (write_lf_mfunc_id): New function. (add_lf_func_id): New function. (add_lf_mfunc_id): New function. (add_function): Call add_lf_func_id or add_lf_mfunc_id.
Diffstat (limited to 'gcc')
-rw-r--r--gcc/dwarf2codeview.cc150
1 files changed, 137 insertions, 13 deletions
diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 00a1795..d593795 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -112,6 +112,7 @@ enum cv_leaf_type {
LF_METHOD = 0x150f,
LF_ONEMETHOD = 0x1511,
LF_FUNC_ID = 0x1601,
+ LF_MFUNC_ID = 0x1602,
LF_STRING_ID = 0x1605,
LF_CHAR = 0x8000,
LF_SHORT = 0x8001,
@@ -4293,6 +4294,56 @@ write_lf_func_id (codeview_custom_type *t)
asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
}
+/* Write an LF_MFUNC_ID type, which is the version of LF_FUNC_ID for struct
+ functions. Instead of an LF_STRING_ID for the parent scope, we write the
+ type number of the parent struct. */
+
+static void
+write_lf_mfunc_id (codeview_custom_type *t)
+{
+ size_t name_len;
+
+ /* This is lf_mfunc_id in binutils and lfMFuncId in Microsoft's cvinfo.h:
+
+ struct lf_mfunc_id
+ {
+ uint16_t size;
+ uint16_t kind;
+ uint32_t parent_type;
+ uint32_t function_type;
+ char name[];
+ } ATTRIBUTE_PACKED
+ */
+
+ fputs (integer_asm_op (2, false), asm_out_file);
+ asm_fprintf (asm_out_file, "%LLcv_type%x_end - %LLcv_type%x_start\n",
+ t->num, t->num);
+
+ asm_fprintf (asm_out_file, "%LLcv_type%x_start:\n", t->num);
+
+ fputs (integer_asm_op (2, false), asm_out_file);
+ fprint_whex (asm_out_file, t->kind);
+ putc ('\n', asm_out_file);
+
+ fputs (integer_asm_op (4, false), asm_out_file);
+ fprint_whex (asm_out_file, t->lf_mfunc_id.parent_type);
+ putc ('\n', asm_out_file);
+
+ fputs (integer_asm_op (4, false), asm_out_file);
+ fprint_whex (asm_out_file, t->lf_mfunc_id.function_type);
+ putc ('\n', asm_out_file);
+
+ name_len = strlen (t->lf_mfunc_id.name) + 1;
+
+ ASM_OUTPUT_ASCII (asm_out_file, t->lf_mfunc_id.name, name_len);
+
+ write_cv_padding (4 - (name_len % 4));
+
+ free (t->lf_mfunc_id.name);
+
+ asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
+}
+
/* Write an LF_STRING_ID type, which provides a deduplicated string that other
types can reference. */
@@ -4523,6 +4574,10 @@ write_custom_types (void)
write_lf_func_id (custom_types);
break;
+ case LF_MFUNC_ID:
+ write_lf_mfunc_id (custom_types);
+ break;
+
case LF_STRING_ID:
write_lf_string_id (custom_types);
break;
@@ -6192,21 +6247,13 @@ get_scope_string_id (dw_die_ref die)
return ret;
}
-/* Process a DW_TAG_subprogram DIE, and add an S_GPROC32_ID or S_LPROC32_ID
- symbol for this. */
+/* Add an LF_FUNC_ID type and return its number (see write_lf_func_id). */
-static void
-add_function (dw_die_ref die)
+static uint32_t
+add_lf_func_id (dw_die_ref die, const char *name)
{
+ uint32_t function_type, scope_type;
codeview_custom_type *ct;
- const char *name = get_AT_string (die, DW_AT_name);
- uint32_t function_type, func_id_type, scope_type;
- codeview_symbol *s;
-
- if (!name)
- return;
-
- /* Add an LF_FUNC_ID type for this function. */
function_type = get_type_num_subroutine_type (die, false, 0, 0, 0);
scope_type = get_scope_string_id (die);
@@ -6221,7 +6268,84 @@ add_function (dw_die_ref die)
add_custom_type (ct);
- func_id_type = ct->num;
+ return ct->num;
+}
+
+/* Add an LF_MFUNC_ID type and return its number (see write_lf_mfunc_id). */
+
+static uint32_t
+add_lf_mfunc_id (dw_die_ref die, const char *name)
+{
+ uint32_t function_type = 0, parent_type;
+ codeview_custom_type *ct;
+ dw_die_ref spec = get_AT_ref (die, DW_AT_specification);
+
+ parent_type = get_type_num (dw_get_die_parent (spec), false, false);
+
+ if (types_htab)
+ {
+ codeview_type **slot;
+
+ slot = types_htab->find_slot_with_hash (spec, htab_hash_pointer (spec),
+ NO_INSERT);
+
+ if (slot && *slot)
+ function_type = (*slot)->num;
+ }
+
+ if (function_type == 0)
+ {
+ function_type = get_type_num_subroutine_type (die, false, parent_type,
+ 0, 0);
+ }
+
+ ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
+
+ ct->next = NULL;
+ ct->kind = LF_MFUNC_ID;
+ ct->lf_mfunc_id.parent_type = parent_type;
+ ct->lf_mfunc_id.function_type = function_type;
+ ct->lf_mfunc_id.name = xstrdup (name);
+
+ add_custom_type (ct);
+
+ return ct->num;
+}
+
+/* Process a DW_TAG_subprogram DIE, and add an S_GPROC32_ID or S_LPROC32_ID
+ symbol for this. */
+
+static void
+add_function (dw_die_ref die)
+{
+ const char *name = get_AT_string (die, DW_AT_name);
+ uint32_t func_id_type;
+ codeview_symbol *s;
+ dw_die_ref spec = get_AT_ref (die, DW_AT_specification);
+ bool do_mfunc_id = false;
+
+ if (!name)
+ return;
+
+ if (spec && dw_get_die_parent (spec))
+ {
+ switch (dw_get_die_tag (dw_get_die_parent (spec)))
+ {
+ case DW_TAG_class_type:
+ case DW_TAG_structure_type:
+ case DW_TAG_union_type:
+ do_mfunc_id = true;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ if (do_mfunc_id)
+ func_id_type = add_lf_mfunc_id (die, name);
+ else
+ func_id_type = add_lf_func_id (die, name);
/* Add an S_GPROC32_ID / S_LPROC32_ID symbol. */