diff options
-rw-r--r-- | gdb/ChangeLog | 8 | ||||
-rw-r--r-- | gdb/solib-svr4.c | 81 | ||||
-rw-r--r-- | gdb/testsuite/ChangeLog | 7 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/vdso-warning.c | 22 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/vdso-warning.exp | 54 |
5 files changed, 170 insertions, 2 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 8923698..685419a 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,11 @@ +2014-10-10 Jan Kratochvil <jan.kratochvil@redhat.com> + Pedro Alves <palves@redhat.com> + + PR symtab/14466 + * solib-svr4.c (svr4_read_so_list): Rename to ... + (svr4_current_sos_1): ... this and change the function comment. + (svr4_current_sos): New function. + 2014-10-10 Pedro Alves <palves@redhat.com> * arch-utils.c (default_vsyscall_range): New function. diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 5c87019..5313bf0 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -1461,10 +1461,11 @@ svr4_current_sos_direct (struct svr4_info *info) return head; } -/* Implement the "current_sos" target_so_ops method. */ +/* Implement the main part of the "current_sos" target_so_ops + method. */ static struct so_list * -svr4_current_sos (void) +svr4_current_sos_1 (void) { struct svr4_info *info = get_svr4_info (); @@ -1477,6 +1478,82 @@ svr4_current_sos (void) return svr4_current_sos_direct (info); } +/* Implement the "current_sos" target_so_ops method. */ + +static struct so_list * +svr4_current_sos (void) +{ + struct so_list *so_head = svr4_current_sos_1 (); + struct mem_range vsyscall_range; + + /* Filter out the vDSO module, if present. Its symbol file would + not be found on disk. The vDSO/vsyscall's OBJFILE is instead + managed by symfile-mem.c:add_vsyscall_page. */ + if (gdbarch_vsyscall_range (target_gdbarch (), &vsyscall_range) + && vsyscall_range.length != 0) + { + struct so_list **sop; + + sop = &so_head; + while (*sop != NULL) + { + struct so_list *so = *sop; + + /* We can't simply match the vDSO by starting address alone, + because lm_info->l_addr_inferior (and also l_addr) do not + necessarily represent the real starting address of the + ELF if the vDSO's ELF itself is "prelinked". The l_ld + field (the ".dynamic" section of the shared object) + always points at the absolute/resolved address though. + So check whether that address is inside the vDSO's + mapping instead. + + E.g., on Linux 3.16 (x86_64) the vDSO is a regular + 0-based ELF, and we see: + + (gdb) info auxv + 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffb000 + (gdb) p/x *_r_debug.r_map.l_next + $1 = {l_addr = 0x7ffff7ffb000, ..., l_ld = 0x7ffff7ffb318, ...} + + And on Linux 2.6.32 (x86_64) we see: + + (gdb) info auxv + 33 AT_SYSINFO_EHDR System-supplied DSO's ELF header 0x7ffff7ffe000 + (gdb) p/x *_r_debug.r_map.l_next + $5 = {l_addr = 0x7ffff88fe000, ..., l_ld = 0x7ffff7ffe580, ... } + + Dumping that vDSO shows: + + (gdb) info proc mappings + 0x7ffff7ffe000 0x7ffff7fff000 0x1000 0 [vdso] + (gdb) dump memory vdso.bin 0x7ffff7ffe000 0x7ffff7fff000 + # readelf -Wa vdso.bin + [...] + Entry point address: 0xffffffffff700700 + [...] + Section Headers: + [Nr] Name Type Address Off Size + [ 0] NULL 0000000000000000 000000 000000 + [ 1] .hash HASH ffffffffff700120 000120 000038 + [ 2] .dynsym DYNSYM ffffffffff700158 000158 0000d8 + [...] + [ 9] .dynamic DYNAMIC ffffffffff700580 000580 0000f0 + */ + if (address_in_mem_range (so->lm_info->l_ld, &vsyscall_range)) + { + *sop = so->next; + free_so (so); + break; + } + + sop = &so->next; + } + } + + return so_head; +} + /* Get the address of the link_map for a given OBJFILE. */ CORE_ADDR diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index fac6e07..5578060 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,3 +1,10 @@ +2014-10-10 Jan Kratochvil <jan.kratochvil@redhat.com> + Pedro Alves <palves@redhat.com> + + PR symtab/14466 + * gdb.base/vdso-warning.c: New file. + * gdb.base/vdso-warning.exp: New file. + 2014-10-02 Doug Evans <dje@google.com> * gdb.base/structs.c (main): Don't run forever. diff --git a/gdb/testsuite/gdb.base/vdso-warning.c b/gdb/testsuite/gdb.base/vdso-warning.c new file mode 100644 index 0000000..4b94803 --- /dev/null +++ b/gdb/testsuite/gdb.base/vdso-warning.c @@ -0,0 +1,22 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2014 Free Software Foundation, Inc. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +int +main (void) +{ + return 0; +} diff --git a/gdb/testsuite/gdb.base/vdso-warning.exp b/gdb/testsuite/gdb.base/vdso-warning.exp new file mode 100644 index 0000000..1f538fa --- /dev/null +++ b/gdb/testsuite/gdb.base/vdso-warning.exp @@ -0,0 +1,54 @@ +# Copyright 2012-2014 Free Software Foundation, Inc. + +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +standard_testfile + +if { [prepare_for_testing "failed to prepare" ${testfile} $srcfile] } { + return -1 +} + +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" + +gdb_run_cmd + +set test "stop without warning" +gdb_test_multiple "" $test { + -re "Could not load shared library symbols .*\r\n$gdb_prompt $" { + fail $test + } + -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 + } +} |