[05/11] Handle const and varible modifiers for CodeView

Message ID 20240618001713.24034-6-mark@harmstone.com
State Committed
Commit 29fec9ee74c3219bce714f2e5b6381a48049e01e
Headers
Series CodeView variables and type system |

Commit Message

Mark Harmstone June 18, 2024, 12:17 a.m. UTC
  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

Jeff Law June 24, 2024, 3:39 a.m. UTC | #1
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
  
Mark Harmstone June 25, 2024, 2:49 a.m. UTC | #2
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
  
Jeff Law June 25, 2024, 5:42 a.m. UTC | #3
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
  

Patch

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 51401f2d5bc..05f5f60997e 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -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;
diff --git a/gcc/dwarf2codeview.h b/gcc/dwarf2codeview.h
index 0af4c98250f..d48cfbebc32 100644
--- a/gcc/dwarf2codeview.h
+++ b/gcc/dwarf2codeview.h
@@ -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.  */