diff options
author | Jan Kratochvil <jan.kratochvil@redhat.com> | 2010-07-05 18:01:53 +0000 |
---|---|---|
committer | Jan Kratochvil <jan.kratochvil@redhat.com> | 2010-07-05 18:01:53 +0000 |
commit | 5e3b36f8799d7928f5c5ac5e871c0968b5874369 (patch) | |
tree | 819e2ed544aa1320a504ea740f2435ba9a6a395c /gdb | |
parent | 86e4bafc3b0bb0148b95807d37b36aae14cdf56c (diff) | |
download | gdb-5e3b36f8799d7928f5c5ac5e871c0968b5874369.zip gdb-5e3b36f8799d7928f5c5ac5e871c0968b5874369.tar.gz gdb-5e3b36f8799d7928f5c5ac5e871c0968b5874369.tar.bz2 |
gdb/testsuite/
* gdb.base/attach-pie-misread.exp: Load prelink-support.exp. Replace
build_executable by build_executable_own_libs. Replace "prelink -R"
execution by a call of prelink_yes. Comment why "prelink -r" needs no
change.
* gdb.base/break-interp.exp: Load prelink-support.exp. Rename calls of
copy to file_copy. Move setting opts --dynamic-linker and -rpath,
mkdir $dir and ldd its parsing and copying to lib/prelink-support.exp.
Replace build_executable by build_executable_own_libs's function
build_executable_own_libs.
(prelinkNO): Create new stub to call prelink_no.
(prelinkYES): Create new stub to call prelink_yes.
(test_attach): Rename calls of copy to file_copy.
(section_get, prelinkNO_run, prelinkNO, prelinkYES, symlink_resolve)
(copy): Move to ...
* lib/prelink-support.exp: ... a new file. Rename prelinkNO to
prelink_no, prelinkYES to prelink_yes, copy to file_copy.
* gdb.base/prelink.exp: Disable testcase also for is_remote and
skip_shlib_tests. Load prelink-support.exp. Replace gdb_compile with
special flags by gdb_compile_shlib. Replace second gdb_compile by
build_executable_own_libs. Replace "prelink -R" execution by a call of
prelink_yes. Replace "prelink -u" and second "prelink -R" execution by
a second call of prelink_yes. Replace restart commands by
clean_restart.
(prelink): Rename to ...
(seen displacement message): ... this test. Extend its expectation
strictness.
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/testsuite/ChangeLog | 30 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/attach-pie-misread.exp | 25 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/break-interp.exp | 208 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/prelink.exp | 46 | ||||
-rw-r--r-- | gdb/testsuite/lib/prelink-support.exp | 254 |
5 files changed, 338 insertions, 225 deletions
diff --git a/gdb/testsuite/ChangeLog b/gdb/testsuite/ChangeLog index 682dc9a..8d52e40 100644 --- a/gdb/testsuite/ChangeLog +++ b/gdb/testsuite/ChangeLog @@ -1,4 +1,34 @@ 2010-07-05 Jan Kratochvil <jan.kratochvil@redhat.com> + Joel Brobecker <brobecker@adacore.com> + + * gdb.base/attach-pie-misread.exp: Load prelink-support.exp. Replace + build_executable by build_executable_own_libs. Replace "prelink -R" + execution by a call of prelink_yes. Comment why "prelink -r" needs no + change. + * gdb.base/break-interp.exp: Load prelink-support.exp. Rename calls of + copy to file_copy. Move setting opts --dynamic-linker and -rpath, + mkdir $dir and ldd its parsing and copying to lib/prelink-support.exp. + Replace build_executable by build_executable_own_libs's function + build_executable_own_libs. + (prelinkNO): Create new stub to call prelink_no. + (prelinkYES): Create new stub to call prelink_yes. + (test_attach): Rename calls of copy to file_copy. + (section_get, prelinkNO_run, prelinkNO, prelinkYES, symlink_resolve) + (copy): Move to ... + * lib/prelink-support.exp: ... a new file. Rename prelinkNO to + prelink_no, prelinkYES to prelink_yes, copy to file_copy. + * gdb.base/prelink.exp: Disable testcase also for is_remote and + skip_shlib_tests. Load prelink-support.exp. Replace gdb_compile with + special flags by gdb_compile_shlib. Replace second gdb_compile by + build_executable_own_libs. Replace "prelink -R" execution by a call of + prelink_yes. Replace "prelink -u" and second "prelink -R" execution by + a second call of prelink_yes. Replace restart commands by + clean_restart. + (prelink): Rename to ... + (seen displacement message): ... this test. Extend its expectation + strictness. + +2010-07-05 Jan Kratochvil <jan.kratochvil@redhat.com> * gdb.base/attach-pie-misread.exp, gdb.base/attach-pie-misread.c: New. * gdb.base/break-interp.exp (reach, test_core, test_ld): Require each diff --git a/gdb/testsuite/gdb.base/attach-pie-misread.exp b/gdb/testsuite/gdb.base/attach-pie-misread.exp index 334272b..10e4936 100644 --- a/gdb/testsuite/gdb.base/attach-pie-misread.exp +++ b/gdb/testsuite/gdb.base/attach-pie-misread.exp @@ -18,13 +18,15 @@ if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_test continue } +load_lib prelink-support.exp + set test "attach-pie-misread" set srcfile ${test}.c set genfile ${objdir}/${subdir}/${test}-gen.h set executable ${test} set binfile ${objdir}/${subdir}/${executable} -if {[build_executable ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie"]] == -1} { +if {[build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie"]] == ""} { return -1 } @@ -94,7 +96,8 @@ if {$result == 0} { fail $test } -if {[build_executable ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie -DGEN=\"$genfile\""]] == -1} { +set prelink_args [build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie -DGEN=\"$genfile\""]] +if {$prelink_args == ""} { return -1 } @@ -104,20 +107,8 @@ file delete -- $genfile set phdr [read_phdr $binfile "readelf rebuilt with stub_size"] set dynamic_vaddr_prelinkno [lindex $phdr 0] -set command "exec /usr/sbin/prelink -q -N --no-exec-shield -R $binfile" -verbose -log "command is $command" -set result [catch $command output] -verbose -log "result is $result" -verbose -log "output is $output" - -set test "prelink -R" -if {$result == 0 && $output == ""} { - pass $test -} elseif {$result == 1 && [regexp {^(couldn't execute "/usr/sbin/prelink[^\r\n]*": no such file or directory\n?)*$} $output]} { - untested attach-pie-misread.exp +if ![prelink_yes $prelink_args] { return -1 -} else { - fail $test } set phdr [read_phdr $binfile "readelf with prelink -R"] @@ -168,6 +159,10 @@ foreach align_mult {1 2} { set shifted_offset [format 0x%x [expr "$first_offset - $align_mult * $align_max"]] verbose -log "shifted_offset is $shifted_offset" + # For normal prelink (prelink_yes call), we need to supply $prelink_args. + # For the prelink `-r' option below, $prelink_args is not required. + # Moreover, if it was used, the problem would not longer be reproducible + # as the libraries would also get relocated. set command "exec /usr/sbin/prelink -q -N --no-exec-shield -r $shifted_offset $binfile" verbose -log "command is $command" set result [catch $command output] diff --git a/gdb/testsuite/gdb.base/break-interp.exp b/gdb/testsuite/gdb.base/break-interp.exp index 8cd20d4..a3b9c20 100644 --- a/gdb/testsuite/gdb.base/break-interp.exp +++ b/gdb/testsuite/gdb.base/break-interp.exp @@ -18,6 +18,8 @@ if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_test continue } +load_lib prelink-support.exp + set test "break-interp" set binprefix ${objdir}/${subdir}/${test} # Only to get the $interp_system name. @@ -31,8 +33,7 @@ if [get_compiler_info ${binfile_lib}] { return -1 } -# Use -soname so that it is listed with " => " by ldd and this testcase makes -# a copy of ${binfile_lib} for each prelink variant. +# Use -soname so that the new library gets copied by build_executable_own_libs. if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-Wl,-soname,${test}.so]] != ""} { return -1 @@ -42,38 +43,6 @@ if {[build_executable ${test}.exp $binfile_test ${srcfile_test} {}] == -1} { return -1 } -# Return the interpreter filename string. -# Return "" if no interpreter was found. -proc section_get {exec section} { - global objdir - global subdir - set tmp "${objdir}/${subdir}/break-interp.interp" - set objcopy_program [transform objcopy] - - set command "exec $objcopy_program -O binary --set-section-flags $section=A --change-section-address $section=0 -j $section $exec $tmp" - verbose -log "command is $command" - set result [catch $command output] - verbose -log "result is $result" - verbose -log "output is $output" - if {$result == 1} { - return "" - } - set fi [open $tmp] - fconfigure $fi -translation binary - set data [read $fi] - close $fi - #file delete $tmp - # .interp has size $len + 1 but .gnu_debuglink contains garbage after \000. - set len [string first \000 $data] - if {$len < 0} { - verbose -log "section $section not found" - return "" - } - set retval [string range $data 0 [expr $len - 1]] - verbose -log "section $section is <$retval>" - return $retval -} - # Note: The separate debug info file content build-id/crc32 are not verified # contrary to the GDB search algorithm skipping non-matching ones. proc system_debug_get {exec} { @@ -117,104 +86,12 @@ set interp_system [section_get ${objdir}/${subdir}/$binfile_test .interp] set interp_system_debug [system_debug_get $interp_system] verbose -log "$interp_system has debug $interp_system_debug" -proc prelinkNO_run {arg} { - set command "exec /usr/sbin/prelink -uN $arg" - verbose -log "command is $command" - set result [catch $command output] - verbose -log "result is $result" - verbose -log "output is $output" - return [list $result $output] -} - -proc prelinkNO {arg {name {}}} { - if {$name == ""} { - set name [file tail $arg] - } - set test "unprelink $name" - set run [prelinkNO_run $arg] - set result [lindex $run 0] - set output [lindex $run 1] - if {$result == 0 && $output == ""} { - verbose -log "$name has been now unprelinked" - set run [prelinkNO_run $arg] - set result [lindex $run 0] - set output [lindex $run 1] - } - # Last line does miss the trailing \n. - if {$result == 1 && [regexp {^(/usr/sbin/prelink[^\r\n]*: [^ ]* does not have .gnu.prelink_undo section\n?)*$} $output]} { - pass $test - return 1 - } else { - fail $test - return 0 - } +proc prelinkNO {arg {name ""}} { + return [prelink_no $arg $name] } proc prelinkYES {arg {name ""}} { - if {$name == ""} { - set name [file tail $arg] - } - - # Try to unprelink it first so that if it has been already prelinked before - # we get different address now and the result is not affected by the - # previous $arg state.. - prelinkNO $arg "$name pre-unprelink" - - set test "prelink $name" - set command "exec /usr/sbin/prelink -qNR --no-exec-shield $arg" - verbose -log "command is $command" - set result [catch $command output] - verbose -log "result is $result" - verbose -log "output is $output" - if {$result == 0 && $output == ""} { - pass $test - return 1 - } elseif {$result == 1 \ - && [string match -nocase "*: Not enough room to add .dynamic entry" $output]} { - # Linker should have reserved some entries for prelink. - xfail $test - return 0 - } else { - fail $test - return 0 - } -} - -# Resolve symlinks. -proc symlink_resolve {file} { - set loop 0 - while {[file type $file] == "link"} { - set target [file readlink $file] - if {[file pathtype $target] == "relative"} { - set src2 [file dirname $file]/$target - } else { - set src2 $target - } - verbose -log "Resolved symlink $file targetting $target as $src2" - set file $src2 - - set loop [expr $loop + 1] - if {$loop > 30} { - fail "Looping symlink resolution for $file" - return "" - } - } - return $file -} - -proc copy {src dest} { - set src [symlink_resolve $src] - # Test name would contain build-id hash for symlink-unresolved $src. - set test "copy [file tail $src] to [file tail $dest]" - set command "file copy -force $src $dest" - verbose -log "command is $command" - if [catch $command] { - fail $test - return 0 - } else { - pass $test - return 1 - } + return [prelink_yes $arg $name] } proc strip_debug {dest} { @@ -425,8 +302,8 @@ proc test_attach {file displacement {relink_args ""}} { # Formerly this test was testing only prelinking of $EXEC. As the # prelink command automatically prelinks all of $EXEC's libraries, # even $INTERP got prelinked. Therefore, we formerly had to - # `[copy $interp_saved $interp]' to make $INTERP not affected by - # this prelinking of $EXEC. + # `[file_copy $interp_saved $interp]' to make $INTERP not affected + # by this prelinking of $EXEC. # # But now we need to test even prelinking of $INTERP. We could # create a separate test to test just the $INTERP prelinking. For @@ -439,7 +316,7 @@ proc test_attach {file displacement {relink_args ""}} { test_attach_gdb $exec $pid $displacement "attach-relink$relink" } } - copy $interp_saved $interp + file_copy $interp_saved $interp } remote_exec host "kill -9 $pid" @@ -582,7 +459,7 @@ foreach ldprelink {NO YES} { lappend pf_prefix "$ldname:" if {$ldsepdebug == "NO"} { - copy $interp_system $interp + file_copy $interp_system $interp # Never call strip-debug before unprelink: # prelink: ...: Section .note.gnu.build-id created after prelinking if ![prelinkNO $interp] { @@ -590,10 +467,10 @@ foreach ldprelink {NO YES} { } strip_debug $interp } elseif {$ldsepdebug == "IN" && $interp_system_debug == ""} { - copy $interp_system $interp + file_copy $interp_system $interp } elseif {$ldsepdebug == "IN" && $interp_system_debug != ""} { - copy $interp_system $interp - copy $interp_system_debug "${interp}.debug" + file_copy $interp_system $interp + file_copy $interp_system_debug "${interp}.debug" # eu-unstrip: DWARF data in '...' not adjusted for prelinking bias; consider prelink -u if {![prelinkNO $interp] || ![prelinkNO "${interp}.debug"]} { continue @@ -609,15 +486,15 @@ foreach ldprelink {NO YES} { pass $test } } elseif {$ldsepdebug == "SEP" && $interp_system_debug == ""} { - copy $interp_system $interp + file_copy $interp_system $interp # eu-unstrip: DWARF data in '...' not adjusted for prelinking bias; consider prelink -u if ![prelinkNO $interp] { continue } gdb_gnu_strip_debug $interp } elseif {$ldsepdebug == "SEP" && $interp_system_debug != ""} { - copy $interp_system $interp - copy $interp_system_debug "${interp}.debug" + file_copy $interp_system $interp + file_copy $interp_system_debug "${interp}.debug" } if {$ldsepdebug == "SEP"} { @@ -638,7 +515,7 @@ foreach ldprelink {NO YES} { } test_ld $interp 0 [expr {$ldsepdebug == "NO"}] $displacement - if ![copy $interp $interp_saved] { + if ![file_copy $interp $interp_saved] { continue } set old_binprefix $pf_prefix @@ -656,64 +533,28 @@ foreach ldprelink {NO YES} { set binname "BINprelink${binprelink}debug${binsepdebug}pie${binpie}" set exec $binprefix-$binname - set dir ${exec}.d set pf_prefix $old_binprefix lappend pf_prefix "$binname:" - set opts "additional_flags=-Wl,--dynamic-linker,$interp,-rpath,$dir" - lappend opts "additional_flags=-Wl,$binfile_lib,-rpath,[file dirname $binfile_lib]" + set opts "additional_flags=-Wl,$binfile_lib,-rpath,[file dirname $binfile_lib]" if {$binsepdebug != "NO"} { lappend opts {debug} } if {$binpie != "NO"} { lappend opts {additional_flags=-fPIE -pie} } - if {[build_executable ${test}.exp [file tail $exec] $srcfile $opts] == -1} { + + set dir ${exec}.d + set relink_args [build_executable_own_libs ${test}.exp [file tail $exec] $srcfile $opts $interp $dir] + if {$relink_args == ""} { continue; } + if {$binsepdebug == "SEP"} { gdb_gnu_strip_debug $exec } - # Supply a self-sufficent directory $dir with the required - # libraries. To make an executable properly prelinked all - # its dependencies on libraries must be also prelinked. If - # some of the system libraries is currently not prelinked - # we have no right to prelink (modify it) at its current - # system place. - - file delete -force $dir - file mkdir $dir - - set command "ldd $exec" - set test "ldd [file tail $exec]" - set result [catch "exec $command" output] - verbose -log "result of $command is $result" - verbose -log "output of $command is $output" - if {$result != 0 || $output == ""} { - fail $test - } else { - pass $test - } - - # gdb testsuite will put there also needless -lm. - set test "$test output contains libc" - set libc [regexp -all -inline -line {^.* => (/[^ ]+).*$} $output] - if {[llength $libc] == 0} { - fail $test - } else { - pass $test - } - - set dests {} - for {set i 1} {$i < [llength $libc]} {incr i 2} { - set abspath [lindex $libc $i] - set dest "$dir/[file tail $abspath]" - copy $abspath $dest - lappend dests $dest - } - if {$binpie == "NO"} { set displacement "NONE" } elseif {$binprelink == "NO"} { @@ -722,9 +563,8 @@ foreach ldprelink {NO YES} { set displacement "ZERO" } - set relink_args "--dynamic-linker=$interp --ld-library-path=$dir $exec $interp [concat $dests]" if {[prelink$binprelink $relink_args [file tail $exec]] - && [copy $interp_saved $interp]} { + && [file_copy $interp_saved $interp]} { if {$binpie != "ATTACH"} { test_ld $exec 1 [expr {$binsepdebug == "NO"}] $displacement } else { diff --git a/gdb/testsuite/gdb.base/prelink.exp b/gdb/testsuite/gdb.base/prelink.exp index 1803a80..8931c9f 100644 --- a/gdb/testsuite/gdb.base/prelink.exp +++ b/gdb/testsuite/gdb.base/prelink.exp @@ -23,8 +23,7 @@ if $tracelevel then { } -# are we on a target board -if ![isnative] then { +if { ![isnative] || [is_remote host] || [skip_shlib_tests]} { return } @@ -36,32 +35,31 @@ if {$gcc_compiled == 0} { return -1 } +load_lib prelink-support.exp + set testfile "prelink" set libsrcfile ${testfile}-lib.c set libfile ${objdir}/${subdir}/${testfile}.so -if { [gdb_compile "${srcdir}/${subdir}/${libsrcfile}" "${libfile}" executable [list debug "additional_flags=-fpic -shared -nodefaultlibs"]] != ""} { + +# Use -soname so that the new library gets copied by build_executable_own_libs. + +if { [gdb_compile_shlib "${srcdir}/${subdir}/${libsrcfile}" "${libfile}" [list debug "additional_flags=-Wl,-soname,[file tail ${libfile}]"]] != ""} { # If creating the shared library fails, maybe we don't have the right tools return -1 } -# `--no-exec-shield' is for i386 where prelink in the exec-shield mode is -# forced to push all the libraries tight together to fit into the first two -# memory areas (either the ASCII Shield area or at least below the executable). -# In this case its -R option cannot be applied and we falsely FAIL here as if -# the system is already prelinked prelink has no choice how to randomize the -# single new unprelinked library address without wasting the first one/two -# memory areas. We do not care of the efficiency of loading such resulting -# exec-shield unfriendly prelinked library. -if {[catch "system \"prelink -qNR --no-exec-shield ${libfile}\""] != 0} { - # Maybe we don't have prelink. +set srcfile ${testfile}.c +set executable ${testfile}t +set binfile ${objdir}/${subdir}/${executable} +set prelink_args [build_executable_own_libs ${testfile}.exp $executable $srcfile [list debug "additional_flags=-Wl,${libfile},-rpath,[file dirname ${libfile}]"]] +if {$prelink_args == ""} { return -1 } -set srcfile ${testfile}.c -set binfile ${objdir}/${subdir}/${testfile}t -if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${libfile}" "${binfile}" executable [list debug "additional_flags=-Wl,-rpath,${objdir}/${subdir}"]] != ""} { - return -1; +if ![prelink_yes $prelink_args] { + # Maybe we don't have prelink. + return -1 } set found 0 @@ -94,20 +92,16 @@ if { $found == 0 } { return 0 } -if {[catch "system \"prelink -uN ${libfile}\""] != 0} { - untested "${testfile}.so was not prelinked, maybe system libraries are not prelinked?" - return 0 +# Relink $libfile to a different address. +if ![prelink_yes $prelink_args] { + return -1 } -catch "system \"prelink -qNR --no-exec-shield ${libfile}\"" # Start with a fresh gdb -gdb_exit -gdb_start -gdb_reinitialize_dir $srcdir/$subdir -gdb_load ${binfile} +clean_restart $executable # Print the "adjusting expectations" message. gdb_test_no_output "set verbose on" -gdb_test "core-file $objdir/$subdir/prelink.core" {Using PIC \(Position Independent Code\) prelink displacement.*} "prelink" +gdb_test "core-file $objdir/$subdir/prelink.core" "Using PIC \\(Position Independent Code\\) prelink displacement 0x\[^0\]\[0-9a-f\]* for \[^\r\n\]*[file tail ${libfile}].*" "seen displacement message" diff --git a/gdb/testsuite/lib/prelink-support.exp b/gdb/testsuite/lib/prelink-support.exp new file mode 100644 index 0000000..6d9e909 --- /dev/null +++ b/gdb/testsuite/lib/prelink-support.exp @@ -0,0 +1,254 @@ +# Copyright (C) 2010 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/>. + +# Return nul-terminated string read from section SECTION of EXEC. Return "" +# if no such section or nul-terminated string was found. Function is useful +# for sections ".interp" or ".gnu_debuglink". + +proc section_get {exec section} { + global objdir + global subdir + set tmp "${objdir}/${subdir}/section_get.tmp" + set objcopy_program [transform objcopy] + + set command "exec $objcopy_program -O binary --set-section-flags $section=A --change-section-address $section=0 -j $section $exec $tmp" + verbose -log "command is $command" + set result [catch $command output] + verbose -log "result is $result" + verbose -log "output is $output" + if {$result == 1} { + return "" + } + set fi [open $tmp] + fconfigure $fi -translation binary + set data [read $fi] + close $fi + file delete $tmp + # .interp has size $len + 1 but .gnu_debuglink contains garbage after \000. + set len [string first \000 $data] + if {$len < 0} { + verbose -log "section $section not found" + return "" + } + set retval [string range $data 0 [expr $len - 1]] + verbose -log "section $section is <$retval>" + return $retval +} + +# Resolve symlinks. + +proc symlink_resolve {file} { + set loop 0 + while {[file type $file] == "link"} { + set target [file readlink $file] + if {[file pathtype $target] == "relative"} { + set src2 [file dirname $file]/$target + } else { + set src2 $target + } + verbose -log "Resolved symlink $file targetting $target as $src2" + set file $src2 + + set loop [expr $loop + 1] + if {$loop > 30} { + fail "Looping symlink resolution for $file" + return "" + } + } + return $file +} + +# Copy SRC to DEST, resolving any symlinks in SRC. Return nonzero iff +# the copy was succesful. +# +# This function is guaranteed to never raise any exception, even when the copy +# fails. + +proc file_copy {src dest} { + set src [symlink_resolve $src] + # Test name would contain unstable directory name for symlink-unresolved + # $src. + set test "copy [file tail $src] to [file tail $dest]" + set command "file copy -force -- $src $dest" + verbose -log "command is $command" + if [catch $command] { + fail $test + return 0 + } else { + pass $test + return 1 + } +} + +# Wrap function build_executable so that the resulting executable is fully +# self-sufficient (without dependencies on system libraries). Parameter +# INTERP may be used to specify a loader (ld.so) to be used that is +# different from the default system one. Libraries on which the executable +# depends are copied into directory DIR. Default DIR value to +# `${objdir}/${subdir}/${EXECUTABLE}.d'. +# +# In case of success, return a string containing the arguments to be used +# in order to perform a prelink of the executable obtained. Return the +# empty string in case of failure. +# +# This can be useful when trying to prelink an executable which might +# depend on system libraries. To properly prelink an executable, all +# of its dynamically linked libraries must be prelinked as well. If +# the executable depends on some system libraries, we may not have +# sufficient write priviledges on these files to perform the prelink. +# This is why we make a copy of these shared libraries, and link the +# executable against these copies instead. +# +# Function recognizes only libraries listed by `ldd' after +# its ` => ' separator. That means $INTERP and any libraries not being linked +# with -Wl,-soname,NAME.so are not copied. + +proc build_executable_own_libs {testname executable sources options {interp ""} {dir ""}} { + global objdir subdir + + if {[build_executable $testname $executable $sources $options] == -1} { + return "" + } + set binfile ${objdir}/${subdir}/${executable} + + set command "ldd $binfile" + set test "ldd $executable" + set result [catch "exec $command" output] + verbose -log "result of $command is $result" + verbose -log "output of $command is $output" + if {$result != 0 || $output == ""} { + fail $test + } else { + pass $test + } + + # gdb testsuite will put there also needless -lm. + set test "$test output contains libs" + set libs [regexp -all -inline -line {^.* => (/[^ ]+).*$} $output] + if {[llength $libs] == 0} { + fail $test + } else { + pass $test + } + + if {$dir == ""} { + set dir ${binfile}.d + } + file delete -force -- $dir + file mkdir $dir + + if {$interp == ""} { + set interp_system [section_get $binfile .interp] + set interp ${dir}/[file tail $interp_system] + file_copy $interp_system $interp + } + + set dests {} + foreach {trash abspath} $libs { + set dest "$dir/[file tail $abspath]" + file_copy $abspath $dest + lappend dests $dest + } + + # Do not lappend it so that "-rpath $dir" overrides any possible "-rpath"s + # specified by the caller to be able to link it for ldd" above. + set options [linsert $options 0 "additional_flags=-Wl,--dynamic-linker,$interp,-rpath,$dir"] + + if {[build_executable $testname $executable $sources $options] == -1} { + return "" + } + + set prelink_args "--dynamic-linker=$interp --ld-library-path=$dir $binfile $interp [concat $dests]" + return $prelink_args +} + +# Unprelink ARG. Reported test name can be specified by NAME. Return non-zero +# on success, zero on failure. + +proc prelink_no {arg {name {}}} { + if {$name == ""} { + set name [file tail $arg] + } + set test "unprelink $name" + set command "exec /usr/sbin/prelink -uN $arg" + verbose -log "command is $command" + set result [catch $command output] + verbose -log "result is $result" + verbose -log "output is $output" + if {$result == 0 && $output == ""} { + verbose -log "$name has been now unprelinked" + set command "exec /usr/sbin/prelink -uN $arg" + verbose -log "command is $command" + set result [catch $command output] + verbose -log "result is $result" + verbose -log "output is $output" + } + # Last line does miss the trailing \n. There can be multiple such messages + # as ARG may list multiple files. + if {$result == 1 && [regexp {^(/usr/sbin/prelink[^\r\n]*: [^ ]* does not have .gnu.prelink_undo section\n?)*$} $output]} { + pass $test + return 1 + } else { + fail $test + return 0 + } +} + +# Prelink ARG. Reported test name can be specified by NAME. Return non-zero +# on success, zero on failure. + +proc prelink_yes {arg {name ""}} { + if {$name == ""} { + set name [file tail $arg] + } + + # Try to unprelink it first so that, if it has been already prelinked + # before, we get a different address now, making the new result unaffected + # by any previous prelinking. + prelink_no $arg "$name pre-unprelink" + + set test "prelink $name" + + # `--no-exec-shield' is for i386, where prelink in the exec-shield mode is + # forced to push all the libraries tight together, in order to fit into + # the first two memory areas (either the ASCII Shield area or at least + # below the executable). If the prelink was performed in exec-shield + # mode, prelink could have no choice on how to randomize the single new + # unprelinked library address without wasting space in the first one/two + # memory areas. In such case prelink could place $ARG repeatedly at the + # same place and we could have false prelink results on + # gdb.base/prelink.exp and others. To prevent this from happening, we use + # the --no-exec-shield switch. This may have some consequences in terms + # of security, but we do not care in our case. + + set command "exec /usr/sbin/prelink -qNR --no-exec-shield $arg" + + verbose -log "command is $command" + set result [catch $command output] + verbose -log "result is $result" + verbose -log "output is $output" + if {$result == 0 && $output == ""} { + pass $test + return 1 + } elseif {$result == 1 \ + && [string match -nocase "*: Not enough room to add .dynamic entry" $output]} { + # Linker should have reserved some entries for prelink. + xfail $test + return 0 + } else { + fail $test + return 0 + } +} |