diff mbox series

[3/4] Write CodeView S_FRAMEPROC symbols

Message ID 20240819011530.25488-3-mark@harmstone.com
State New
Headers show
Series [1/4] Write CodeView information about enregistered optimized variables | expand

Commit Message

Mark Harmstone Aug. 19, 2024, 1:15 a.m. UTC
Write S_FRAMEPROC symbols, which aren't very useful but seem to be necessary
for Microsoft debuggers to function properly. These symbols come after S_LOCAL
symbols for optimized variables, but before S_REGISTER and S_REGREL32 for
unoptimized variables.

gcc/
	* dwarf2codeview.cc (enum cv_sym_type): Add S_FRAMEPROC.
	(write_s_frameproc): New function.
	(write_function): Call write_s_frameproc.
---
 gcc/dwarf2codeview.cc | 80 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 78 insertions(+), 2 deletions(-)
diff mbox series

Patch

diff --git a/gcc/dwarf2codeview.cc b/gcc/dwarf2codeview.cc
index 74bbf6bc1d7..88310504cf7 100644
--- a/gcc/dwarf2codeview.cc
+++ b/gcc/dwarf2codeview.cc
@@ -71,6 +71,7 @@  along with GCC; see the file COPYING3.  If not see
 
 enum cv_sym_type {
   S_END = 0x0006,
+  S_FRAMEPROC = 0x1012,
   S_BLOCK32 = 0x1103,
   S_REGISTER = 0x1106,
   S_LDATA32 = 0x110c,
@@ -2822,6 +2823,74 @@  write_s_end (void)
   targetm.asm_out.internal_label (asm_out_file, SYMBOL_END_LABEL, label_num);
 }
 
+/* Write the S_FRAMEPROC symbol, which is supposed to give information about
+   the function frame.  It doesn't seem to be really used in modern versions of
+   MSVC, which is why we zero-out everything here.  You still need to write it
+   though, otherwise windbg won't necessarily show all the local variables.  */
+
+static void
+write_s_frameproc (void)
+{
+  unsigned int label_num = ++sym_label_num;
+
+  /* This is struct FRAMEPROCSYM in Microsoft's cvinfo.h:
+
+      struct frameprocsym
+      {
+	uint16_t size;
+	uint16_t kind;
+	uint32_t frame_size;
+	uint32_t padding_size;
+	uint32_t padding_offset;
+	uint32_t saved_registers_size;
+	uint32_t exception_handler_offset;
+	uint16_t exception_handler_section;
+	uint32_t flags;
+      } 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_FRAMEPROC);
+  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);
+  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);
+  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 (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, 0);
+  putc ('\n', asm_out_file);
+
+  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.  */
 
@@ -3070,9 +3139,16 @@  write_function (codeview_symbol *s)
     fbloc = frame_base->dw_attr_val.v.val_loc;
 
   if (flag_var_tracking)
-    write_optimized_function_vars (s->function.die, fbloc, rtx_low, rtx_high);
+    {
+      write_optimized_function_vars (s->function.die, fbloc, rtx_low,
+				     rtx_high);
+      write_s_frameproc ();
+    }
   else
-    write_unoptimized_function_vars (s->function.die, fbloc);
+    {
+      write_s_frameproc ();
+      write_unoptimized_function_vars (s->function.die, fbloc);
+    }
 
   /* Output the S_PROC_ID_END record.  */