[PATCH 07/24] pdbout: Output line numbers.
Mark Harmstone
mark@harmstone.com
Sat Mar 20 16:26:35 GMT 2021
---
gcc/pdbout.c | 150 ++++++++++++++++++++++++++++++++++++++++++++++++++-
gcc/pdbout.h | 10 ++++
2 files changed, 159 insertions(+), 1 deletion(-)
diff --git a/gcc/pdbout.c b/gcc/pdbout.c
index a4424fa470d..040ac6fe8e4 100644
--- a/gcc/pdbout.c
+++ b/gcc/pdbout.c
@@ -54,6 +54,11 @@ static void pdbout_begin_function (tree func);
static void pdbout_late_global_decl (tree var);
static void pdbout_start_source_file (unsigned int line ATTRIBUTE_UNUSED,
const char *file);
+static void pdbout_source_line (unsigned int line,
+ unsigned int column ATTRIBUTE_UNUSED,
+ const char *text,
+ int discriminator ATTRIBUTE_UNUSED,
+ bool is_stmt ATTRIBUTE_UNUSED);
static void pdbout_function_decl (tree decl);
static void pdbout_var_location (rtx_insn * loc_note);
static void pdbout_begin_block (unsigned int line ATTRIBUTE_UNUSED,
@@ -69,6 +74,7 @@ static struct pdb_global_var *global_vars = NULL;
static struct pdb_type *types = NULL, *last_type = NULL;
static struct pdb_source_file *source_files = NULL, *last_source_file = NULL;
static uint32_t source_file_string_offset = 1;
+static unsigned int num_line_number_entries = 0;
static unsigned int num_source_files = 0;
static unsigned int var_loc_number = 1;
static hash_table <pdb_type_tree_hasher> tree_hash_table (31);
@@ -97,7 +103,7 @@ const struct gcc_debug_hooks pdb_debug_hooks = {
pdbout_begin_block,
pdbout_end_block,
debug_true_const_tree, /* ignore_block */
- debug_nothing_int_int_charstar_int_bool, /* source_line */
+ pdbout_source_line,
pdbout_begin_prologue,
debug_nothing_int_charstar, /* end_prologue */
debug_nothing_int_charstar, /* begin_epilogue */
@@ -617,6 +623,88 @@ write_file_checksums ()
fprintf (asm_out_file, ".Lchksumsend:\n");
}
+/* Loop through each function, and output the line number to
+ * address mapping. */
+static void
+write_line_numbers ()
+{
+ struct pdb_func *func = funcs;
+ unsigned int lines_part = 0;
+
+ while (func)
+ {
+ while (func->lines)
+ {
+ struct pdb_line *l, *last_line;
+ unsigned int num_entries = 0, source_file, first_entry;
+
+ source_file = func->lines->source_file;
+
+ l = last_line = func->lines;
+ while (l && l->source_file == source_file)
+ {
+ num_entries++;
+ last_line = l;
+ l = l->next;
+ }
+
+ first_entry = func->lines->entry;
+
+ fprintf (asm_out_file, "\t.long\t0x%x\n", DEBUG_S_LINES);
+ fprintf (asm_out_file, "\t.long\t[.Llinesend%u]-[.Llinesstart%u]\n",
+ lines_part, lines_part);
+ fprintf (asm_out_file, ".Llinesstart%u:\n", lines_part);
+
+ // offset
+ fprintf (asm_out_file, "\t.secrel32\t.Lline%u\n", first_entry);
+ // section
+ fprintf (asm_out_file, "\t.secidx\t.Lline%u\n", first_entry);
+
+ fprintf (asm_out_file, "\t.short\t0\n"); // flags
+
+ // next section of function is another source file
+ if (last_line->next)
+ {
+ fprintf (asm_out_file, "\t.long\t[.Lline%u]-[.Lline%u]\n",
+ last_line->next->entry, first_entry); // length
+ }
+ else
+ {
+ fprintf (asm_out_file,
+ "\t.long\t[" FUNC_END_LABEL "%u]-[.Lline%u]\n",
+ func->num, first_entry); // length
+ }
+
+ // file ID (0x18 is size of checksum struct)
+ fprintf (asm_out_file, "\t.long\t0x%x\n", source_file * 0x18);
+ fprintf (asm_out_file, "\t.long\t0x%x\n", num_entries);
+ // length of file block
+ fprintf (asm_out_file, "\t.long\t0x%x\n", 0xc + (num_entries * 8));
+
+ while (func->lines && func->lines->source_file == source_file)
+ {
+ struct pdb_line *n = func->lines->next;
+
+ // offset
+ fprintf (asm_out_file, "\t.long\t[.Lline%u]-[.Lline%u]\n",
+ func->lines->entry, first_entry);
+
+ // line no.
+ fprintf (asm_out_file, "\t.long\t0x%x\n", func->lines->line);
+
+ free (func->lines);
+
+ func->lines = n;
+ }
+
+ fprintf (asm_out_file, ".Llinesend%u:\n", lines_part);
+ lines_part++;
+ }
+
+ func = func->next;
+ }
+}
+
/* Output the .debug$S section, which has everything except the
* type definitions (global variables, functions, string table,
* file checksums, line numbers).
@@ -688,6 +776,8 @@ write_pdb_section (void)
write_file_checksums ();
+ write_line_numbers ();
+
while (funcs)
{
struct pdb_func *n = funcs->next;
@@ -728,6 +818,7 @@ get_tree_name (tree t)
static void
pdbout_begin_function (tree func)
{
+ expanded_location xloc;
struct pdb_func *f = (struct pdb_func *) xmalloc (sizeof (struct pdb_func));
f->next = funcs;
@@ -735,6 +826,7 @@ pdbout_begin_function (tree func)
f->num = current_function_funcdef_no;
f->public_flag = TREE_PUBLIC (func);
f->type = find_type (TREE_TYPE (func));
+ f->lines = f->last_line = NULL;
f->local_vars = f->last_local_var = NULL;
f->var_locs = f->last_var_loc = NULL;
@@ -747,6 +839,11 @@ pdbout_begin_function (tree func)
cur_func = f;
cur_block = &f->block;
+
+ xloc = expand_location (DECL_SOURCE_LOCATION (func));
+
+ if (xloc.line != 0)
+ pdbout_source_line (xloc.line, 0, xloc.file, 0, 0);
}
/* We've been passed a late global declaration, i.e. a global variable -
@@ -1184,6 +1281,57 @@ pdbout_init (const char *file)
add_source_file (file);
}
+/* We've encountered a new line of source code. Add an asm label for this,
+ * and record the mapping for later. */
+static void
+pdbout_source_line (unsigned int line, unsigned int column ATTRIBUTE_UNUSED,
+ const char *text,
+ int discriminator ATTRIBUTE_UNUSED,
+ bool is_stmt ATTRIBUTE_UNUSED)
+{
+ struct pdb_line *ent;
+ struct pdb_source_file *psf;
+ unsigned int source_file = 0;
+
+ if (!cur_func)
+ return;
+
+ psf = source_files;
+ while (psf)
+ {
+ if (!strcmp (text, psf->name))
+ {
+ source_file = psf->num;
+ break;
+ }
+
+ psf = psf->next;
+ }
+
+ if (cur_func->last_line && cur_func->last_line->line == line
+ && cur_func->last_line->source_file == source_file)
+ return;
+
+ ent = (struct pdb_line *) xmalloc (sizeof (struct pdb_line));
+
+ ent->next = NULL;
+ ent->line = line;
+ ent->entry = num_line_number_entries;
+ ent->source_file = source_file;
+
+ if (cur_func->last_line)
+ cur_func->last_line->next = ent;
+
+ cur_func->last_line = ent;
+
+ if (!cur_func->lines)
+ cur_func->lines = ent;
+
+ fprintf (asm_out_file, ".Lline%u:\n", num_line_number_entries);
+
+ num_line_number_entries++;
+}
+
/* Given an x86 gcc register no., return the CodeView equivalent. */
static enum pdb_x86_register
map_register_no_x86 (unsigned int regno, machine_mode mode)
diff --git a/gcc/pdbout.h b/gcc/pdbout.h
index bd0a29635e7..8a6fef3c256 100644
--- a/gcc/pdbout.h
+++ b/gcc/pdbout.h
@@ -37,6 +37,7 @@
#define CV_SIGNATURE_C13 4
#define DEBUG_S_SYMBOLS 0xf1
+#define DEBUG_S_LINES 0xf2
#define DEBUG_S_STRINGTABLE 0xf3
#define DEBUG_S_FILECHKSMS 0xf4
@@ -45,6 +46,14 @@
#define CHKSUM_TYPE_SHA1 2
#define CHKSUM_TYPE_SHA_256 3
+struct pdb_line
+{
+ struct pdb_line *next;
+ unsigned int line;
+ unsigned int entry;
+ unsigned int source_file;
+};
+
enum pdb_local_var_type
{
pdb_local_var_unknown,
@@ -98,6 +107,7 @@ struct pdb_func
int num;
unsigned int public_flag;
struct pdb_type *type;
+ struct pdb_line *lines, *last_line;
struct pdb_local_var *local_vars, *last_local_var;
struct pdb_var_location *var_locs, *last_var_loc;
struct pdb_block block;
--
2.26.2
More information about the Gcc-patches
mailing list