--- 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