Check function is GC'ed
authorYao Qi <yao@codesourcery.com>
Mon, 4 Aug 2014 06:57:22 +0000 (14:57 +0800)
committerYao Qi <yao@codesourcery.com>
Fri, 19 Sep 2014 08:53:27 +0000 (16:53 +0800)
I see the following fail on arm-none-eabi target,

(gdb) b 24^M
Breakpoint 1 at 0x4: file
../../../../git/gdb/testsuite/gdb.base/break-on-linker-gcd-function.cc,
line 24.^M
(gdb) FAIL: gdb.base/break-on-linker-gcd-function.exp: b 24

Currently, we are using flag has_section_at_zero to determine whether
address zero in debug info means the corresponding code has been
GC'ed, like this:

case DW_LNE_set_address:
  address = read_address (abfd, line_ptr, cu, &bytes_read);

  if (address == 0 && !dwarf2_per_objfile->has_section_at_zero)
    {
      /* This line table is for a function which has been
 GCd by the linker.  Ignore it.  PR gdb/12528 */

However, this is incorrect on some bare metal targets, as .text
section is located at 0x0, so dwarf2_per_objfile->has_section_at_zero
is true.  If a function is GC'ed by linker, the address is zero.  GDB
thinks address zero is a function's address rather than this function
is GC'ed.

In this patch, we choose 'lowpc' got in read_file_scope to check
whether 'lowpc' is greater than zero.  If it isn't, address zero really
means the function is GC'ed.  In this patch, we pass 'lowpc' in
read_file_scope through handle_DW_AT_stmt_list and dwarf_decode_lines,
and to dwarf_decode_lines_1 finally.

This patch fixes the fail above. This patch also covers the path that
partial symbol isn't used, which is tested by starting gdb with
--readnow option.

It is regression tested on x86-linux with
target_board=dwarf4-gdb-index, and arm-none-eabi.  OK to apply?

gdb:

2014-09-19  Yao Qi  <yao@codesourcery.com>

* dwarf2read.c (dwarf_decode_lines): Update declaration.
(handle_DW_AT_stmt_list): Add argument 'lowpc'.  Update
comments.  Callers update.
(dwarf_decode_lines): Likewise.
(dwarf_decode_lines_1): Add argument 'lowpc'.  Update
comments.  Skip the line table if  'lowpc' is greater than
'address'.  Don't check
dwarf2_per_objfile->has_section_at_zero.

gdb/testsuite:

2014-09-19  Yao Qi  <yao@codesourcery.com>

* gdb.base/break-on-linker-gcd-function.exp: Move test into new
proc set_breakpoint_on_gcd_function.  Invoke
set_breakpoint_on_gcd_function.  Restart GDB with --readnow and
invoke set_breakpoint_on_gcd_function again.

gdb/ChangeLog
gdb/dwarf2read.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/break-on-linker-gcd-function.exp

index 3fbc13ec200984658e074c7a2064849a4f6db941..37577080dd8d860136012332fc68b8ae5fd5ff1f 100644 (file)
@@ -1,3 +1,14 @@
+2014-09-19  Yao Qi  <yao@codesourcery.com>
+
+       * dwarf2read.c (dwarf_decode_lines): Update declaration.
+       (handle_DW_AT_stmt_list): Add argument 'lowpc'.  Update
+       comments.  Callers update.
+       (dwarf_decode_lines): Likewise.
+       (dwarf_decode_lines_1): Add argument 'lowpc'.  Update
+       comments.  Skip the line table if  'lowpc' is greater than
+       'address'.  Don't check
+       dwarf2_per_objfile->has_section_at_zero.
+
 2014-09-18  Doug Evans  <dje@google.com>
 
        * NEWS: Mention new "producer" attribute of gdb.Symtab.
index be32309803790930adb44c9afe115e938d093c3d..9d0ee13d465192782551b4666c07eca320f0a617 100644 (file)
@@ -1512,7 +1512,8 @@ static struct line_header *dwarf_decode_line_header (unsigned int offset,
                                                     struct dwarf2_cu *cu);
 
 static void dwarf_decode_lines (struct line_header *, const char *,
-                               struct dwarf2_cu *, struct partial_symtab *);
+                               struct dwarf2_cu *, struct partial_symtab *,
+                               CORE_ADDR);
 
 static void dwarf2_start_subfile (const char *, const char *, const char *);
 
@@ -4448,7 +4449,7 @@ dwarf2_build_include_psymtabs (struct dwarf2_cu *cu,
     return;  /* No linetable, so no includes.  */
 
   /* NOTE: pst->dirname is DW_AT_comp_dir (if present).  */
-  dwarf_decode_lines (lh, pst->dirname, cu, pst);
+  dwarf_decode_lines (lh, pst->dirname, cu, pst, pst->textlow);
 
   free_line_header (lh);
 }
@@ -8967,11 +8968,12 @@ find_file_and_directory (struct die_info *die, struct dwarf2_cu *cu,
 
 /* Handle DW_AT_stmt_list for a compilation unit.
    DIE is the DW_TAG_compile_unit die for CU.
-   COMP_DIR is the compilation directory.  */
+   COMP_DIR is the compilation directory.  LOWPC is passed to
+   dwarf_decode_lines.  See dwarf_decode_lines comments about it.  */
 
 static void
 handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
-                       const char *comp_dir) /* ARI: editCase function */
+                       const char *comp_dir, CORE_ADDR lowpc) /* ARI: editCase function */
 {
   struct attribute *attr;
 
@@ -8988,7 +8990,7 @@ handle_DW_AT_stmt_list (struct die_info *die, struct dwarf2_cu *cu,
        {
          cu->line_header = line_header;
          make_cleanup (free_cu_line_header, cu);
-         dwarf_decode_lines (line_header, comp_dir, cu, NULL);
+         dwarf_decode_lines (line_header, comp_dir, cu, NULL, lowpc);
        }
     }
 }
@@ -9039,7 +9041,7 @@ read_file_scope (struct die_info *die, struct dwarf2_cu *cu)
   /* Decode line number information if present.  We do this before
      processing child DIEs, so that the line header table is available
      for DW_AT_decl_file.  */
-  handle_DW_AT_stmt_list (die, cu, comp_dir);
+  handle_DW_AT_stmt_list (die, cu, comp_dir, lowpc);
 
   /* Process all dies in compilation unit.  */
   if (die->child != NULL)
@@ -17252,7 +17254,8 @@ dwarf_finish_line (struct gdbarch *gdbarch, struct subfile *subfile,
 
 static void
 dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
-                     struct dwarf2_cu *cu, const int decode_for_pst_p)
+                     struct dwarf2_cu *cu, const int decode_for_pst_p,
+                     CORE_ADDR lowpc)
 {
   const gdb_byte *line_ptr, *extended_end;
   const gdb_byte *line_end;
@@ -17375,7 +17378,12 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
                case DW_LNE_set_address:
                  address = read_address (abfd, line_ptr, cu, &bytes_read);
 
-                 if (address == 0 && !dwarf2_per_objfile->has_section_at_zero)
+                 /* If address < lowpc then it's not a usable value, it's
+                    outside the pc range of the CU.  However, we restrict
+                    the test to only address values of zero to preserve
+                    GDB's previous behaviour which is to handle the specific
+                    case of a function being GC'd by the linker.  */
+                 if (address == 0 && address < lowpc)
                    {
                      /* This line table is for a function which has been
                         GCd by the linker.  Ignore it.  PR gdb/12528 */
@@ -17595,17 +17603,20 @@ dwarf_decode_lines_1 (struct line_header *lh, const char *comp_dir,
    as the corresponding symtab.  Since COMP_DIR is not used in the name of the
    symtab we don't use it in the name of the psymtabs we create.
    E.g. expand_line_sal requires this when finding psymtabs to expand.
-   A good testcase for this is mb-inline.exp.  */
+   A good testcase for this is mb-inline.exp.
+
+   LOWPC is the lowest address in CU (or 0 if not known).  */
 
 static void
 dwarf_decode_lines (struct line_header *lh, const char *comp_dir,
-                   struct dwarf2_cu *cu, struct partial_symtab *pst)
+                   struct dwarf2_cu *cu, struct partial_symtab *pst,
+                   CORE_ADDR lowpc)
 {
   struct objfile *objfile = cu->objfile;
   const int decode_for_pst_p = (pst != NULL);
   struct subfile *first_subfile = current_subfile;
 
-  dwarf_decode_lines_1 (lh, comp_dir, cu, decode_for_pst_p);
+  dwarf_decode_lines_1 (lh, comp_dir, cu, decode_for_pst_p, lowpc);
 
   if (decode_for_pst_p)
     {
index a4b03dc9f810e038b02ffb58aec449feb93c2fcb..c421904c75eb33bec7bbd93f57f966fea5293a04 100644 (file)
@@ -1,3 +1,10 @@
+2014-09-19  Yao Qi  <yao@codesourcery.com>
+
+       * gdb.base/break-on-linker-gcd-function.exp: Move test into new
+       proc set_breakpoint_on_gcd_function.  Invoke
+       set_breakpoint_on_gcd_function.  Restart GDB with --readnow and
+       invoke set_breakpoint_on_gcd_function again.
+
 2014-09-18  Doug Evans  <dje@google.com>
 
        * gdb.dwarf2/symtab-producer.exp: New file.
index e593b5107700ac2f175ee4ab4b9d79aacdb91eca..b8de1cdea143556422688537f4fd53932d06a494 100644 (file)
@@ -41,9 +41,23 @@ if {[build_executable_from_specs $testfile.exp $testfile \
 
 clean_restart $testfile
 
-# Single hex digit
-set xd {[0-9a-f]}
+proc set_breakpoint_on_gcd_function {} {
+    # Single hex digit
+    set xd {[0-9a-f]}
+
+    # This accepts e.g. "Breakpoint 1 at 0x40968a" (fixed GDB)
+    # but rejects e.g. "Breakpoint 1 at 0x4" (broken GDB).
+    gdb_test "b [gdb_get_line_number "gdb break here"]" \
+       "Breakpoint \[0-9\] at 0x${xd}${xd}+: .*"
+}
+
+set_breakpoint_on_gcd_function
 
-# This accepts e.g. "Breakpoint 1 at 0x40968a" (fixed GDB)
-# but rejects e.g. "Breakpoint 1 at 0x4" (broken GDB).
-gdb_test "b [gdb_get_line_number "gdb break here"]" "Breakpoint \[0-9\] at 0x${xd}${xd}+: .*"
+set saved_gdbflags $GDBFLAGS
+set GDBFLAGS "$GDBFLAGS --readnow"
+clean_restart ${testfile}
+set GDBFLAGS $saved_gdbflags
+
+with_test_prefix "readnow" {
+    set_breakpoint_on_gcd_function
+}