diff options
author | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2021-01-12 16:27:53 +0100 |
---|---|---|
committer | Bernd Edlinger <bernd.edlinger@hotmail.de> | 2021-05-06 16:37:58 +0200 |
commit | e69ac0203725fb8da83a1cc88d32191b7a0b2c0c (patch) | |
tree | 26336b92515ae622b239818452a41a394fdbf2c9 /gcc | |
parent | 0f442f1378f4e9866793309504e38467f34c5d61 (diff) | |
download | gcc-e69ac0203725fb8da83a1cc88d32191b7a0b2c0c.zip gcc-e69ac0203725fb8da83a1cc88d32191b7a0b2c0c.tar.gz gcc-e69ac0203725fb8da83a1cc88d32191b7a0b2c0c.tar.bz2 |
Add line debug info for virtual thunks
There is no debug info when the DECL_IGNORED_P flag
is set. But sometimes we have the line info of the
function decl, as in the case of on virtual thunks.
So instead of no line info at all, we emit at least
the location of the function decl.
On the other side, there are DECL_IGNORED_P functions
which do not have any source line info at all.
Remove those from the debug_range info, to make it
clear for the debugger that the line info for these
functions is invalid. This has the effect that the
debugger will not step into the function without
debug info.
2021-05-06 Bernd Edlinger <bernd.edlinger@hotmail.de>
PR ipa/97937
* debug.h (gcc_debug_hooks): Add set_ignored_loc function pointer.
* dwarf2out.h (dw_fde_node::ignored_debug): New data item.
* dbxout.c (dbx_debug_hooks, xcoff_debug_hooks): Add dummy
set_ignored_loc callbacks.
* debug.c (do_nothing_debug_hooks): Likewise.
* vmsdbgout.c (vmsdbg_debug_hooks): Likewise.
* dwarf2out.c (text_section_used, cold_text_section_used): Remove.
(in_text_section_p, last_text_label, last_cold_label,
switch_text_ranges, switch_cold_ranges): New data items.
(dwarf2out_note_section_used): Remove.
(dwarf2out_begin_prologue): Set fde->ignored_debug and
in_text_section_p.
(mark_ignored_debug_section): New helper function.
(dwarf2out_end_epilogue, dwarf2out_switch_text_section): Call
mark_ignored_debug_section.
(dwarf2_debug_hooks): Use dwarf2out_set_ignored_loc.
(dwarf2_lineno_debug_hooks): Use dummy for set_ignored_loc.
(size_of_aranges): Adjust formula for multi-part text ranges size.
(output_aranges): Output multi-part text ranges.
(dwarf2out_set_ignored_loc): New callback function.
(dwarf2out_finish): Output multi-part text ranges.
(dwarf2out_c_finalize): Clear new data items.
* final.c (final_start_function_1): Call set_ignored_loc callback.
(final_scan_insn_1): Likewise.
* ggc-page.c (gt_ggc_mx): New helper function.
* stringpool.c (gt_pch_nx): Likewise.
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/dbxout.c | 2 | ||||
-rw-r--r-- | gcc/debug.c | 1 | ||||
-rw-r--r-- | gcc/debug.h | 4 | ||||
-rw-r--r-- | gcc/dwarf2out.c | 244 | ||||
-rw-r--r-- | gcc/dwarf2out.h | 2 | ||||
-rw-r--r-- | gcc/final.c | 8 | ||||
-rw-r--r-- | gcc/ggc-page.c | 6 | ||||
-rw-r--r-- | gcc/stringpool.c | 6 | ||||
-rw-r--r-- | gcc/vmsdbgout.c | 1 |
9 files changed, 224 insertions, 50 deletions
diff --git a/gcc/dbxout.c b/gcc/dbxout.c index 70b635c..d20527b 100644 --- a/gcc/dbxout.c +++ b/gcc/dbxout.c @@ -362,6 +362,7 @@ const struct gcc_debug_hooks dbx_debug_hooks = dbxout_end_block, debug_true_const_tree, /* ignore_block */ dbxout_source_line, /* source_line */ + debug_nothing_int_int_charstar, /* set_ignored_loc */ dbxout_begin_prologue, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ debug_nothing_int_charstar, /* begin_epilogue */ @@ -409,6 +410,7 @@ const struct gcc_debug_hooks xcoff_debug_hooks = xcoffout_end_block, debug_true_const_tree, /* ignore_block */ xcoffout_source_line, + debug_nothing_int_int_charstar, /* set_ignored_loc */ xcoffout_begin_prologue, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ debug_nothing_int_charstar, /* begin_epilogue */ diff --git a/gcc/debug.c b/gcc/debug.c index 0a7fcfa..39add0d 100644 --- a/gcc/debug.c +++ b/gcc/debug.c @@ -36,6 +36,7 @@ const struct gcc_debug_hooks do_nothing_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, /* set_ignored_loc */ debug_nothing_int_int_charstar, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ debug_nothing_int_charstar, /* begin_epilogue */ diff --git a/gcc/debug.h b/gcc/debug.h index cd265ff..ad45ea53 100644 --- a/gcc/debug.h +++ b/gcc/debug.h @@ -73,6 +73,10 @@ struct gcc_debug_hooks void (* source_line) (unsigned int line, unsigned int column, const char *file, int discriminator, bool is_stmt); + /* Record a source file location for a DECL_IGNORED_P function. */ + void (* set_ignored_loc) (unsigned int line, unsigned int column, + const char *file); + /* Called at start of prologue code. LINE is the first line in the function. */ void (* begin_prologue) (unsigned int line, unsigned int column, diff --git a/gcc/dwarf2out.c b/gcc/dwarf2out.c index 5b819ab..871362b 100644 --- a/gcc/dwarf2out.c +++ b/gcc/dwarf2out.c @@ -259,13 +259,21 @@ static GTY(()) int dw2_string_counter; /* True if the compilation unit places functions in more than one section. */ static GTY(()) bool have_multiple_function_sections = false; -/* Whether the default text and cold text sections have been used at all. */ -static GTY(()) bool text_section_used = false; -static GTY(()) bool cold_text_section_used = false; - /* The default cold text section. */ static GTY(()) section *cold_text_section; +/* True if currently in text section. */ +static GTY(()) bool in_text_section_p = false; + +/* Last debug-on location in corresponding section. */ +static GTY(()) const char *last_text_label; +static GTY(()) const char *last_cold_label; + +/* Mark debug-on/off locations per section. + NULL means the section is not used at all. */ +static GTY(()) vec<const char *, va_gc> *switch_text_ranges; +static GTY(()) vec<const char *, va_gc> *switch_cold_ranges; + /* The DIE for C++14 'auto' in a function return type. */ static GTY(()) dw_die_ref auto_die; @@ -275,7 +283,6 @@ static GTY(()) dw_die_ref decltype_auto_die; /* Forward declarations for functions defined in this file. */ static void output_call_frame_info (int); -static void dwarf2out_note_section_used (void); /* Personality decl of current unit. Used only when assembler does not support personality CFI. */ @@ -1107,6 +1114,8 @@ dwarf2out_begin_prologue (unsigned int line ATTRIBUTE_UNUSED, fde->dw_fde_current_label = dup_label; fde->in_std_section = (fnsec == text_section || (cold_text_section && fnsec == cold_text_section)); + fde->ignored_debug = DECL_IGNORED_P (current_function_decl); + in_text_section_p = fnsec == text_section; /* We only want to output line number information for the genuine dwarf2 prologue case, not the eh frame case. */ @@ -1174,6 +1183,59 @@ dwarf2out_vms_begin_epilogue (unsigned int line ATTRIBUTE_UNUSED, fde->dw_fde_vms_begin_epilogue = xstrdup (label); } +/* Mark the ranges of non-debug subsections in the std text sections. */ + +static void +mark_ignored_debug_section (dw_fde_ref fde, bool second) +{ + bool std_section; + const char *begin_label, *end_label; + const char **last_end_label; + vec<const char *, va_gc> **switch_ranges; + + if (second) + { + std_section = fde->second_in_std_section; + begin_label = fde->dw_fde_second_begin; + end_label = fde->dw_fde_second_end; + } + else + { + std_section = fde->in_std_section; + begin_label = fde->dw_fde_begin; + end_label = fde->dw_fde_end; + } + + if (!std_section) + return; + + if (in_text_section_p) + { + last_end_label = &last_text_label; + switch_ranges = &switch_text_ranges; + } + else + { + last_end_label = &last_cold_label; + switch_ranges = &switch_cold_ranges; + } + + if (fde->ignored_debug) + { + if (*switch_ranges && !(vec_safe_length (*switch_ranges) & 1)) + vec_safe_push (*switch_ranges, *last_end_label); + } + else + { + *last_end_label = end_label; + + if (!*switch_ranges) + vec_alloc (*switch_ranges, 16); + else if (vec_safe_length (*switch_ranges) & 1) + vec_safe_push (*switch_ranges, begin_label); + } +} + /* Output a marker (i.e. a label) for the absolute end of the generated code for a function definition. This gets called *after* the epilogue code has been generated. */ @@ -1200,6 +1262,8 @@ dwarf2out_end_epilogue (unsigned int line ATTRIBUTE_UNUSED, gcc_assert (fde != NULL); if (fde->dw_fde_second_begin == NULL) fde->dw_fde_end = xstrdup (label); + + mark_ignored_debug_section (fde, fde->dw_fde_second_begin != NULL); } void @@ -1214,18 +1278,6 @@ dwarf2out_frame_finish (void) output_call_frame_info (1); } -/* Note that the current function section is being used for code. */ - -static void -dwarf2out_note_section_used (void) -{ - section *sec = current_function_section (); - if (sec == text_section) - text_section_used = true; - else if (sec == cold_text_section) - cold_text_section_used = true; -} - static void var_location_switch_text_section (void); static void set_cur_line_info_table (section *); @@ -1254,13 +1306,11 @@ dwarf2out_switch_text_section (void) } have_multiple_function_sections = true; - /* There is no need to mark used sections when not debugging. */ - if (cold_text_section != NULL) - dwarf2out_note_section_used (); - if (dwarf2out_do_cfi_asm ()) fprintf (asm_out_file, "\t.cfi_endproc\n"); + mark_ignored_debug_section (fde, false); + /* Now do the real section switch. */ sect = current_function_section (); switch_to_section (sect); @@ -1268,6 +1318,7 @@ dwarf2out_switch_text_section (void) fde->second_in_std_section = (sect == text_section || (cold_text_section && sect == cold_text_section)); + in_text_section_p = sect == text_section; if (dwarf2out_do_cfi_asm ()) dwarf2out_do_cfi_startproc (true); @@ -2801,6 +2852,7 @@ static void dwarf2out_function_decl (tree); static void dwarf2out_begin_block (unsigned, unsigned); static void dwarf2out_end_block (unsigned, unsigned); static bool dwarf2out_ignore_block (const_tree); +static void dwarf2out_set_ignored_loc (unsigned, unsigned, const char *); static void dwarf2out_early_global_decl (tree); static void dwarf2out_late_global_decl (tree); static void dwarf2out_type_decl (tree, int); @@ -2836,6 +2888,7 @@ const struct gcc_debug_hooks dwarf2_debug_hooks = dwarf2out_end_block, dwarf2out_ignore_block, dwarf2out_source_line, + dwarf2out_set_ignored_loc, dwarf2out_begin_prologue, #if VMS_DEBUGGING_INFO dwarf2out_vms_end_prologue, @@ -2885,6 +2938,7 @@ const struct gcc_debug_hooks dwarf2_lineno_debug_hooks = debug_nothing_int_int, /* end_block */ debug_true_const_tree, /* ignore_block */ dwarf2out_source_line, /* source_line */ + debug_nothing_int_int_charstar, /* set_ignored_loc */ debug_nothing_int_int_charstar, /* begin_prologue */ debug_nothing_int_charstar, /* end_prologue */ debug_nothing_int_charstar, /* begin_epilogue */ @@ -9756,10 +9810,12 @@ size_of_aranges (void) size = DWARF_ARANGES_HEADER_SIZE; /* Count the address/length pair for this compilation unit. */ - if (text_section_used) - size += 2 * DWARF2_ADDR_SIZE; - if (cold_text_section_used) - size += 2 * DWARF2_ADDR_SIZE; + if (switch_text_ranges) + size += 2 * DWARF2_ADDR_SIZE + * (vec_safe_length (switch_text_ranges) / 2 + 1); + if (switch_cold_ranges) + size += 2 * DWARF2_ADDR_SIZE + * (vec_safe_length (switch_cold_ranges) / 2 + 1); if (have_multiple_function_sections) { unsigned fde_idx; @@ -9767,7 +9823,7 @@ size_of_aranges (void) FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { - if (DECL_IGNORED_P (fde->decl)) + if (fde->ignored_debug) continue; if (!fde->in_std_section) size += 2 * DWARF2_ADDR_SIZE; @@ -11713,18 +11769,52 @@ output_aranges (void) the address may end up as 0 if the section is discarded by ld --gc-sections, leaving an invalid (0, 0) entry that can be confused with the terminator. */ - if (text_section_used) + if (switch_text_ranges) { - dw2_asm_output_addr (DWARF2_ADDR_SIZE, text_section_label, "Address"); - dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, - text_section_label, "Length"); + const char *prev_loc = text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_text_ranges, idx, loc) + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, loc, prev_loc, "Length"); + prev_loc = NULL; + } + else + prev_loc = loc; + + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, text_end_label, + prev_loc, "Length"); + } } - if (cold_text_section_used) + + if (switch_cold_ranges) { - dw2_asm_output_addr (DWARF2_ADDR_SIZE, cold_text_section_label, - "Address"); - dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label, - cold_text_section_label, "Length"); + const char *prev_loc = cold_text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_cold_ranges, idx, loc) + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, loc, prev_loc, "Length"); + prev_loc = NULL; + } + else + prev_loc = loc; + + if (prev_loc) + { + dw2_asm_output_addr (DWARF2_ADDR_SIZE, prev_loc, "Address"); + dw2_asm_output_delta (DWARF2_ADDR_SIZE, cold_end_label, + prev_loc, "Length"); + } } if (have_multiple_function_sections) @@ -11734,7 +11824,7 @@ output_aranges (void) FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { - if (DECL_IGNORED_P (fde->decl)) + if (fde->ignored_debug) continue; if (!fde->in_std_section) { @@ -28020,7 +28110,6 @@ dwarf2out_begin_function (tree fun) switch_to_section (sec); } - dwarf2out_note_section_used (); call_site_count = 0; tail_call_site_count = 0; @@ -28323,6 +28412,20 @@ dwarf2out_source_line (unsigned int line, unsigned int column, table->in_use = true; } +/* Record a source file location for a DECL_IGNORED_P function. */ + +static void +dwarf2out_set_ignored_loc (unsigned int line, unsigned int column, + const char *filename) +{ + dw_fde_ref fde = cfun->fde; + + fde->ignored_debug = false; + set_cur_line_info_table (function_section (fde->decl)); + + dwarf2out_source_line (line, column, filename, 0, true); +} + /* Record the beginning of a new source file. */ static void @@ -31760,30 +31863,68 @@ dwarf2out_finish (const char *filename) /* We can only use the low/high_pc attributes if all of the code was in .text. */ - if (!have_multiple_function_sections + if ((!have_multiple_function_sections + && vec_safe_length (switch_text_ranges) < 2) || (dwarf_version < 3 && dwarf_strict)) { + const char *end_label = text_end_label; + if (vec_safe_length (switch_text_ranges) == 1) + end_label = (*switch_text_ranges)[0]; /* Don't add if the CU has no associated code. */ - if (text_section_used) - add_AT_low_high_pc (main_comp_unit_die, text_section_label, - text_end_label, true); + if (switch_text_ranges) + add_AT_low_high_pc (main_comp_unit_die, text_section_label, + end_label, true); } else { unsigned fde_idx; dw_fde_ref fde; bool range_list_added = false; + if (switch_text_ranges) + { + const char *prev_loc = text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_text_ranges, idx, loc) + if (prev_loc) + { + add_ranges_by_labels (main_comp_unit_die, prev_loc, + loc, &range_list_added, true); + prev_loc = NULL; + } + else + prev_loc = loc; - if (text_section_used) - add_ranges_by_labels (main_comp_unit_die, text_section_label, - text_end_label, &range_list_added, true); - if (cold_text_section_used) - add_ranges_by_labels (main_comp_unit_die, cold_text_section_label, - cold_end_label, &range_list_added, true); + if (prev_loc) + add_ranges_by_labels (main_comp_unit_die, prev_loc, + text_end_label, &range_list_added, true); + } + + if (switch_cold_ranges) + { + const char *prev_loc = cold_text_section_label; + const char *loc; + unsigned idx; + + FOR_EACH_VEC_ELT (*switch_cold_ranges, idx, loc) + if (prev_loc) + { + add_ranges_by_labels (main_comp_unit_die, prev_loc, + loc, &range_list_added, true); + prev_loc = NULL; + } + else + prev_loc = loc; + + if (prev_loc) + add_ranges_by_labels (main_comp_unit_die, prev_loc, + cold_end_label, &range_list_added, true); + } FOR_EACH_VEC_ELT (*fde_vec, fde_idx, fde) { - if (DECL_IGNORED_P (fde->decl)) + if (fde->ignored_debug) continue; if (!fde->in_std_section) add_ranges_by_labels (main_comp_unit_die, fde->dw_fde_begin, @@ -32657,9 +32798,12 @@ dwarf2out_c_finalize (void) skeleton_debug_str_hash = NULL; dw2_string_counter = 0; have_multiple_function_sections = false; - text_section_used = false; - cold_text_section_used = false; + in_text_section_p = false; cold_text_section = NULL; + last_text_label = NULL; + last_cold_label = NULL; + switch_text_ranges = NULL; + switch_cold_ranges = NULL; current_unit_personality = NULL; early_dwarf = false; diff --git a/gcc/dwarf2out.h b/gcc/dwarf2out.h index 76a9c0a..54b6343 100644 --- a/gcc/dwarf2out.h +++ b/gcc/dwarf2out.h @@ -114,6 +114,8 @@ struct GTY(()) dw_fde_node { hard frame pointer register should be emitted only on the latter instruction. */ unsigned rule18 : 1; + /* True if this function is to be ignored by debugger. */ + unsigned ignored_debug : 1; }; diff --git a/gcc/final.c b/gcc/final.c index ba4285d..e0a70fc 100644 --- a/gcc/final.c +++ b/gcc/final.c @@ -1724,6 +1724,9 @@ final_start_function_1 (rtx_insn **firstp, FILE *file, int *seen, if (!dwarf2_debug_info_emitted_p (current_function_decl)) dwarf2out_begin_prologue (0, 0, NULL); + if (DECL_IGNORED_P (current_function_decl) && last_linenum && last_filename) + debug_hooks->set_ignored_loc (last_linenum, last_columnnum, last_filename); + #ifdef LEAF_REG_REMAP if (crtl->uses_only_leaf_regs) leaf_renumber_regs (first); @@ -2187,6 +2190,7 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, in_cold_section_p = !in_cold_section_p; + gcc_checking_assert (in_cold_section_p); if (in_cold_section_p) cold_function_name = clone_function_name (current_function_decl, "cold"); @@ -2200,6 +2204,10 @@ final_scan_insn_1 (rtx_insn *insn, FILE *file, int optimize_p ATTRIBUTE_UNUSED, } else if (!DECL_IGNORED_P (current_function_decl)) debug_hooks->switch_text_section (); + if (DECL_IGNORED_P (current_function_decl) && last_linenum + && last_filename) + debug_hooks->set_ignored_loc (last_linenum, last_columnnum, + last_filename); switch_to_section (current_function_section ()); targetm.asm_out.function_switched_text_sections (asm_out_file, diff --git a/gcc/ggc-page.c b/gcc/ggc-page.c index 4d11692..1b09f0d 100644 --- a/gcc/ggc-page.c +++ b/gcc/ggc-page.c @@ -1518,6 +1518,12 @@ gt_ggc_mx (const char *& x) } void +gt_ggc_mx (char *& x) +{ + gt_ggc_m_S (x); +} + +void gt_ggc_mx (unsigned char *& x) { gt_ggc_m_S (x); diff --git a/gcc/stringpool.c b/gcc/stringpool.c index e4d79b0..2f21466 100644 --- a/gcc/stringpool.c +++ b/gcc/stringpool.c @@ -206,6 +206,12 @@ gt_pch_nx (const char *& x) } void +gt_pch_nx (char *& x) +{ + gt_pch_n_S (x); +} + +void gt_pch_nx (unsigned char *& x) { gt_pch_n_S (x); diff --git a/gcc/vmsdbgout.c b/gcc/vmsdbgout.c index c226bc6..05fadce 100644 --- a/gcc/vmsdbgout.c +++ b/gcc/vmsdbgout.c @@ -188,6 +188,7 @@ const struct gcc_debug_hooks vmsdbg_debug_hooks vmsdbgout_end_block, vmsdbgout_ignore_block, vmsdbgout_source_line, + debug_nothing_int_int_charstar, /* set_ignored_loc */ vmsdbgout_begin_prologue, vmsdbgout_end_prologue, vmsdbgout_begin_epilogue, |