public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* [PATCH 1/3] Write CodeView information about local static variables
@ 2024-08-13  0:24 Mark Harmstone
  2024-08-13  0:24 ` [PATCH 2/3] Write CodeView information about enregistered variables Mark Harmstone
                   ` (2 more replies)
  0 siblings, 3 replies; 5+ messages in thread
From: Mark Harmstone @ 2024-08-13  0:24 UTC (permalink / raw)
  To: gcc-patches; +Cc: Mark Harmstone

Outputs CodeView S_LDATA32 symbols, for static variables within
functions, along with S_BLOCK32 and S_END for the beginning and end of
lexical blocks.

gcc/
	* dwarf2codeview.cc (enum cv_sym_type): Add S_END and S_BLOCK32.
	(write_local_s_ldata32): New function.
	(write_unoptimized_local_variable): New function.
	(write_s_block32): New function.
	(write_s_end): New function.
	(write_unoptimized_function_vars): New function.
	(write_function): Call write_unoptimized_function_vars.
---
 gcc/dwarf2codeview.cc | 258 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 258 insertions(+)

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 7e4faaa9388..cb2d64bfcc6 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -70,6 +70,8 @@ along with GCC; see the file COPYING3.  If not see
 /* This is enum SYM_ENUM_e in Microsoft's cvinfo.h.  */
 
 enum cv_sym_type {
+  S_END = 0x0006,
+  S_BLOCK32 = 0x1103,
   S_LDATA32 = 0x110c,
   S_GDATA32 = 0x110d,
   S_COMPILE3 = 0x113c,
@@ -986,6 +988,260 @@ end:
   free (s->data_symbol.name);
 }
 
+/* Write an S_LDATA32 symbol, representing a static variable within a function.
+   This symbol can also appear outside of a function block - see
+   write_data_symbol.  */
+
+static void
+write_local_s_ldata32 (dw_die_ref die, dw_loc_descr_ref loc_ref)
+{
+  unsigned int label_num = ++sym_label_num;
+  const char *name = get_AT_string (die, DW_AT_name);
+  uint32_t type;
+
+  /* This is struct datasym in binutils:
+
+      struct datasym
+      {
+	uint16_t size;
+	uint16_t kind;
+	uint32_t type;
+	uint32_t offset;
+	uint16_t section;
+	char name[];
+      } ATTRIBUTE_PACKED;
+  */
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file,
+	       "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
+	       label_num, label_num);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, S_LDATA32);
+  putc ('\n', asm_out_file);
+
+  type = get_type_num (get_AT_ref (die, DW_AT_type), false, false);
+
+  fputs (integer_asm_op (4, false), asm_out_file);
+  fprint_whex (asm_out_file, type);
+  putc ('\n', asm_out_file);
+
+  asm_fprintf (asm_out_file, "\t.secrel32 ");
+  output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr);
+  fputc ('\n', asm_out_file);
+
+  asm_fprintf (asm_out_file, "\t.secidx ");
+  output_addr_const (asm_out_file, loc_ref->dw_loc_oprnd1.v.val_addr);
+  fputc ('\n', asm_out_file);
+
+  ASM_OUTPUT_ASCII (asm_out_file, name, strlen (name) + 1);
+
+  ASM_OUTPUT_ALIGN (asm_out_file, 2);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
+}
+
+/* Write a symbol representing an unoptimized variable within a function, if
+   we're able to translate the DIE's DW_AT_location into its CodeView
+   equivalent.  */
+
+static void
+write_unoptimized_local_variable (dw_die_ref die)
+{
+  dw_attr_node *loc;
+  dw_loc_descr_ref loc_ref;
+
+  loc = get_AT (die, DW_AT_location);
+  if (!loc)
+    return;
+
+  if (loc->dw_attr_val.val_class != dw_val_class_loc)
+    return;
+
+  loc_ref = loc->dw_attr_val.v.val_loc;
+  if (!loc_ref)
+    return;
+
+  switch (loc_ref->dw_loc_opc)
+    {
+    case DW_OP_addr:
+      write_local_s_ldata32 (die, loc_ref);
+      break;
+
+    default:
+      break;
+    }
+}
+
+/* Translate a DW_TAG_lexical_block DIE into an S_BLOCK32 symbol, representing
+   a block within an unoptimized function.  Returns false if we're not able
+   to resolve the location, which will prevent the caller from issuing an
+   unneeded S_END.  */
+
+static bool
+write_s_block32 (dw_die_ref die)
+{
+  unsigned int label_num = ++sym_label_num;
+  dw_attr_node *loc_low, *loc_high;
+  const char *label_low, *label_high;
+  rtx rtx_low, rtx_high;
+
+  /* This is struct blocksym in binutils and BLOCKSYM32 in Microsoft's
+     cvinfo.h:
+
+    struct blocksym
+    {
+      uint16_t size;
+      uint16_t kind;
+      uint32_t parent;
+      uint32_t end;
+      uint32_t len;
+      uint32_t offset;
+      uint16_t section;
+      char name[];
+    } ATTRIBUTE_PACKED;
+  */
+
+  loc_low = get_AT (die, DW_AT_low_pc);
+  if (!loc_low)
+    return false;
+
+  if (loc_low->dw_attr_val.val_class != dw_val_class_lbl_id)
+    return false;
+
+  label_low = loc_low->dw_attr_val.v.val_lbl_id;
+  if (!label_low)
+    return false;
+
+  rtx_low = gen_rtx_SYMBOL_REF (Pmode, label_low);
+
+  loc_high = get_AT (die, DW_AT_high_pc);
+  if (!loc_high)
+    return false;
+
+  if (loc_high->dw_attr_val.val_class != dw_val_class_high_pc)
+    return false;
+
+  label_high = loc_high->dw_attr_val.v.val_lbl_id;
+  if (!label_high)
+    return false;
+
+  rtx_high = gen_rtx_SYMBOL_REF (Pmode, label_high);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file,
+	       "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
+	       label_num, label_num);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, S_BLOCK32);
+  putc ('\n', asm_out_file);
+
+  /* The parent and end fields get filled in by the linker.  */
+
+  fputs (integer_asm_op (4, 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, 0);
+  putc ('\n', asm_out_file);
+
+  fputs (integer_asm_op (4, false), asm_out_file);
+  output_addr_const (asm_out_file, rtx_high);
+  fputs (" - ", asm_out_file);
+  output_addr_const (asm_out_file, rtx_low);
+  putc ('\n', asm_out_file);
+
+  asm_fprintf (asm_out_file, "\t.secrel32 ");
+  output_addr_const (asm_out_file, rtx_low);
+  fputc ('\n', asm_out_file);
+
+  asm_fprintf (asm_out_file, "\t.secidx ");
+  output_addr_const (asm_out_file, rtx_low);
+  fputc ('\n', asm_out_file);
+
+  ASM_OUTPUT_ASCII (asm_out_file, "", 1);
+
+  ASM_OUTPUT_ALIGN (asm_out_file, 2);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
+
+  return true;
+}
+
+/* Write an S_END symbol, which is used to finish off a number of different
+   symbol types.  Here we use it to mark the S_BLOCK32 as finished.  */
+
+static void
+write_s_end (void)
+{
+  unsigned int label_num = ++sym_label_num;
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  asm_fprintf (asm_out_file,
+	       "%L" SYMBOL_END_LABEL "%u - %L" SYMBOL_START_LABEL "%u\n",
+	       label_num, label_num);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_START_LABEL, label_num);
+
+  fputs (integer_asm_op (2, false), asm_out_file);
+  fprint_whex (asm_out_file, S_END);
+  putc ('\n', asm_out_file);
+
+  ASM_OUTPUT_ALIGN (asm_out_file, 2);
+
+  targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
+}
+
+/* Loop through the DIEs in an unoptimized function, writing out any variables
+   or blocks that we encounter.  */
+
+static void
+write_unoptimized_function_vars (dw_die_ref die)
+{
+  dw_die_ref first_child, c;
+
+  first_child = dw_get_die_child (die);
+
+  if (!first_child)
+    return;
+
+  c = first_child;
+  do
+  {
+    c = dw_get_die_sib (c);
+
+    switch (dw_get_die_tag (c))
+      {
+      case DW_TAG_variable:
+	write_unoptimized_local_variable (c);
+	break;
+
+      case DW_TAG_lexical_block:
+	{
+	  bool block_started = write_s_block32 (c);
+
+	  write_unoptimized_function_vars (c);
+
+	  if (block_started)
+	    write_s_end ();
+
+	  break;
+	}
+
+      default:
+	break;
+      }
+  }
+  while (c != first_child);
+}
+
 /* Write an S_GPROC32_ID symbol, representing a global function, or an
    S_LPROC32_ID symbol, for a static function.  */
 
@@ -1111,6 +1367,8 @@ write_function (codeview_symbol *s)
 
   targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
 
+  write_unoptimized_function_vars (s->function.die);
+
   /* Output the S_PROC_ID_END record.  */
 
   label_num = ++sym_label_num;
-- 
2.44.2


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2024-08-16 20:50 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2024-08-13  0:24 [PATCH 1/3] Write CodeView information about local static variables Mark Harmstone
2024-08-13  0:24 ` [PATCH 2/3] Write CodeView information about enregistered variables Mark Harmstone
2024-08-13  0:24 ` [PATCH 3/3] Write CodeView information about stack variables Mark Harmstone
2024-08-14  4:09 ` [PATCH 1/3] Write CodeView information about local static variables Jeff Law
2024-08-16 20:50   ` Mark Harmstone

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).