]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
Add line debug info for virtual thunks
authorBernd Edlinger <bernd.edlinger@hotmail.de>
Tue, 12 Jan 2021 15:27:53 +0000 (16:27 +0100)
committerBernd Edlinger <bernd.edlinger@hotmail.de>
Thu, 6 May 2021 14:37:58 +0000 (16:37 +0200)
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.

gcc/dbxout.c
gcc/debug.c
gcc/debug.h
gcc/dwarf2out.c
gcc/dwarf2out.h
gcc/final.c
gcc/ggc-page.c
gcc/stringpool.c
gcc/vmsdbgout.c

index 70b635c3488a93b026b2ce0371b56f8be49cab3d..d20527b2c19307b493cac6dce79db5f008a106af 100644 (file)
@@ -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 */
index 0a7fcfa80cf3bebd82469dea82a3368caa9450c5..39add0d0b3909304fbb8e43fcd6fce3d0ca0399b 100644 (file)
@@ -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 */
index cd265ffbc99b548f824a53211078d8fc511d0014..ad45ea5374bf4956a7a87dec97fc25d970339f95 100644 (file)
@@ -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,
index 5b819ab1a923b0045f23de28376e52bd962749c1..871362b5d0c7ae2e14a4c6986cf2f51fb81c8369 100644 (file)
@@ -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;
index 76a9c0a39a298eff4fd0150eb24eb83735524e23..54b6343704c72fdfad83665ea007354b730b3f93 100644 (file)
@@ -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;
 };
 
 
index ba4285ddf14dc922cabe10fc82e4778d3fe32dce..e0a70fcd830b9c40f341a9e85ae3f6196ea64707 100644 (file)
@@ -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,
index 4d11692e34cb509e65414c8a352ef59d71859b64..1b09f0da94ff33c37cad8839e28b834189d16040 100644 (file)
@@ -1517,6 +1517,12 @@ gt_ggc_mx (const char *& x)
   gt_ggc_m_S (x);
 }
 
+void
+gt_ggc_mx (char *& x)
+{
+  gt_ggc_m_S (x);
+}
+
 void
 gt_ggc_mx (unsigned char *& x)
 {
index e4d79b0dca096488ab5bad1f7c61ce7cef4fe26b..2f21466af245d282e6cc9d4a10e1b7495209f29b 100644 (file)
@@ -205,6 +205,12 @@ gt_pch_nx (const char *& x)
   gt_pch_n_S (x);
 }
 
+void
+gt_pch_nx (char *& x)
+{
+  gt_pch_n_S (x);
+}
+
 void
 gt_pch_nx (unsigned char *& x)
 {
index c226bc69c8559e49a5b32dc625e159f38300dc65..05fadce075e5573f50a45b492d4dde30cbaddb79 100644 (file)
@@ -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,