public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [patch 4/6] testsuite: Unify to lib/prelink-support.exp
@ 2010-03-29 16:18 Jan Kratochvil
  2010-06-09 15:09 ` ping: " Jan Kratochvil
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2010-03-29 16:18 UTC (permalink / raw)
  To: gdb-patches

Hi,

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  <jan.kratochvil@redhat.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.

--- 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} {
@@ -416,7 +299,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.
@@ -425,7 +308,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"
@@ -568,7 +451,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] {
@@ -576,10 +459,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
@@ -595,15 +478,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"} {
@@ -624,7 +507,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
@@ -642,22 +525,25 @@ 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
 			# Just a sanity check.  As gdb_gnu_strip_debug uses the
@@ -666,44 +552,6 @@ foreach ldprelink {NO YES} {
 			file delete "$exec.debug"
 		    }
 
-		    # 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"} {
@@ -712,9 +560,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
@@ -25,8 +25,7 @@ if $tracelevel then {
 set prms_id 0
 set bug_id 0
 
-# are we on a target board
-if ![isnative] then {
+if { ![isnative] || [is_remote host] || [skip_shlib_tests]} {
     return
 }
 
@@ -38,32 +37,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
@@ -96,20 +94,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 "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 <http://www.gnu.org/licenses/>.
+
+# 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
+    }
+}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* ping: [patch 4/6] testsuite: Unify to lib/prelink-support.exp
  2010-03-29 16:18 [patch 4/6] testsuite: Unify to lib/prelink-support.exp Jan Kratochvil
@ 2010-06-09 15:09 ` Jan Kratochvil
  2010-06-29 21:56   ` Joel Brobecker
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2010-06-09 15:09 UTC (permalink / raw)
  To: gdb-patches

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  <jan.kratochvil@redhat.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.

--- 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 <http://www.gnu.org/licenses/>.
+
+# 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
+    }
+}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ping: [patch 4/6] testsuite: Unify to lib/prelink-support.exp
  2010-06-09 15:09 ` ping: " Jan Kratochvil
@ 2010-06-29 21:56   ` Joel Brobecker
  2010-07-04 10:18     ` Jan Kratochvil
  0 siblings, 1 reply; 6+ messages in thread
From: Joel Brobecker @ 2010-06-29 21:56 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

> gdb/testsuite/
> 2010-03-29  Jan Kratochvil  <jan.kratochvil@redhat.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.

This is OK, but I think it could have been split into smaller patches,
and that might have made the review process a little easier (this patch
took me 90 mins to review).

Just some editorial comments. I realize some of the comments were already
there, but since I'm looking at them, I thought I throw the suggestion in
now, rather than never.

> +    # $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"

Sorry, I don't understand what you are trying to explain here.

> +		    # This $dir is assumed in build_executable_own_libs.
> +		    set dir ${exec}.d

I wonder if this should just be passed as an argument to
build_executable_own_libs to avoid this assumption (just a thought).

> +# Use -soname so that it is listed with " => " by ldd and this testcase makes
> +# a copy of ${libfile} for each prelink variant.

I think it's useful to explain why it needs to be listed with "=>" by ldd.
Also, I think that the fact that the testcase makes a copy of the library
for each prelink variand is unrelated to the -soname trick, is that correct?
If it is, then we need to make it clear, somehow. Right now, having the
two ideas in the same sentence and and "and" seems to indicate that they
are in fact related.

> +# 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".

IMO, the lines are two long. I don't exactly know what the standard max
length is, but it should be 78 or less.

Small corrections: "0-byte-terminated" or maybe simpler "nul-terminated".
Also, English -> "This function" for section*s*...

> +# 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.

Long lines... Also, suggest:

  # 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.

> +# 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'.

Some minor corrections (can you also spot me for errors, in particular
for the return value which wasn't documented in your patch?):

# 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 `${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.

> +    # 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..

Missing commas:

    # 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.


> +    # `--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.

IMO: The sentences go on for too long without punctuation.   I suggest:

# `--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,
# we can have false prelink failures when the system is already prelinked
# (due to the use of the -R switch), because prelink has no choice on how
# to randomize the single new unprelinked library address without wasting
# the first one/two memory areas.  To prevent this from happening, we use
# the --no-exec-shield switch.  This may have some consequences in terms
# of loading performance, but we do not care in our case.
# 
-- 
Joel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ping: [patch 4/6] testsuite: Unify to lib/prelink-support.exp
  2010-06-29 21:56   ` Joel Brobecker
@ 2010-07-04 10:18     ` Jan Kratochvil
  2010-07-05 17:35       ` Joel Brobecker
  0 siblings, 1 reply; 6+ messages in thread
From: Jan Kratochvil @ 2010-07-04 10:18 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On Tue, 29 Jun 2010 23:55:58 +0200, Joel Brobecker wrote:
> This is OK, but I think it could have been split into smaller patches,
> and that might have made the review process a little easier

OK.


> > +    # $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"
> 
> Sorry, I don't understand what you are trying to explain here.

$prelink_args are:
  set prelink_args "--dynamic-linker=$interp --ld-library-path=$dir $binfile $interp [concat $dests]"

What about this?
    # 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 would be 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"


> > +		    # This $dir is assumed in build_executable_own_libs.
> > +		    set dir ${exec}.d
> 
> I wonder if this should just be passed as an argument to
> build_executable_own_libs to avoid this assumption (just a thought).

Great idea, done.  I was trying before to make it a return value from
build_executable_own_libs which is not easy enough with TCL missing
references/pointers/list-assignments.


> > +# Use -soname so that it is listed with " => " by ldd and this testcase makes
> > +# a copy of ${libfile} for each prelink variant.
> 
> I think it's useful to explain why it needs to be listed with "=>" by ldd.
> Also, I think that the fact that the testcase makes a copy of the library
> for each prelink variand is unrelated to the -soname trick, is that correct?
> If it is, then we need to make it clear, somehow. Right now, having the
> two ideas in the same sentence and and "and" seems to indicate that they
> are in fact related.

They are in fact related.

	: | gcc -shared -fPIC -Wall -o lib1.so -x c - -Wl,-soname,lib1.so
vs.
	: | gcc -shared -fPIC -Wall -o lib1.so -x c -
and
	echo 'int main(void){return 0;}'|gcc -o 1 -Wall ./lib1.so -x c -;LD_LIBRARY_PATH=. ldd ./1
produce
	linux-vdso.so.1 =>  (0x00007fffd7dff000)
	lib1.so => ./lib1.so (0x00007f9ec1564000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003decc00000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003dec800000)
vs.
	linux-vdso.so.1 =>  (0x00007fff2b9ff000)
	./lib1.so (0x00007f55f330a000)
	libc.so.6 => /lib64/libc.so.6 (0x0000003decc00000)
	/lib64/ld-linux-x86-64.so.2 (0x0000003dec800000)

Used:
	# Use -soname so that the new library gets copied by build_executable_own_libs.
+ for build_executable_own_libs:
	# Function recognizes only libraries listed by `ldd' after its ` => ' separator.
	# That means $INTERP and any libraries not using -Wl,-soname,NAME.so are not
	# copied.


> > +# 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".
> 
> IMO, the lines are two long. I don't exactly know what the standard max
> length is, but it should be 78 or less.

Checked GNU Coding Standards does not talk about it but its GNU indent
parameters do not specify -lc which defaults to 78 so you are right.
I had to update my config, thanks.


> Some minor corrections (can you also spot me for errors, in particular
> for the return value which wasn't documented in your patch?):

Text looks correct to me.


> IMO: The sentences go on for too long without punctuation.   I suggest:
> 
> # `--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,
> # we can have false prelink failures when the system is already prelinked
> # (due to the use of the -R switch), because prelink has no choice on how
> # to randomize the single new unprelinked library address without wasting
> # the first one/two memory areas.  To prevent this from happening, we use
> # the --no-exec-shield switch.  This may have some consequences in terms
> # of loading performance, but we do not care in our case.

With such review of the text I had to do some additional ones, used:

    # `--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.


Thanks,
Jan


gdb/testsuite/
2010-07-04  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.

--- 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 would be 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]
--- 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 prelinks automatically even all $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 {
--- 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"
--- /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
+    }
+}

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ping: [patch 4/6] testsuite: Unify to lib/prelink-support.exp
  2010-07-04 10:18     ` Jan Kratochvil
@ 2010-07-05 17:35       ` Joel Brobecker
  2010-07-05 18:11         ` Jan Kratochvil
  0 siblings, 1 reply; 6+ messages in thread
From: Joel Brobecker @ 2010-07-05 17:35 UTC (permalink / raw)
  To: Jan Kratochvil; +Cc: gdb-patches

> gdb/testsuite/
> 2010-07-04  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.

OK to commit.

> +    # 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 would be used the problem would not longer be reproducible
> +    # as the libraries would also get relocated.

Minor editorial changes (mostly adding comas)...

    # 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.

-- 
Joel

^ permalink raw reply	[flat|nested] 6+ messages in thread

* Re: ping: [patch 4/6] testsuite: Unify to lib/prelink-support.exp
  2010-07-05 17:35       ` Joel Brobecker
@ 2010-07-05 18:11         ` Jan Kratochvil
  0 siblings, 0 replies; 6+ messages in thread
From: Jan Kratochvil @ 2010-07-05 18:11 UTC (permalink / raw)
  To: Joel Brobecker; +Cc: gdb-patches

On Mon, 05 Jul 2010 19:34:52 +0200, Joel Brobecker wrote:
> OK to commit.

Checked-in.


Thanks,
Jan


http://sourceware.org/ml/gdb-cvs/2010-07/msg00027.html

--- src/gdb/testsuite/ChangeLog	2010/07/05 18:00:39	1.2373
+++ src/gdb/testsuite/ChangeLog	2010/07/05 18:01:53	1.2374
@@ -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
--- src/gdb/testsuite/gdb.base/attach-pie-misread.exp	2010/07/05 18:00:40	1.1
+++ src/gdb/testsuite/gdb.base/attach-pie-misread.exp	2010/07/05 18:01:53	1.2
@@ -18,13 +18,15 @@
     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 @@
     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 @@
 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 @@
     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]
--- src/gdb/testsuite/gdb.base/break-interp.exp	2010/07/05 18:00:40	1.16
+++ src/gdb/testsuite/gdb.base/break-interp.exp	2010/07/05 18:01:53	1.17
@@ -18,6 +18,8 @@
     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 @@
     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 @@
     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_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 @@
 	    # 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 @@
 		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 @@
 	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 @@
 	    }
 	    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 @@
 		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 @@
 	}
 	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 @@
 
 		    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 @@
 			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 {
--- src/gdb/testsuite/gdb.base/prelink.exp	2010/06/01 21:29:21	1.14
+++ src/gdb/testsuite/gdb.base/prelink.exp	2010/07/05 18:01:53	1.15
@@ -23,8 +23,7 @@
 	}
 
 
-# are we on a target board
-if ![isnative] then {
+if { ![isnative] || [is_remote host] || [skip_shlib_tests]} {
     return
 }
 
@@ -36,32 +35,31 @@
     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 @@
     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"
--- src/gdb/testsuite/lib/prelink-support.exp
+++ src/gdb/testsuite/lib/prelink-support.exp	2010-07-05 18:11:02.600467000 +0000
@@ -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
+    }
+}

^ permalink raw reply	[flat|nested] 6+ messages in thread

end of thread, other threads:[~2010-07-05 18:11 UTC | newest]

Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-29 16:18 [patch 4/6] testsuite: Unify to lib/prelink-support.exp Jan Kratochvil
2010-06-09 15:09 ` ping: " Jan Kratochvil
2010-06-29 21:56   ` Joel Brobecker
2010-07-04 10:18     ` Jan Kratochvil
2010-07-05 17:35       ` Joel Brobecker
2010-07-05 18:11         ` Jan Kratochvil

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).