gdb/testsuite/
authorJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 5 Jul 2010 18:01:53 +0000 (18:01 +0000)
committerJan Kratochvil <jan.kratochvil@redhat.com>
Mon, 5 Jul 2010 18:01:53 +0000 (18:01 +0000)
* 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.

gdb/testsuite/ChangeLog
gdb/testsuite/gdb.base/attach-pie-misread.exp
gdb/testsuite/gdb.base/break-interp.exp
gdb/testsuite/gdb.base/prelink.exp
gdb/testsuite/lib/prelink-support.exp [new file with mode: 0644]

index 682dc9a..8d52e40 100644 (file)
@@ -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
index 334272b..10e4936 100644 (file)
@@ -18,13 +18,15 @@ if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_test
     continue
 }
 
+load_lib prelink-support.exp
+
 set test "attach-pie-misread"
 set srcfile ${test}.c
 set genfile ${objdir}/${subdir}/${test}-gen.h
 set executable ${test}
 set binfile ${objdir}/${subdir}/${executable}
 
-if {[build_executable ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie"]] == -1} {
+if {[build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie"]] == ""} {
     return -1
 }
 
@@ -94,7 +96,8 @@ if {$result == 0} {
     fail $test
 }
 
-if {[build_executable ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie -DGEN=\"$genfile\""]] == -1} {
+set prelink_args [build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie -DGEN=\"$genfile\""]]
+if {$prelink_args == ""} {
     return -1
 }
 
@@ -104,20 +107,8 @@ file delete -- $genfile
 set phdr [read_phdr $binfile "readelf rebuilt with stub_size"]
 set dynamic_vaddr_prelinkno [lindex $phdr 0]
 
-set command "exec /usr/sbin/prelink -q -N --no-exec-shield -R $binfile"
-verbose -log "command is $command"
-set result [catch $command output]
-verbose -log "result is $result"
-verbose -log "output is $output"
-
-set test "prelink -R"
-if {$result == 0 && $output == ""} {
-    pass $test
-} elseif {$result == 1 && [regexp {^(couldn't execute "/usr/sbin/prelink[^\r\n]*": no such file or directory\n?)*$} $output]} {
-    untested attach-pie-misread.exp
+if ![prelink_yes $prelink_args] {
     return -1
-} else {
-    fail $test
 }
 
 set phdr [read_phdr $binfile "readelf with prelink -R"]
@@ -168,6 +159,10 @@ foreach align_mult {1 2} {
     set shifted_offset [format 0x%x [expr "$first_offset - $align_mult * $align_max"]]
     verbose -log "shifted_offset is $shifted_offset"
 
+    # For normal prelink (prelink_yes call), we need to supply $prelink_args.
+    # For the prelink `-r' option below, $prelink_args is not required.
+    # Moreover, if it was used, the problem would not longer be reproducible
+    # as the libraries would also get relocated.
     set command "exec /usr/sbin/prelink -q -N --no-exec-shield -r $shifted_offset $binfile"
     verbose -log "command is $command"
     set result [catch $command output]
index 8cd20d4..a3b9c20 100644 (file)
@@ -18,6 +18,8 @@ if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_test
     continue
 }
 
+load_lib prelink-support.exp
+
 set test "break-interp"
 set binprefix ${objdir}/${subdir}/${test}
 # Only to get the $interp_system name.
@@ -31,8 +33,7 @@ if [get_compiler_info ${binfile_lib}] {
     return -1
 }
 
-# Use -soname so that it is listed with " => " by ldd and this testcase makes
-# a copy of ${binfile_lib} for each prelink variant.
+# Use -soname so that the new library gets copied by build_executable_own_libs.
 
 if {[gdb_compile_shlib ${srcdir}/${subdir}/${srcfile_lib} ${binfile_lib} [list debug additional_flags=-Wl,-soname,${test}.so]] != ""} {
     return -1
@@ -42,38 +43,6 @@ if {[build_executable ${test}.exp $binfile_test ${srcfile_test} {}] == -1} {
     return -1
 }
 
-# Return the interpreter filename string.
-# Return "" if no interpreter was found.
-proc section_get {exec section} {
-    global objdir
-    global subdir
-    set tmp "${objdir}/${subdir}/break-interp.interp"
-    set objcopy_program [transform objcopy]
-
-    set command "exec $objcopy_program -O binary --set-section-flags $section=A --change-section-address $section=0 -j $section $exec $tmp"
-    verbose -log "command is $command"
-    set result [catch $command output]
-    verbose -log "result is $result"
-    verbose -log "output is $output"
-    if {$result == 1} {
-       return ""
-    }
-    set fi [open $tmp]
-    fconfigure $fi -translation binary
-    set data [read $fi]
-    close $fi
-    #file delete $tmp
-    # .interp has size $len + 1 but .gnu_debuglink contains garbage after \000.
-    set len [string first \000 $data]
-    if {$len < 0} {
-       verbose -log "section $section not found"
-       return ""
-    }
-    set retval [string range $data 0 [expr $len - 1]]
-    verbose -log "section $section is <$retval>"
-    return $retval
-}
-
 # Note: The separate debug info file content build-id/crc32 are not verified
 # contrary to the GDB search algorithm skipping non-matching ones.
 proc system_debug_get {exec} {
@@ -117,104 +86,12 @@ set interp_system [section_get ${objdir}/${subdir}/$binfile_test .interp]
 set interp_system_debug [system_debug_get $interp_system]
 verbose -log "$interp_system has debug $interp_system_debug"
 
-proc prelinkNO_run {arg} {
-    set command "exec /usr/sbin/prelink -uN $arg"
-    verbose -log "command is $command"
-    set result [catch $command output]
-    verbose -log "result is $result"
-    verbose -log "output is $output"
-    return [list $result $output]
-}
-
-proc prelinkNO {arg {name {}}} {
-    if {$name == ""} {
-       set name [file tail $arg]
-    }
-    set test "unprelink $name"
-    set run [prelinkNO_run $arg]
-    set result [lindex $run 0]
-    set output [lindex $run 1]
-    if {$result == 0 && $output == ""} {
-       verbose -log "$name has been now unprelinked"
-       set run [prelinkNO_run $arg]
-       set result [lindex $run 0]
-       set output [lindex $run 1]
-    }
-    # Last line does miss the trailing \n.
-    if {$result == 1 && [regexp {^(/usr/sbin/prelink[^\r\n]*: [^ ]* does not have .gnu.prelink_undo section\n?)*$} $output]} {
-       pass $test
-       return 1
-    } else {
-       fail $test
-       return 0
-    }
+proc prelinkNO {arg {name ""}} {
+    return [prelink_no $arg $name]
 }
 
 proc prelinkYES {arg {name ""}} {
-    if {$name == ""} {
-       set name [file tail $arg]
-    }
-
-    # Try to unprelink it first so that if it has been already prelinked before
-    # we get different address now and the result is not affected by the
-    # previous $arg state..
-    prelinkNO $arg "$name pre-unprelink"
-
-    set test "prelink $name"
-    set command "exec /usr/sbin/prelink -qNR --no-exec-shield $arg"
-    verbose -log "command is $command"
-    set result [catch $command output]
-    verbose -log "result is $result"
-    verbose -log "output is $output"
-    if {$result == 0 && $output == ""} {
-       pass $test
-       return 1
-    } elseif {$result == 1 \
-             && [string match -nocase "*: Not enough room to add .dynamic entry" $output]} {
-       # Linker should have reserved some entries for prelink.
-       xfail $test
-       return 0
-    } else {
-       fail $test
-       return 0
-    }
-}
-
-# Resolve symlinks.
-proc symlink_resolve {file} {
-    set loop 0
-    while {[file type $file] == "link"} {
-       set target [file readlink $file]
-       if {[file pathtype $target] == "relative"} {
-           set src2 [file dirname $file]/$target
-       } else {
-           set src2 $target
-       }
-       verbose -log "Resolved symlink $file targetting $target as $src2"
-       set file $src2
-
-       set loop [expr $loop + 1]
-       if {$loop > 30} {
-           fail "Looping symlink resolution for $file"
-           return ""
-       }
-    }
-    return $file
-}
-
-proc copy {src dest} {
-    set src [symlink_resolve $src]
-    # Test name would contain build-id hash for symlink-unresolved $src.
-    set test "copy [file tail $src] to [file tail $dest]"
-    set command "file copy -force $src $dest"
-    verbose -log "command is $command"
-    if [catch $command] {
-       fail $test
-       return 0
-    } else {
-       pass $test
-       return 1
-    }
+    return [prelink_yes $arg $name]
 }
 
 proc strip_debug {dest} {
@@ -425,8 +302,8 @@ proc test_attach {file displacement {relink_args ""}} {
            # Formerly this test was testing only prelinking of $EXEC.  As the
            # prelink command automatically prelinks all of $EXEC's libraries,
            # even $INTERP got prelinked.  Therefore, we formerly had to
-           # `[copy $interp_saved $interp]' to make $INTERP not affected by
-           # this prelinking of $EXEC.
+           # `[file_copy $interp_saved $interp]' to make $INTERP not affected
+           # by this prelinking of $EXEC.
            #
            # But now we need to test even prelinking of $INTERP.  We could
            # create a separate test to test just the $INTERP prelinking.  For
@@ -439,7 +316,7 @@ proc test_attach {file displacement {relink_args ""}} {
                test_attach_gdb $exec $pid $displacement "attach-relink$relink"
            }
        }
-       copy $interp_saved $interp
+       file_copy $interp_saved $interp
     }
 
     remote_exec host "kill -9 $pid"
@@ -582,7 +459,7 @@ foreach ldprelink {NO YES} {
        lappend pf_prefix "$ldname:"
 
        if {$ldsepdebug == "NO"} {
-           copy $interp_system $interp
+           file_copy $interp_system $interp
            # Never call strip-debug before unprelink:
            # prelink: ...: Section .note.gnu.build-id created after prelinking
            if ![prelinkNO $interp] {
@@ -590,10 +467,10 @@ foreach ldprelink {NO YES} {
            }
            strip_debug $interp
        } elseif {$ldsepdebug == "IN" && $interp_system_debug == ""} {
-           copy $interp_system $interp
+           file_copy $interp_system $interp
        } elseif {$ldsepdebug == "IN" && $interp_system_debug != ""} {
-           copy $interp_system $interp
-           copy $interp_system_debug "${interp}.debug"
+           file_copy $interp_system $interp
+           file_copy $interp_system_debug "${interp}.debug"
            # eu-unstrip: DWARF data in '...' not adjusted for prelinking bias; consider prelink -u
            if {![prelinkNO $interp] || ![prelinkNO "${interp}.debug"]} {
                continue
@@ -609,15 +486,15 @@ foreach ldprelink {NO YES} {
                pass $test
            }
        } elseif {$ldsepdebug == "SEP" && $interp_system_debug == ""} {
-           copy $interp_system $interp
+           file_copy $interp_system $interp
            # eu-unstrip: DWARF data in '...' not adjusted for prelinking bias; consider prelink -u
            if ![prelinkNO $interp] {
                continue
            }
            gdb_gnu_strip_debug $interp
        } elseif {$ldsepdebug == "SEP" && $interp_system_debug != ""} {
-           copy $interp_system $interp
-           copy $interp_system_debug "${interp}.debug"
+           file_copy $interp_system $interp
+           file_copy $interp_system_debug "${interp}.debug"
        }
 
        if {$ldsepdebug == "SEP"} {
@@ -638,7 +515,7 @@ foreach ldprelink {NO YES} {
        }
        test_ld $interp 0 [expr {$ldsepdebug == "NO"}] $displacement
 
-       if ![copy $interp $interp_saved] {
+       if ![file_copy $interp $interp_saved] {
            continue
        }
        set old_binprefix $pf_prefix
@@ -656,64 +533,28 @@ foreach ldprelink {NO YES} {
 
                    set binname "BINprelink${binprelink}debug${binsepdebug}pie${binpie}"
                    set exec $binprefix-$binname
-                   set dir ${exec}.d
 
                    set pf_prefix $old_binprefix
                    lappend pf_prefix "$binname:"
 
-                   set opts "additional_flags=-Wl,--dynamic-linker,$interp,-rpath,$dir"
-                   lappend opts "additional_flags=-Wl,$binfile_lib,-rpath,[file dirname $binfile_lib]"
+                   set opts "additional_flags=-Wl,$binfile_lib,-rpath,[file dirname $binfile_lib]"
                    if {$binsepdebug != "NO"} {
                        lappend opts {debug}
                    }
                    if {$binpie != "NO"} {
                        lappend opts {additional_flags=-fPIE -pie}
                    }
-                   if {[build_executable ${test}.exp [file tail $exec] $srcfile $opts] == -1} {
+
+                   set dir ${exec}.d
+                   set relink_args [build_executable_own_libs ${test}.exp [file tail $exec] $srcfile $opts $interp $dir]
+                   if {$relink_args == ""} {
                        continue;
                    }
+
                    if {$binsepdebug == "SEP"} {
                        gdb_gnu_strip_debug $exec
                    }
 
-                   # Supply a self-sufficent directory $dir with the required
-                   # libraries.  To make an executable properly prelinked all
-                   # its dependencies on libraries must be also prelinked.  If
-                   # some of the system libraries is currently not prelinked
-                   # we have no right to prelink (modify it) at its current
-                   # system place.
-
-                   file delete -force $dir
-                   file mkdir $dir
-
-                   set command "ldd $exec"
-                   set test "ldd [file tail $exec]"
-                   set result [catch "exec $command" output]
-                   verbose -log "result of $command is $result"
-                   verbose -log "output of $command is $output"
-                   if {$result != 0 || $output == ""} {
-                       fail $test
-                   } else {
-                       pass $test
-                   }
-
-                   # gdb testsuite will put there also needless -lm.
-                   set test "$test output contains libc"
-                   set libc [regexp -all -inline -line {^.* => (/[^ ]+).*$} $output]
-                   if {[llength $libc] == 0} {
-                       fail $test
-                   } else {
-                       pass $test
-                   }
-
-                   set dests {}
-                   for {set i 1} {$i < [llength $libc]} {incr i 2} {
-                       set abspath [lindex $libc $i]
-                       set dest "$dir/[file tail $abspath]"
-                       copy $abspath $dest
-                       lappend dests $dest
-                   }
-
                    if {$binpie == "NO"} {
                        set displacement "NONE"
                    } elseif {$binprelink == "NO"} {
@@ -722,9 +563,8 @@ foreach ldprelink {NO YES} {
                        set displacement "ZERO"
                    }
 
-                   set relink_args "--dynamic-linker=$interp --ld-library-path=$dir $exec $interp [concat $dests]"
                    if {[prelink$binprelink $relink_args [file tail $exec]]
-                       && [copy $interp_saved $interp]} {
+                       && [file_copy $interp_saved $interp]} {
                        if {$binpie != "ATTACH"} {
                            test_ld $exec 1 [expr {$binsepdebug == "NO"}] $displacement
                        } else {
index 1803a80..8931c9f 100644 (file)
@@ -23,8 +23,7 @@ if $tracelevel then {
        }
 
 
-# are we on a target board
-if ![isnative] then {
+if { ![isnative] || [is_remote host] || [skip_shlib_tests]} {
     return
 }
 
@@ -36,32 +35,31 @@ if {$gcc_compiled == 0} {
     return -1
 }
 
+load_lib prelink-support.exp
+
 set testfile "prelink"
 
 set libsrcfile ${testfile}-lib.c
 set libfile ${objdir}/${subdir}/${testfile}.so
-if { [gdb_compile "${srcdir}/${subdir}/${libsrcfile}" "${libfile}" executable [list debug "additional_flags=-fpic -shared -nodefaultlibs"]] != ""} {
+
+# Use -soname so that the new library gets copied by build_executable_own_libs.
+
+if { [gdb_compile_shlib "${srcdir}/${subdir}/${libsrcfile}" "${libfile}" [list debug "additional_flags=-Wl,-soname,[file tail ${libfile}]"]] != ""} {
     # If creating the shared library fails, maybe we don't have the right tools
     return -1
 }
 
-# `--no-exec-shield' is for i386 where prelink in the exec-shield mode is
-# forced to push all the libraries tight together to fit into the first two
-# memory areas (either the ASCII Shield area or at least below the executable).
-# In this case its -R option cannot be applied and we falsely FAIL here as if
-# the system is already prelinked prelink has no choice how to randomize the
-# single new unprelinked library address without wasting the first one/two
-# memory areas.  We do not care of the efficiency of loading such resulting
-# exec-shield unfriendly prelinked library.
-if {[catch "system \"prelink -qNR --no-exec-shield ${libfile}\""] != 0} {
-    # Maybe we don't have prelink.
+set srcfile ${testfile}.c
+set executable ${testfile}t
+set binfile ${objdir}/${subdir}/${executable}
+set prelink_args [build_executable_own_libs ${testfile}.exp $executable $srcfile [list debug "additional_flags=-Wl,${libfile},-rpath,[file dirname ${libfile}]"]]
+if {$prelink_args == ""} {
     return -1
 }
 
-set srcfile ${testfile}.c
-set binfile ${objdir}/${subdir}/${testfile}t
-if { [gdb_compile "${srcdir}/${subdir}/${srcfile} ${libfile}" "${binfile}" executable [list debug "additional_flags=-Wl,-rpath,${objdir}/${subdir}"]] != ""} {
-    return -1;
+if ![prelink_yes $prelink_args] {
+    # Maybe we don't have prelink.
+    return -1
 }
 
 set found 0
@@ -94,20 +92,16 @@ if { $found == 0  } {
     return 0
 }
 
-if {[catch "system \"prelink -uN ${libfile}\""] != 0} {
-    untested "${testfile}.so was not prelinked, maybe system libraries are not prelinked?"
-    return 0
+# Relink $libfile to a different address.
+if ![prelink_yes $prelink_args] {
+    return -1
 }
-catch "system \"prelink -qNR --no-exec-shield ${libfile}\""
 
 # Start with a fresh gdb
 
-gdb_exit
-gdb_start
-gdb_reinitialize_dir $srcdir/$subdir
-gdb_load ${binfile}
+clean_restart $executable
 
 # Print the "adjusting expectations" message.
 gdb_test_no_output "set verbose on"
 
-gdb_test "core-file $objdir/$subdir/prelink.core" {Using PIC \(Position Independent Code\) prelink displacement.*} "prelink"
+gdb_test "core-file $objdir/$subdir/prelink.core" "Using PIC \\(Position Independent Code\\) prelink displacement 0x\[^0\]\[0-9a-f\]* for \[^\r\n\]*[file tail ${libfile}].*" "seen displacement message"
diff --git a/gdb/testsuite/lib/prelink-support.exp b/gdb/testsuite/lib/prelink-support.exp
new file mode 100644 (file)
index 0000000..6d9e909
--- /dev/null
@@ -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
+    }
+}