This is the mail archive of the gdb-cvs@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

[binutils-gdb/gdb-7.12-branch] Fix PR gdb/20505 - Make vDSO detection work with core files


https://sourceware.org/git/gitweb.cgi?p=binutils-gdb.git;h=601a2a8f639f9ef6dab86118a87fa67861f2091e

commit 601a2a8f639f9ef6dab86118a87fa67861f2091e
Author: Pedro Alves <palves@redhat.com>
Date:   Mon Aug 22 20:22:35 2016 +0100

    Fix PR gdb/20505 - Make vDSO detection work with core files
    
    Loading a core dump that was either generated on a system running
    pristine glibc master, or on a Fedora/RHEL system with LD_DEBUG=unused
    set in the environment, solib-svr4.c:svr4_current_sos fails to filter
    out the vDSO, resulting in:
    
      (gdb) core-file corefile.core^M
      [New LWP 2362]^M
      warning: Could not load shared library symbols for linux-vdso.so.1.^M
      Do you need "set solib-search-path" or "set sysroot"?^M
      Core was generated by `build-gdb/gdb/testsuite/outputs/gdb.base/corefile/'.^M
      ...
    
    The problem is that gdbarch_vsyscall_range does not support core
    inferiors at all.
    
    When live debugging, we're finding the vDSO's start address with
    auxv/AT_SYSINFO_EHDR, and then we find the vDSO's size by look for the
    corresponding mapping, by parsing /proc/PID/maps.  When debugging a
    core dump, we can also determine the starting address from
    auxv/AT_SYSINFO_EHDR.  However, we obviously can't read the core
    mappings out of the host's /proc.  But we can instead look for a
    corresponding load segment in the core's bfd.
    
    gdb/ChangeLog:
    2016-08-22  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/20505
    	* linux-tdep.c (linux_vsyscall_range_raw): For core inferiors,
    	find the vDSO's start address with AT_SYSINFO_EHDR too, and
    	determine the vDSO's size by finding the PT_LOAD segment that
    	matches AT_SYSINFO_EHDR.
    
    gdb/testsuite/ChangeLog:
    2016-08-22  Pedro Alves  <palves@redhat.com>
    
    	PR gdb/20505
    	* gdb.base/vdso-warning.exp: Test core dumps too.  Use
    	with_test_prefix.  Factor out bits to ...
    	(test_no_vdso): ... this new procedure.

Diff:
---
 gdb/ChangeLog                           |  8 ++++
 gdb/linux-tdep.c                        | 35 ++++++++++++---
 gdb/testsuite/ChangeLog                 |  7 +++
 gdb/testsuite/gdb.base/vdso-warning.exp | 76 ++++++++++++++++++++++-----------
 4 files changed, 97 insertions(+), 29 deletions(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index a0dcf42..9a3174a 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,11 @@
+2016-08-22  Pedro Alves  <palves@redhat.com>
+
+	PR gdb/20505
+	* linux-tdep.c (linux_vsyscall_range_raw): For core inferiors,
+	find the vDSO's start address with AT_SYSINFO_EHDR too, and
+	determine the vDSO's size by finding the PT_LOAD segment that
+	matches AT_SYSINFO_EHDR.
+
 2016-08-19  Yao Qi  <yao.qi@linaro.org>
 
 	* aarch64-tdep.c (aarch64_analyze_prologue): Handle register
diff --git a/gdb/linux-tdep.c b/gdb/linux-tdep.c
index ab110b0..718dc1a 100644
--- a/gdb/linux-tdep.c
+++ b/gdb/linux-tdep.c
@@ -2287,17 +2287,42 @@ linux_vsyscall_range_raw (struct gdbarch *gdbarch, struct mem_range *range)
   long pid;
   char *data;
 
-  /* Can't access /proc if debugging a core file.  */
-  if (!target_has_execution)
+  if (target_auxv_search (&current_target, AT_SYSINFO_EHDR, &range->start) <= 0)
     return 0;
 
+  /* It doesn't make sense to access the host's /proc when debugging a
+     core file.  Instead, look for the PT_LOAD segment that matches
+     the vDSO.  */
+  if (!target_has_execution)
+    {
+      Elf_Internal_Phdr *phdrs;
+      long phdrs_size;
+      int num_phdrs, i;
+
+      phdrs_size = bfd_get_elf_phdr_upper_bound (core_bfd);
+      if (phdrs_size == -1)
+	return 0;
+
+      phdrs = (Elf_Internal_Phdr *) alloca (phdrs_size);
+      num_phdrs = bfd_get_elf_phdrs (core_bfd, phdrs);
+      if (num_phdrs == -1)
+	return 0;
+
+      for (i = 0; i < num_phdrs; i++)
+	if (phdrs[i].p_type == PT_LOAD
+	    && phdrs[i].p_vaddr == range->start)
+	  {
+	    range->length = phdrs[i].p_memsz;
+	    return 1;
+	  }
+
+      return 0;
+    }
+
   /* We need to know the real target PID to access /proc.  */
   if (current_inferior ()->fake_pid_p)
     return 0;
 
-  if (target_auxv_search (&current_target, AT_SYSINFO_EHDR, &range->start) <= 0)
-    return 0;
-
   pid = current_inferior ()->pid;
 
   /* Note that reading /proc/PID/task/PID/maps (1) is much faster than
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog
index 3a94e82..4438bcc 100644
--- a/gdb/testsuite/ChangeLog
+++ b/gdb/testsuite/ChangeLog
@@ -1,3 +1,10 @@
+2016-08-22  Pedro Alves  <palves@redhat.com>
+
+	PR gdb/20505
+	* gdb.base/vdso-warning.exp: Test core dumps too.  Use
+	with_test_prefix.  Factor out bits to ...
+	(test_no_vdso): ... this new procedure.
+
 2016-08-15  Doug Evans  <dje@google.com>
 
 	* gdb.xml/extra-regs.xml: Update, end field now required, default type
diff --git a/gdb/testsuite/gdb.base/vdso-warning.exp b/gdb/testsuite/gdb.base/vdso-warning.exp
index af2b2b0..aeb85a2 100644
--- a/gdb/testsuite/gdb.base/vdso-warning.exp
+++ b/gdb/testsuite/gdb.base/vdso-warning.exp
@@ -13,42 +13,70 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
+# Test that on Linux, we don't warn about not finding the vDSO.  E.g.:
+#
+#   warning: Could not load shared library symbols for linux-vdso.so.1.
+
 standard_testfile
 
 if { [prepare_for_testing "failed to prepare" ${testfile} $srcfile] } {
     return -1
 }
 
-gdb_breakpoint "main"
+with_test_prefix "setup" {
+    gdb_breakpoint "main"
 
-# At least some versions of Fedora/RHEL glibc have local patches that
-# hide the vDSO.  This lines re-exposes it.  See PR libc/13097,
-# comment 2.  There's no support for passing environment variables in
-# the remote protocol, but that's OK -- if we're testing against a
-# glibc that doesn't list the vDSO without this, the test should still
-# pass.
-gdb_test_no_output "set environment LD_DEBUG=unused"
+    # At least some versions of Fedora/RHEL glibc have local patches that
+    # hide the vDSO.  This lines re-exposes it.  See PR libc/13097,
+    # comment 2.  There's no support for passing environment variables in
+    # the remote protocol, but that's OK -- if we're testing against a
+    # glibc that doesn't list the vDSO without this, the test should still
+    # pass.
+    gdb_test_no_output "set environment LD_DEBUG=unused"
+}
 
-gdb_run_cmd
+proc test_no_vdso {command} {
+    global srcfile
+    global gdb_prompt
 
-set test "stop without warning"
-gdb_test_multiple "" $test {
-    -re "Could not load shared library symbols .*\r\n$gdb_prompt $" {
-	fail $test
+    set message "startup"
+    gdb_test_multiple "$command" $message {
+	-re "Could not load shared library symbols .*\r\n$gdb_prompt $" {
+	    fail $message
+	}
+	-re "main \\(\\) at .*$srcfile.*\r\n$gdb_prompt $" {
+	    pass $message
+	}
     }
-    -re "\r\nBreakpoint \[0-9\]+, main .*\r\n$gdb_prompt $" {
-	pass $test
+
+    # Extra testing in case the warning changes and we miss updating
+    # the above.
+    set test "no vdso without symbols is listed"
+    gdb_test_multiple "info shared" $test {
+	-re "No\[^\r\n\]+linux-(vdso|gate).*$gdb_prompt $" {
+	    fail $test
+	}
+	-re "$gdb_prompt $" {
+	    pass $test
+	}
     }
 }
 
-# Extra testing in case the warning changes and we miss updating the
-# above.
-set test "no vdso without symbols is listed"
-gdb_test_multiple "info shared" $test {
-    -re "No\[^\r\n\]+linux-(vdso|gate).*$gdb_prompt $" {
-	fail $test
-    }
-    -re "$gdb_prompt $" {
-	pass $test
+# First, try a live process.
+with_test_prefix "run" {
+    gdb_run_cmd
+    test_no_vdso ""
+}
+
+# Now, dump a core, and reload it.
+with_test_prefix "core" {
+    set corefile [standard_output_file $testfile.core]
+    set core_supported [gdb_gcore_cmd "$corefile" "save a corefile"]
+    if {!$core_supported} {
+	return -1
     }
+
+    clean_restart ${testfile}
+
+    test_no_vdso "core-file $corefile"
 }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]