From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (qmail 12144 invoked by alias); 9 Jun 2010 15:09:47 -0000 Received: (qmail 12105 invoked by uid 22791); 9 Jun 2010 15:09:41 -0000 X-SWARE-Spam-Status: No, hits=-4.8 required=5.0 tests=AWL,BAYES_20,RCVD_IN_DNSWL_HI,SPF_HELO_PASS,TW_BJ,TW_JC,T_RP_MATCHES_RCVD X-Spam-Check-By: sourceware.org Received: from mx1.redhat.com (HELO mx1.redhat.com) (209.132.183.28) by sourceware.org (qpsmtpd/0.43rc1) with ESMTP; Wed, 09 Jun 2010 15:09:29 +0000 Received: from int-mx03.intmail.prod.int.phx2.redhat.com (int-mx03.intmail.prod.int.phx2.redhat.com [10.5.11.16]) by mx1.redhat.com (8.13.8/8.13.8) with ESMTP id o59F9RDt008967 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 9 Jun 2010 11:09:27 -0400 Received: from host0.dyn.jankratochvil.net (ovpn01.gateway.prod.ext.phx2.redhat.com [10.5.9.1]) by int-mx03.intmail.prod.int.phx2.redhat.com (8.13.8/8.13.8) with ESMTP id o59F9Omb009375 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=NO) for ; Wed, 9 Jun 2010 11:09:26 -0400 Received: from host0.dyn.jankratochvil.net (localhost [127.0.0.1]) by host0.dyn.jankratochvil.net (8.14.4/8.14.4) with ESMTP id o59F9O6w007809 for ; Wed, 9 Jun 2010 17:09:24 +0200 Received: (from jkratoch@localhost) by host0.dyn.jankratochvil.net (8.14.4/8.14.4/Submit) id o59F9N4n007808 for gdb-patches@sourceware.org; Wed, 9 Jun 2010 17:09:23 +0200 Date: Wed, 09 Jun 2010 15:09:00 -0000 From: Jan Kratochvil To: gdb-patches@sourceware.org Subject: ping: [patch 4/6] testsuite: Unify to lib/prelink-support.exp Message-ID: <20100609150923.GD7183@host0.dyn.jankratochvil.net> References: <20100329161753.GC2940@host0.dyn.jankratochvil.net> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20100329161753.GC2940@host0.dyn.jankratochvil.net> User-Agent: Mutt/1.5.20 (2009-12-10) X-IsSubscribed: yes Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org X-SW-Source: 2010-06/txt/msg00234.txt.bz2 Hi, originally posted as: [patch 4/6] testsuite: Unify to lib/prelink-support.exp http://sourceware.org/ml/gdb-patches/2010-03/msg01002.html Rediffed only. ------------------------------------------------------------------------------ when there are now two PIE/prelink related testcases (gdb.base/break-interp.exp and gdb.base/attach-pie-misread.exp) there was some code duplicity. Unified it. The gdb.base/prelink.exp part fixes a problem that default_target_compile (either from dejagnu or from lib/ada.exp) currently always adds "-lm" making the testcase dependent on whether the system libraries are already prelinked and being UNTESTED otherwise producing: prelink: Could not set /lib64/libm-2.11.1.so owner or mode: Operation not permitted Going to post an alternative fix of this problem for gdb.base/prelink.exp when I had it accidentally already coded but I would prefer the variant attached below - as it uses the same code as existing gdb.base/break-interp.exp and gdb.base/attach-pie-misread.exp anyway). Moreover one can also follow that testcases should represent real world cases where -nodefaultlibs is not in use (OTOH the second opinion is that testcases should test only the absolutely minimal artifically reproduced problem which would more match the use of -nodefaultlibs). gdb.base/prelink.exp [is_remote host] || [skip_shlib_tests] restrictions are new but the code already has violated such cases. No regressions on {x86_64,x86_64-m32,i686}-fedora12-linux-gnu for the whole patch series together. Thanks, Jan gdb/testsuite/ 2010-03-29 Jan Kratochvil * 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. --- 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,8 @@ 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" + # $prelink_args are not need for "-r". Moreover it would relocated all the + # copied libraries making the problem no longer reproducible. 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] --- 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. @@ -42,38 +44,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,99 +87,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 - } 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} { @@ -417,7 +300,7 @@ proc test_attach {file displacement {relink_args ""}} { global exec interp_saved interp foreach relink {YES NO} { - # It would be more correct to also [copy $interp_saved $interp] + # It would be more correct to also [file_copy $interp_saved $interp] # here to really test just different prelink of $exec. # But we would need a separate test for different prelink of ld.so # where a bug occured. It is now all merged into this single test. @@ -426,7 +309,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" @@ -569,7 +452,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] { @@ -577,10 +460,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 @@ -596,15 +479,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"} { @@ -625,7 +508,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 @@ -643,64 +526,29 @@ 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 relink_args [build_executable_own_libs ${test}.exp [file tail $exec] $srcfile $opts $interp] + if {$relink_args == ""} { continue; } + # This $dir is assumed in build_executable_own_libs. + set dir ${exec}.d + 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"} { @@ -709,9 +557,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 { --- 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 it is listed with " => " by ldd and this testcase makes +# a copy of ${libfile} for each prelink variant. +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" --- /dev/null +++ b/gdb/testsuite/lib/prelink-support.exp @@ -0,0 +1,226 @@ +# 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 . + +# Return 0 byte terminated string read from section SECTION of EXEC. Return "" +# if no such section or 0 byte terminated string was found. Function is useful +# for section ".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 of SRC. Protect script being aborted +# if the copy fails. Return non-zero on success, zero on failure. + +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. The reason is that +# making an executable properly prelinked requires all its dynamically linked +# libraries must be also prelinked. If some of the system libraries is +# currently not prelinked we may have no right to prelink (modify it) at its +# current system place. Parameter INTERP may specify different ld.so to use +# than the default system one. Libraries are copied into directory +# `${objdir}/${subdir}/${executable}.d'. + +proc build_executable_own_libs {testname executable sources options {interp ""}} { + 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 + } + + 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 different address now and the result is not affected by the + # previous $arg state.. + 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 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. + 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 + } else { + fail $test + return 0 + } +}