---
 gcc/pdbout.c | 149 +++++++++++++++++++++++++++++++++++++++++++++++++--
 gcc/pdbout.h |  12 +++++
 2 files changed, 158 insertions(+), 3 deletions(-)

diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index feaab37cc37..17011134d7a 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -29,14 +29,25 @@
 #include "tree.h"
 #include "debug.h"
 #include "pdbout.h"
+#include "function.h"
 #include "output.h"
 #include "target.h"
 
+#define FUNC_BEGIN_LABEL       ".Lstartfunc"
+#define FUNC_END_LABEL         ".Lendfunc"
+
+static void pdbout_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
+                                  unsigned int column ATTRIBUTE_UNUSED,
+                                  const char *file ATTRIBUTE_UNUSED);
+static void pdbout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
+                                const char *file ATTRIBUTE_UNUSED);
 static void pdbout_finish (const char *filename);
+static void pdbout_begin_function (tree func);
 static void pdbout_late_global_decl (tree var);
 
 static struct pdb_type *find_type (tree t);
 
+static struct pdb_func *funcs = NULL, *cur_func = NULL;
 static struct pdb_global_var *global_vars = NULL;
 static struct pdb_type *types = NULL, *last_type = NULL;
 static hash_table <pdb_type_tree_hasher> tree_hash_table (31);
@@ -66,11 +77,11 @@ const struct gcc_debug_hooks pdb_debug_hooks = {
   debug_nothing_int_int,       /* end_block */
   debug_true_const_tree,       /* ignore_block */
   debug_nothing_int_int_charstar_int_bool,     /* source_line */
-  debug_nothing_int_int_charstar,      /* begin_prologue */
+  pdbout_begin_prologue,
   debug_nothing_int_charstar,  /* end_prologue */
   debug_nothing_int_charstar,  /* begin_epilogue */
-  debug_nothing_int_charstar,  /* end_epilogue */
-  debug_nothing_tree,          /* begin_function */
+  pdbout_end_epilogue,
+  pdbout_begin_function,
   debug_nothing_int,           /* end_function */
   debug_nothing_tree,          /* register_main_translation_unit */
   debug_nothing_tree,          /* function_decl */
@@ -93,6 +104,84 @@ const struct gcc_debug_hooks pdb_debug_hooks = {
   TYPE_SYMTAB_IS_ADDRESS       /* tree_type_symtab_field */
 };
 
+/* Add label before function start */
+static void
+pdbout_begin_prologue (unsigned int line ATTRIBUTE_UNUSED,
+                      unsigned int column ATTRIBUTE_UNUSED,
+                      const char *file ATTRIBUTE_UNUSED)
+{
+  fprintf (asm_out_file, FUNC_BEGIN_LABEL "%u:\n",
+          current_function_funcdef_no);
+}
+
+/* Add label after function end */
+static void
+pdbout_end_epilogue (unsigned int line ATTRIBUTE_UNUSED,
+                    const char *file ATTRIBUTE_UNUSED)
+{
+  fprintf (asm_out_file, FUNC_END_LABEL "%u:\n", current_function_funcdef_no);
+}
+
+/* Output PROCSYM32 structure, which describes a global function (S_GPROC32)
+ * or a local (i.e. static) one (S_LPROC32). */
+static void
+pdbout_proc32 (struct pdb_func *func)
+{
+  size_t name_len = func->name ? strlen (func->name) : 0;
+  uint16_t len = 40 + name_len, align;
+
+  // start procedure
+
+  if (len % 4 != 0)
+    {
+      align = 4 - (len % 4);
+      len += 4 - (len % 4);
+    }
+  else
+    align = 0;
+
+  fprintf (asm_out_file, ".Lcvprocstart%u:\n", func->num);
+  fprintf (asm_out_file, "\t.short\t0x%x\n",
+          (uint16_t) (len - sizeof (uint16_t)));       // reclen
+  fprintf (asm_out_file, "\t.short\t0x%x\n",
+          func->public_flag ? S_GPROC32 : S_LPROC32);
+  fprintf (asm_out_file, "\t.long\t0\n");      // pParent
+  fprintf (asm_out_file, "\t.long\t[.Lcvprocend%u]-[.debug$S]\n",
+          func->num);  // pEnd
+  fprintf (asm_out_file, "\t.long\t0\n");      // pNext
+  fprintf (asm_out_file,
+          "\t.long\t[" FUNC_END_LABEL "%u]-[" FUNC_BEGIN_LABEL "%u]\n",
+          func->num, func->num);       // len
+  fprintf (asm_out_file, "\t.long\t0\n");      // DbgStart
+  fprintf (asm_out_file, "\t.long\t0\n");      // DbgEnd
+  fprintf (asm_out_file, "\t.short\t0x%x\n", func->type ? func->type->id : 0);
+  fprintf (asm_out_file, "\t.short\t0\n");     // padding
+
+  fprintf (asm_out_file, "\t.secrel32\t" FUNC_BEGIN_LABEL "%u\n",
+          func->num);  // offset
+  fprintf (asm_out_file, "\t.secidx\t" FUNC_BEGIN_LABEL "%u\n",
+          func->num);  // section
+
+  fprintf (asm_out_file, "\t.byte\t0\n");      // flags
+
+  if (func->name)
+    ASM_OUTPUT_ASCII (asm_out_file, func->name, name_len + 1);
+  else
+    fprintf (asm_out_file, "\t.byte\t0\n");
+
+  for (unsigned int i = 0; i < align; i++)
+    {
+      fprintf (asm_out_file, "\t.byte\t0\n");
+    }
+
+  // end procedure
+
+  fprintf (asm_out_file, ".Lcvprocend%u:\n", func->num);
+
+  fprintf (asm_out_file, "\t.short\t0x2\n");
+  fprintf (asm_out_file, "\t.short\t0x%x\n", S_END);
+}
+
 /* Output DATASYM32 structure, describing a global variable: either
  * one with file-level scope (S_LDATA32) or global scope (S_GDATA32). */
 static void
@@ -138,6 +227,8 @@ pdbout_data32 (struct pdb_global_var *v)
 static void
 write_pdb_section (void)
 {
+  struct pdb_func *func;
+
   fprintf (asm_out_file, "\t.section\t.debug$S, \"ndr\"\n");
   fprintf (asm_out_file, "\t.long\t0x%x\n", CV_SIGNATURE_C13);
   fprintf (asm_out_file, "\t.long\t0x%x\n", DEBUG_S_SYMBOLS);
@@ -164,7 +255,27 @@ write_pdb_section (void)
       global_vars = n;
     }
 
+  func = funcs;
+  while (func)
+    {
+      pdbout_proc32 (func);
+
+      func = func->next;
+    }
+
   fprintf (asm_out_file, ".Lsymend:\n");
+
+  while (funcs)
+    {
+      struct pdb_func *n = funcs->next;
+
+      if (funcs->name)
+       free (funcs->name);
+
+      free (funcs);
+
+      funcs = n;
+    }
 }
 
 /* We've finished compilation - output the .debug$S section
@@ -175,6 +286,38 @@ pdbout_finish (const char *filename ATTRIBUTE_UNUSED)
   write_pdb_section ();
 }
 
+/* For a tree t, construct the name. */
+static char *
+get_tree_name (tree t)
+{
+  char *name;
+
+  if (TREE_CODE (t) == FUNCTION_DECL)
+    name = xstrdup (IDENTIFIER_POINTER (DECL_NAME (t)));
+  else
+    return NULL;
+
+  return name;
+}
+
+/* We've been passed a function definition - allocate and initialize a pdb_func
+ * struct to represent it. */
+static void
+pdbout_begin_function (tree func)
+{
+  struct pdb_func *f = (struct pdb_func *) xmalloc (sizeof (struct pdb_func));
+
+  f->next = funcs;
+  f->name = get_tree_name (func);
+  f->num = current_function_funcdef_no;
+  f->public_flag = TREE_PUBLIC (func);
+  f->type = find_type (TREE_TYPE (func));
+
+  funcs = f;
+
+  cur_func = f;
+}
+
 /* We've been passed a late global declaration, i.e. a global variable -
  * allocate a pdb_global_var struct and add it to the list of globals. */
 static void
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
index e3430793ee7..85a1eb548cb 100644
--- a/gcc/pdbout.h
+++ b/gcc/pdbout.h
@@ -20,14 +20,26 @@
 #ifndef GCC_PDBOUT_H
 #define GCC_PDBOUT_H 1
 
+#define S_END                          0x0006
 #define S_LDATA32                      0x110c
 #define S_GDATA32                      0x110d
+#define S_LPROC32                      0x110f
+#define S_GPROC32                      0x1110
 
 /* Format version as of MSVC 7 */
 #define CV_SIGNATURE_C13       4
 
 #define DEBUG_S_SYMBOLS                        0xf1
 
+struct pdb_func
+{
+  struct pdb_func *next;
+  char *name;
+  int num;
+  unsigned int public_flag;
+  struct pdb_type *type;
+};
+
 struct pdb_global_var
 {
   struct pdb_global_var *next;
-- 
2.26.2

Reply via email to