[05/11] Handle const and varible modifiers for CodeView
Commit Message
Translate DW_TAG_const_type and DW_TAG_volatile_type DIEs into
LF_MODIFIER symbols.
gcc/
* dwarf2codeview.cc
(struct codeview_custom_type): Add lf_modifier to union.
(write_cv_padding, write_lf_modifier): New functions.
(write_custom_types): Call write_lf_modifier.
(get_type_num_const_type): New function.
(get_type_num_volatile_type): Likewise.
(get_type_num): Handle DW_TAG_const_type and
DW_TAG_volatile_type DIEs.
* dwarf2codeview.h (MOD_const, MOD_volatile): Define.
(LF_MODIFIER): Likewise.
---
gcc/dwarf2codeview.cc | 157 ++++++++++++++++++++++++++++++++++++++++++
gcc/dwarf2codeview.h | 5 ++
2 files changed, 162 insertions(+)
Comments
On 6/17/24 6:17 PM, Mark Harmstone wrote:
> Translate DW_TAG_const_type and DW_TAG_volatile_type DIEs into
> LF_MODIFIER symbols.
>
> gcc/
> * dwarf2codeview.cc
> (struct codeview_custom_type): Add lf_modifier to union.
> (write_cv_padding, write_lf_modifier): New functions.
> (write_custom_types): Call write_lf_modifier.
> (get_type_num_const_type): New function.
> (get_type_num_volatile_type): Likewise.
> (get_type_num): Handle DW_TAG_const_type and
> DW_TAG_volatile_type DIEs.
> * dwarf2codeview.h (MOD_const, MOD_volatile): Define.
> (LF_MODIFIER): Likewise.
> ---
> @@ -903,6 +908,76 @@ write_lf_pointer (codeview_custom_type *t)
> asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
> }
>
> +/* All CodeView type definitions have to be aligned to a four-byte boundary,
> + so write some padding bytes if necessary. These have to be specific values:
> + f3, f2, f1. */
Consider changing the magic numbers to a #define or const object or an
enum as a follow-up.
> +
> + ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
So presumably you're freeing these objects elsewhere? I see the free
(custom_types), but I don' see where you free an subobjects. Did I miss
something?
I'll go ahead and commit, but please double check for memory leaks.
Jeff
On 24/6/24 04:39, Jeff Law wrote:
>>
> So presumably you're freeing these objects elsewhere? I see the free (custom_types), but I don' see where you free an subobjects. Did I miss something?
>
> I'll go ahead and commit, but please double check for memory leaks.
Thanks Jeff. I just realized I wrote "varible" rather than "volatile" - ah well.
See patch 4 - write_custom_types loops through the custom_types linked list, and removes and frees the head until it's empty.
Mark
On 6/24/24 8:49 PM, Mark Harmstone wrote:
> On 24/6/24 04:39, Jeff Law wrote:
>>>
>> So presumably you're freeing these objects elsewhere? I see the free
>> (custom_types), but I don' see where you free an subobjects. Did I
>> miss something?
>>
>> I'll go ahead and commit, but please double check for memory leaks.
>
> Thanks Jeff. I just realized I wrote "varible" rather than "volatile" -
> ah well.
Trivially fixable with a follow-up patch.
>
> See patch 4 - write_custom_types loops through the custom_types linked
> list, and removes and frees the head until it's empty.
Thanks. I suspected it was the walk down that list, but better to just
ask the author to be sure :-) Thanks.
jeff
@@ -183,6 +183,11 @@ struct codeview_custom_type
uint32_t base_type;
uint32_t attributes;
} lf_pointer;
+ struct
+ {
+ uint32_t base_type;
+ uint16_t modifier;
+ } lf_modifier;
};
};
@@ -903,6 +908,76 @@ write_lf_pointer (codeview_custom_type *t)
asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
}
+/* All CodeView type definitions have to be aligned to a four-byte boundary,
+ so write some padding bytes if necessary. These have to be specific values:
+ f3, f2, f1. */
+
+static void
+write_cv_padding (size_t padding)
+{
+ if (padding == 4 || padding == 0)
+ return;
+
+ if (padding == 3)
+ {
+ fputs (integer_asm_op (1, false), asm_out_file);
+ fprint_whex (asm_out_file, 0xf3);
+ putc ('\n', asm_out_file);
+ }
+
+ if (padding >= 2)
+ {
+ fputs (integer_asm_op (1, false), asm_out_file);
+ fprint_whex (asm_out_file, 0xf2);
+ putc ('\n', asm_out_file);
+ }
+
+ fputs (integer_asm_op (1, false), asm_out_file);
+ fprint_whex (asm_out_file, 0xf1);
+ putc ('\n', asm_out_file);
+}
+
+/* Write an LF_MODIFIER type, representing a const and/or volatile modification
+ of another type. */
+
+static void
+write_lf_modifier (codeview_custom_type *t)
+{
+ /* This is lf_modifier in binutils and lfModifier in Microsoft's cvinfo.h:
+
+ struct lf_modifier
+ {
+ uint16_t size;
+ uint16_t kind;
+ uint32_t base_type;
+ uint16_t modifier;
+ uint16_t padding;
+ } 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_modifier.base_type);
+ putc ('\n', asm_out_file);
+
+ fputs (integer_asm_op (2, false), asm_out_file);
+ fprint_whex (asm_out_file, t->lf_modifier.modifier);
+ putc ('\n', asm_out_file);
+
+ write_cv_padding (2);
+
+ asm_fprintf (asm_out_file, "%LLcv_type%x_end:\n", t->num);
+}
+
/* Write the .debug$T section, which contains all of our custom type
definitions. */
@@ -924,6 +999,10 @@ write_custom_types (void)
case LF_POINTER:
write_lf_pointer (custom_types);
break;
+
+ case LF_MODIFIER:
+ write_lf_modifier (custom_types);
+ break;
}
free (custom_types);
@@ -1159,6 +1238,76 @@ get_type_num_pointer_type (dw_die_ref type)
return ct->num;
}
+/* Process a DW_TAG_const_type DIE, adding an LF_MODIFIER type and returning
+ its number. */
+
+static uint32_t
+get_type_num_const_type (dw_die_ref type)
+{
+ dw_die_ref base_type;
+ uint32_t base_type_num;
+ codeview_custom_type *ct;
+ bool is_volatile = false;
+
+ base_type = get_AT_ref (type, DW_AT_type);
+ if (!base_type)
+ return 0;
+
+ /* Handle case when this is a const volatile type - we only need one
+ LF_MODIFIER for this. */
+ if (dw_get_die_tag (base_type) == DW_TAG_volatile_type)
+ {
+ is_volatile = true;
+
+ base_type = get_AT_ref (base_type, DW_AT_type);
+ if (!base_type)
+ return 0;
+ }
+
+ base_type_num = get_type_num (base_type);
+ if (base_type_num == 0)
+ return 0;
+
+ ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
+
+ ct->next = NULL;
+ ct->kind = LF_MODIFIER;
+ ct->lf_modifier.base_type = base_type_num;
+ ct->lf_modifier.modifier = MOD_const;
+
+ if (is_volatile)
+ ct->lf_modifier.modifier |= MOD_volatile;
+
+ add_custom_type (ct);
+
+ return ct->num;
+}
+
+/* Process a DW_TAG_volatile_type DIE, adding an LF_MODIFIER type and
+ returning its number. */
+
+static uint32_t
+get_type_num_volatile_type (dw_die_ref type)
+{
+ uint32_t base_type_num;
+ codeview_custom_type *ct;
+
+ base_type_num = get_type_num (get_AT_ref (type, DW_AT_type));
+ if (base_type_num == 0)
+ return 0;
+
+ ct = (codeview_custom_type *) xmalloc (sizeof (codeview_custom_type));
+
+ ct->next = NULL;
+ ct->kind = LF_MODIFIER;
+ ct->lf_modifier.base_type = base_type_num;
+ ct->lf_modifier.modifier = MOD_volatile;
+
+ add_custom_type (ct);
+
+ return ct->num;
+}
+
/* Process a DIE representing a type definition, add a CodeView type if
necessary, and return its number. If it's something we can't handle, return
0. We keep a hash table so that we're not adding the same type multiple
@@ -1201,6 +1350,14 @@ get_type_num (dw_die_ref type)
t->num = get_type_num_pointer_type (type);
break;
+ case DW_TAG_const_type:
+ t->num = get_type_num_const_type (type);
+ break;
+
+ case DW_TAG_volatile_type:
+ t->num = get_type_num_volatile_type (type);
+ break;
+
default:
t->num = 0;
break;
@@ -56,7 +56,12 @@ along with GCC; see the file COPYING3. If not see
#define CV_PTR_NEAR32 0x0a
#define CV_PTR_64 0x0c
+/* LF_MODIFIER values. */
+#define MOD_const 0x1
+#define MOD_volatile 0x2
+
/* Constants for type definitions. */
+#define LF_MODIFIER 0x1001
#define LF_POINTER 0x1002
/* Debug Format Interface. Used in dwarf2out.cc. */