diff options
-rw-r--r-- | gdb/solib-svr4.c | 78 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/dlmopen-lib-dep.c | 21 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/dlmopen-lib.c | 5 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/dlmopen.exp | 40 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/non-lazy-array-index.exp | 18 | ||||
-rw-r--r-- | gdb/testsuite/gdb.server/bkpt-other-inferior.exp | 13 |
6 files changed, 159 insertions, 16 deletions
diff --git a/gdb/solib-svr4.c b/gdb/solib-svr4.c index 295e9b8..6acaf87 100644 --- a/gdb/solib-svr4.c +++ b/gdb/solib-svr4.c @@ -3313,9 +3313,60 @@ svr4_lp64_fetch_link_map_offsets (void) } +/* Return the DSO matching OBJFILE or nullptr if none can be found. */ + +static so_list * +find_solib_for_objfile (struct objfile *objfile) +{ + if (objfile == nullptr) + return nullptr; + + /* If OBJFILE is a separate debug object file, look for the original + object file. */ + if (objfile->separate_debug_objfile_backlink != nullptr) + objfile = objfile->separate_debug_objfile_backlink; + + for (so_list *so : current_program_space->solibs ()) + if (so->objfile == objfile) + return so; + + return nullptr; +} + +/* Return the address of the r_debug object for the namespace containing + SOLIB or zero if it cannot be found. This may happen when symbol files + are added manually, for example, or with the main executable. + + Current callers treat zero as initial namespace so they are doing the + right thing for the main executable. */ + +static CORE_ADDR +find_debug_base_for_solib (so_list *solib) +{ + if (solib == nullptr) + return 0; + + svr4_info *info = get_svr4_info (current_program_space); + gdb_assert (info != nullptr); + for (const std::pair<CORE_ADDR, so_list *> tuple + : info->solib_lists) + { + CORE_ADDR debug_base = tuple.first; + so_list *solist = tuple.second; + + for (; solist != nullptr; solist = solist->next) + if (svr4_same (solib, solist)) + return debug_base; + } + + return 0; +} + /* Search order for ELF DSOs linked with -Bsymbolic. Those DSOs have a - different rule for symbol lookup. The lookup begins here in the DSO, not in - the main executable. */ + different rule for symbol lookup. The lookup begins here in the DSO, + not in the main executable. When starting from CURRENT_OBJFILE, we + stay in the same namespace as that file. Otherwise, we only consider + the initial namespace. */ static void svr4_iterate_over_objfiles_in_search_order @@ -3344,10 +3395,33 @@ svr4_iterate_over_objfiles_in_search_order } } + /* The linker namespace to iterate identified by the address of its + r_debug object, defaulting to the initial namespace. */ + CORE_ADDR initial = elf_locate_base (); + so_list *curr_solib = find_solib_for_objfile (current_objfile); + CORE_ADDR debug_base = find_debug_base_for_solib (curr_solib); + if (debug_base == 0) + debug_base = initial; + for (objfile *objfile : current_program_space->objfiles ()) { if (checked_current_objfile && objfile == current_objfile) continue; + + /* Try to determine the namespace into which objfile was loaded. + + If we fail, e.g. for manually added symbol files or for the main + executable, we assume that they were added to the initial + namespace. */ + so_list *solib = find_solib_for_objfile (objfile); + CORE_ADDR solib_base = find_debug_base_for_solib (solib); + if (solib_base == 0) + solib_base = initial; + + /* Ignore objfiles that were added to a different namespace. */ + if (solib_base != debug_base) + continue; + if (cb (objfile)) return; } diff --git a/gdb/testsuite/gdb.base/dlmopen-lib-dep.c b/gdb/testsuite/gdb.base/dlmopen-lib-dep.c new file mode 100644 index 0000000..c996d76 --- /dev/null +++ b/gdb/testsuite/gdb.base/dlmopen-lib-dep.c @@ -0,0 +1,21 @@ +/* This testcase is part of GDB, the GNU debugger. + + Copyright 2021-2022 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/>. + +*/ + +__attribute__((visibility ("default"))) +int gdb_dlmopen_glob = 1; diff --git a/gdb/testsuite/gdb.base/dlmopen-lib.c b/gdb/testsuite/gdb.base/dlmopen-lib.c index 616bf97..4645bfd 100644 --- a/gdb/testsuite/gdb.base/dlmopen-lib.c +++ b/gdb/testsuite/gdb.base/dlmopen-lib.c @@ -17,9 +17,12 @@ */ +extern int gdb_dlmopen_glob; + __attribute__((visibility ("default"))) int inc (int n) { - return n + 1; /* bp.inc. */ + int amount = gdb_dlmopen_glob; + return n + amount; /* bp.inc. */ } diff --git a/gdb/testsuite/gdb.base/dlmopen.exp b/gdb/testsuite/gdb.base/dlmopen.exp index 8e86d5d..a80db75 100644 --- a/gdb/testsuite/gdb.base/dlmopen.exp +++ b/gdb/testsuite/gdb.base/dlmopen.exp @@ -32,13 +32,22 @@ set basename_lib dlmopen-lib set srcfile_lib $srcdir/$subdir/$basename_lib.c set binfile_lib1 [standard_output_file $basename_lib.1.so] set binfile_lib2 [standard_output_file $basename_lib.2.so] +set srcfile_lib_dep $srcdir/$subdir/$basename_lib-dep.c +set binfile_lib_dep [standard_output_file $basename_lib-dep.so] -if { [gdb_compile_shlib $srcfile_lib $binfile_lib1 {debug}] != "" } { +if { [gdb_compile_shlib $srcfile_lib_dep $binfile_lib_dep {debug}] != "" } { untested "failed to prepare shlib" return -1 } -if { [gdb_compile_shlib $srcfile_lib $binfile_lib2 {debug}] != "" } { +if { [gdb_compile_shlib $srcfile_lib $binfile_lib1 \ + [list debug shlib_load libs=$binfile_lib_dep]] != "" } { + untested "failed to prepare shlib" + return -1 +} + +if { [gdb_compile_shlib $srcfile_lib $binfile_lib2 \ + [list debug shlib_load libs=$binfile_lib_dep]] != "" } { untested "failed to prepare shlib" return -1 } @@ -46,7 +55,7 @@ if { [gdb_compile_shlib $srcfile_lib $binfile_lib2 {debug}] != "" } { if { [prepare_for_testing "failed to prepare" $testfile $srcfile \ [list additional_flags=-DDSO1_NAME=\"$binfile_lib1\" \ additional_flags=-DDSO2_NAME=\"$binfile_lib2\" \ - libs=-ldl debug]] } { + shlib_load debug]] } { return -1 } @@ -73,7 +82,7 @@ proc check_dso_count { dso num } { } # The DSO part of the test. We run it once per DSO call. -proc test_dlmopen_one { ndso1 ndso2 } { +proc test_dlmopen_one { ndso1 ndso2 exp_glob } { global srcfile_lib srcfile_lib basename_lib bp_inc # Try to reach the breakpoint in the dynamically loaded library. @@ -87,16 +96,31 @@ proc test_dlmopen_one { ndso1 ndso2 } { # This might help debugging. gdb_test "info breakpoints" ".*" gdb_test "print \$pc" ".*" + + # We expect different instances of GDB_DLMOPEN_GLOB per DSO. + gdb_test "print amount" "= $exp_glob" + gdb_test "print gdb_dlmopen_glob" "= $exp_glob" + + # Modify that DSO's instance, which should leave the others intact. + gdb_test "print &gdb_dlmopen_glob" "= .*" + gdb_test "print gdb_dlmopen_glob = -1" "= -1" } # The actual test. We run it twice. proc test_dlmopen {} { global srcfile basename_lib bp_main - with_test_prefix "dlmopen 1" { test_dlmopen_one 3 1 } - with_test_prefix "dlmopen 2" { test_dlmopen_one 2 1 } - with_test_prefix "dlmopen 3" { test_dlmopen_one 1 1 } - with_test_prefix "dlmopen 4" { test_dlmopen_one 0 1 } + # Note that when loading dlmopen-lib.1.so and dlmopen-lib.2.so into + # the same namespace, dlmopen-lib-dep.so is loaded only once, so in + # this case, the changes to gdb_dlmopen_glob inside test_dlmopen_one + # will actually be visible. + # + # Hence, we supply the expected value of this variable as argument to + # test_dlmopen_one. + with_test_prefix "dlmopen 1" { test_dlmopen_one 3 1 1 } + with_test_prefix "dlmopen 2" { test_dlmopen_one 2 1 1 } + with_test_prefix "dlmopen 3" { test_dlmopen_one 1 1 1 } + with_test_prefix "dlmopen 4" { test_dlmopen_one 0 1 -1 } with_test_prefix "main" { # Try to reach the breakpoint in the dynamically loaded library. diff --git a/gdb/testsuite/gdb.base/non-lazy-array-index.exp b/gdb/testsuite/gdb.base/non-lazy-array-index.exp index 6b596eb..66686cf 100644 --- a/gdb/testsuite/gdb.base/non-lazy-array-index.exp +++ b/gdb/testsuite/gdb.base/non-lazy-array-index.exp @@ -40,6 +40,7 @@ gdb_test_no_output "set debug target 1" # To check this we 'set debug target 1' (above), and then look for any # xfer_partial calls; there shouldn't be any. set saw_memory_access false +set saw_auxv_parse false gdb_test_multiple "p \$.array\[1\]" "" { -re "^p \\\$\\.array\\\[1\\\]\r\n" { exp_continue @@ -48,6 +49,10 @@ gdb_test_multiple "p \$.array\[1\]" "" { set saw_memory_access true exp_continue } + -re "^->\[^\r\n\]+auxv_parse\[^\r\n\]+\r\n" { + set saw_auxv_parse true + exp_continue + } -re "^->\[^\r\n\]+\r\n" { exp_continue } @@ -58,7 +63,18 @@ gdb_test_multiple "p \$.array\[1\]" "" { exp_continue } -re "^\\\$${decimal} = 2\r\n$gdb_prompt " { - gdb_assert { ! $saw_memory_access } + if { $saw_memory_access } { + if { $saw_auxv_parse } { + # The expression parser may look up global symbols, which + # may require reading AUXV in order to determine the debug + # base for SVR4 linker namespaces. + xfail "$gdb_test_name" + } else { + fail "$gdb_test_name" + } + } else { + pass "$gdb_test_name" + } } } diff --git a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp index d01b911..452c7c9 100644 --- a/gdb/testsuite/gdb.server/bkpt-other-inferior.exp +++ b/gdb/testsuite/gdb.server/bkpt-other-inferior.exp @@ -78,13 +78,18 @@ foreach inf_sel {1 2} { gdb_test_no_output "set debug remote 1" - set test "set breakpoint" - gdb_test_multiple "break -q main" $test { + gdb_test_multiple "break -q main" "set breakpoint" { + -re "Sending packet: \\\$qXfer:auxv:read.*$gdb_prompt $" { + # Symbol lookup may access the target to read AUXV in + # order to determine the debug base for SVR4 linker + # namespaces. + xfail "$gdb_test_name" + } -re "Sending packet.*$gdb_prompt $" { - fail $test + fail "$gdb_test_name" } -re "^break -q main\r\nBreakpoint .* at .*$gdb_prompt $" { - pass $test + pass "$gdb_test_name" } } |