--- gcc/pdbout.c | 226 ++++++++++++++++++++++++++++++++++++++------------- gcc/pdbout.h | 2 + 2 files changed, 170 insertions(+), 58 deletions(-)
diff --git a/gcc/pdbout.c b/gcc/pdbout.c index 0f5315f7f07..b4528fb79e8 100644 --- a/gcc/pdbout.c +++ b/gcc/pdbout.c @@ -71,6 +71,7 @@ static void pdbout_begin_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum); static void pdbout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum); +static void pdbout_new_section (void); static struct pdb_type *find_type (tree t); static char *get_tree_name (tree t); @@ -145,7 +146,7 @@ const struct gcc_debug_hooks pdb_debug_hooks = { pdbout_var_location, debug_nothing_tree, /* inline_entry */ debug_nothing_tree, /* size_function */ - debug_nothing_void, /* switch_text_section */ + pdbout_new_section, debug_nothing_tree_tree, /* set_name */ 0, /* start_end_main_source_file */ TYPE_SYMTAB_IS_ADDRESS /* tree_type_symtab_field */ @@ -157,8 +158,8 @@ 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); + fprintf (asm_out_file, FUNC_BEGIN_LABEL "%s%u:\n", + in_cold_section_p ? "cold" : "", current_function_funcdef_no); } /* Add label after function end */ @@ -166,7 +167,8 @@ 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); + fprintf (asm_out_file, FUNC_END_LABEL "%s%u:\n", + in_cold_section_p ? "cold" : "", current_function_funcdef_no); } /* Output DEFRANGESYMREGISTER or DEFRANGESYMREGISTERREL structure, describing @@ -464,8 +466,8 @@ pdbout_block (struct pdb_block *block, struct pdb_func *func) } else { - fprintf (asm_out_file, "\t.long\t[.Lcvprocstart%u]-[.debug$S]\n", - func->num); + fprintf (asm_out_file, "\t.long\t[.Lcvprocstart%s%u]-[.debug$S]\n", + func->cold ? "cold" : "", func->num); } fprintf (asm_out_file, "\t.long\t[.Lcvblockend%u]-[.debug$S]\n", @@ -497,61 +499,72 @@ pdbout_block (struct pdb_block *block, struct pdb_func *func) 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 + /* Don't output function definition if it contains no lines. This can happen + * if the compiler creates a cold function consisting of just ud2. */ - if (len % 4 != 0) + if (func->lines) { - align = 4 - (len % 4); - len += 4 - (len % 4); - } - else - align = 0; + size_t name_len = func->name ? strlen (func->name) : 0; + uint16_t len = 40 + name_len, align; - 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 + // start procedure - fprintf (asm_out_file, "\t.byte\t0\n"); // flags + if (len % 4 != 0) + { + align = 4 - (len % 4); + len += 4 - (len % 4); + } + else + align = 0; - if (func->name) - ASM_OUTPUT_ASCII (asm_out_file, func->name, name_len + 1); - else - fprintf (asm_out_file, "\t.byte\t0\n"); + fprintf (asm_out_file, ".Lcvprocstart%s%u:\n", + func->cold ? "cold" : "", 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%s%u]-[.debug$S]\n", + func->cold ? "cold" : "", func->num); // pEnd + fprintf (asm_out_file, "\t.long\t0\n"); // pNext + fprintf (asm_out_file, + "\t.long\t[" FUNC_END_LABEL "%s%u]-[" FUNC_BEGIN_LABEL "%s%u]\n", + func->cold ? "cold" : "", func->num, + func->cold ? "cold" : "", 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 - for (unsigned int i = 0; i < align; i++) - { - fprintf (asm_out_file, "\t.byte\t0\n"); - } + fprintf (asm_out_file, "\t.secrel32\t" FUNC_BEGIN_LABEL "%s%u\n", + func->cold ? "cold" : "", func->num); // offset + fprintf (asm_out_file, "\t.secidx\t" FUNC_BEGIN_LABEL "%s%u\n", + func->cold ? "cold" : "", func->num); // section + + fprintf (asm_out_file, "\t.byte\t0\n"); // flags - pdbout_block (&func->block, func); + if (func->name) + ASM_OUTPUT_ASCII (asm_out_file, func->name, name_len + 1); + else + fprintf (asm_out_file, "\t.byte\t0\n"); - // end procedure + for (unsigned int i = 0; i < align; i++) + { + fprintf (asm_out_file, "\t.byte\t0\n"); + } - fprintf (asm_out_file, ".Lcvprocend%u:\n", func->num); + pdbout_block (&func->block, func); - fprintf (asm_out_file, "\t.short\t0x2\n"); - fprintf (asm_out_file, "\t.short\t0x%x\n", S_END); + // end procedure + + fprintf (asm_out_file, ".Lcvprocend%s%u:\n", + func->cold ? "cold" : "", func->num); + + fprintf (asm_out_file, "\t.short\t0x2\n"); + fprintf (asm_out_file, "\t.short\t0x%x\n", S_END); + } while (func->local_vars) { @@ -657,17 +670,32 @@ write_line_numbers () { struct pdb_line *l, *last_line; unsigned int num_entries = 0, source_file, first_entry; + section *sect; source_file = func->lines->source_file; + sect = func->lines->sect; l = last_line = func->lines; - while (l && l->source_file == source_file) + while (l && l->source_file == source_file && l->sect == sect) { num_entries++; last_line = l; l = l->next; } + /* If pdb_line has a NULL section, it's a sentinel at the end of + * the current section - skip it and move on. */ + if (!sect) + { + struct pdb_line *n = func->lines->next; + + free (func->lines); + + func->lines = n; + + continue; + } + first_entry = func->lines->entry; fprintf (asm_out_file, "\t.long\t0x%x\n", DEBUG_S_LINES); @@ -682,17 +710,19 @@ write_line_numbers () fprintf (asm_out_file, "\t.short\t0\n"); // flags - // next section of function is another source file + // next part of function is another source file or section if (last_line->next) { + // length fprintf (asm_out_file, "\t.long\t[.Lline%u]-[.Lline%u]\n", - last_line->next->entry, first_entry); // length + last_line->next->entry, first_entry); } else { + // length fprintf (asm_out_file, - "\t.long\t[" FUNC_END_LABEL "%u]-[.Lline%u]\n", - func->num, first_entry); // length + "\t.long\t[" FUNC_END_LABEL "%s%u]-[.Lline%u]\n", + func->cold ? "cold" : "", func->num, first_entry); } // file ID (0x18 is size of checksum struct) @@ -701,7 +731,7 @@ write_line_numbers () // 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) + while (func->lines && func->lines->source_file == source_file && func->lines->sect == sect) { struct pdb_line *n = func->lines->next; @@ -2406,6 +2436,7 @@ pdbout_begin_function (tree func) f->lines = f->last_line = NULL; f->local_vars = f->last_local_var = NULL; f->var_locs = f->last_var_loc = NULL; + f->cold = in_cold_section_p; f->block.next = NULL; f->block.parent = NULL; @@ -4247,6 +4278,7 @@ pdbout_source_line (unsigned int line, unsigned int column ATTRIBUTE_UNUSED, ent->line = line; ent->entry = num_line_number_entries; ent->source_file = source_file; + ent->sect = current_function_section (); if (cur_func->last_line) cur_func->last_line->next = ent; @@ -4254,7 +4286,13 @@ pdbout_source_line (unsigned int line, unsigned int column ATTRIBUTE_UNUSED, cur_func->last_line = ent; if (!cur_func->lines) - cur_func->lines = ent; + { + if (cur_func->cold) + fprintf (asm_out_file, FUNC_BEGIN_LABEL "cold%u:\n", + current_function_funcdef_no); + + cur_func->lines = ent; + } fprintf (asm_out_file, ".Lline%u:\n", num_line_number_entries); @@ -5148,6 +5186,9 @@ add_local (const char *name, tree t, struct pdb_type *type, rtx orig_rtl, size_t name_len = strlen (name); rtx rtl; + if (cur_func->cold) + return; + plv = (struct pdb_local_var *) xmalloc (offsetof (struct pdb_local_var, name) + name_len + 1); @@ -5286,7 +5327,7 @@ pdbout_var_location (rtx_insn * loc_note) tree var; struct pdb_var_location *var_loc; - if (!cur_func) + if (!cur_func || cur_func->cold) return; if (!NOTE_P (loc_note)) @@ -5400,3 +5441,72 @@ pdbout_end_block (unsigned int line ATTRIBUTE_UNUSED, unsigned int blocknum) cur_block = cur_block->parent; } + +/* We're switching sections mid-function - this happens when GCC moves part + * of a code path to .text.unlikely, such as an if block ending with abort(). + * Create a new function with ".cold" at the end to accommodate this. */ +static void +pdbout_new_section (void) +{ + struct pdb_line *ent; + struct pdb_func *f; + + static const char cold_suf[] = ".cold"; + + if (!cur_func) + return; + + // add line number for end of current section + + ent = (struct pdb_line *) xmalloc (sizeof (struct pdb_line)); + + ent->next = NULL; + ent->line = 0; + ent->entry = num_line_number_entries; + ent->source_file = 0; + ent->sect = NULL; + + 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++; + + // end current function + + fprintf (asm_out_file, FUNC_END_LABEL "%u:\n", current_function_funcdef_no); + + // start cold function + + f = (struct pdb_func *) xmalloc (sizeof (struct pdb_func)); + + f->next = funcs; + + f->name = (char *) xmalloc (strlen (cur_func->name) + sizeof (cold_suf)); + strcpy (f->name, cur_func->name); + strcat (f->name, cold_suf); + + f->num = current_function_funcdef_no; + f->public_flag = cur_func->public_flag; + f->type = cur_func->type; + f->lines = f->last_line = NULL; + f->local_vars = f->last_local_var = NULL; + f->var_locs = f->last_var_loc = NULL; + f->cold = in_cold_section_p; + + f->block.next = NULL; + f->block.parent = NULL; + f->block.num = 0; + f->block.children = f->block.last_child = NULL; + + funcs = f; + + cur_func = f; + cur_block = &f->block; +} diff --git a/gcc/pdbout.h b/gcc/pdbout.h index f1b21fe23a0..7fe0d3312e0 100644 --- a/gcc/pdbout.h +++ b/gcc/pdbout.h @@ -75,6 +75,7 @@ struct pdb_line unsigned int line; unsigned int entry; unsigned int source_file; + section *sect; }; enum pdb_local_var_type @@ -129,6 +130,7 @@ struct pdb_func char *name; int num; unsigned int public_flag; + bool cold; struct pdb_type *type; struct pdb_line *lines, *last_line; struct pdb_local_var *local_vars, *last_local_var; -- 2.26.2