old-cross-binutils/gdb/testsuite/gdb.base/execl-update-breakpoints.exp
Andreas Arnez fdb09caf23 execl-update-breakpoints.exp: Move whole segment instead of .text section
The test case builds two copies of the program, one with the compile
option "ldflags=-Wl,-Ttext=0x1000000" and the other with the address
changed to 0x2000000.  However, when linking with ld.bfd, the
resulting executables crash early in ld.so on S390 and i386.

Analysis of the crash: The default linker script establishes a certain
order of loadable sections, and the option "-Ttext" effectively splits
these into an "unaffected" lot (everything before .text) and an
"affected" lot.  The affected lot is placed at the given address,
whereas the unaffected lot stays at its default address.  The
unaffected lot starts at an aligned address plus Elf header sizes,
which is good if it is the first LOAD segment (like on AMD64).  But if
the affected lot comes first instead (like on S390 and i386), the PHDR
doesn't fit there and is placed *outside* any LOAD segments.  Then the
PHDR is not mapped when the loader gets control, and the loader runs
into a segmentation fault while trying to access it.

Since we are lucky about the order of segments on AMD64, the test
succeeds there, but the resulting binaries are unusually large -- 2.1M
each, with lots of padding within.

When replacing '-Ttext' by '-Ttext-segment', the linker moves all
segments consistently, the binaries have normal sizes, and the test
case succeeds on all mentioned platforms.

Since old versions of the gold linker don't support '-Ttext-segment',
the patch also adds logic for falling back to '-Ttext'.

gdb/testsuite/ChangeLog:

	* gdb.base/execl-update-breakpoints.exp: Specify the link address
	with '-Ttext-segment' instead of '-Ttext'.  Fall back to '-Ttext'
	if the linker doesn't understand this.
2014-12-02 16:35:47 +01:00

128 lines
3.5 KiB
Text

# Copyright 2014 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/>.
# Test that when following an exec, we don't try to insert breakpoints
# in the new image at the addresses the symbols had before the exec.
# Remote protocol does not support follow-exec notifications.
if [is_remote target] {
continue
}
standard_testfile
# Build two copies of the program, each linked at a different address.
# The address of "main" in the first binary should end up being an
# unmapped address in the second binary.
set objfile ${binfile}.o
set exec1 ${binfile}1
set exec2 ${binfile}2
if { [gdb_compile [file join $srcdir $subdir $srcfile] $objfile \
object [list debug]] != "" } {
untested "compile failed"
return -1
}
set opts1_ld [list debug ldflags=-Wl,-Ttext-segment=0x1000000]
set opts1_gold [list debug ldflags=-Wl,-Ttext=0x1000000]
set opts2_ld [list debug ldflags=-Wl,-Ttext-segment=0x2000000]
set opts2_gold [list debug ldflags=-Wl,-Ttext=0x2000000]
if { [gdb_compile $objfile $exec1 executable $opts1_ld] != "" } {
# Old gold linker versions don't support -Ttext-segment. Fall
# back to -Ttext.
if { [gdb_compile $objfile $exec1 executable $opts1_gold] != ""
|| [gdb_compile $objfile $exec2 executable $opts2_gold] != ""} {
untested "link failed"
return -1
}
} elseif { [gdb_compile $objfile $exec2 executable $opts2_ld] != "" } {
untested "link failed"
return -1
}
# First check whether the address of "main" in exec1 is readable in
# exec2. If it is, then skip the test as unsupported.
clean_restart ${exec1}
if ![runto_main] then {
fail "Couldn't run to main"
return -1
}
set addr ""
set test "main address first"
gdb_test_multiple "p/x &main" $test {
-re " = (0x\[0-9a-f\]+)\r\n$gdb_prompt $" {
set addr $expect_out(1,string)
pass $test
}
}
clean_restart ${exec2}
if ![runto_main] then {
fail "Couldn't run to main"
return -1
}
set cannot_access 0
set test "probe memory access"
gdb_test_multiple "x $addr" $test {
-re "Cannot access memory at address .*$gdb_prompt $" {
set cannot_access 1
pass $test
}
-re ".*$gdb_prompt $" {
pass $test
}
}
if {!$cannot_access} {
unsupported "main address is readable in second binary"
return
}
# The test proper. ALWAYS_INSERTED indicates whether testing in
# "breakpoint always-inserted" mode.
proc test { always_inserted } {
global exec1
clean_restart ${exec1}
gdb_test_no_output "set breakpoint always-inserted $always_inserted"
if ![runto_main] then {
fail "Couldn't run to main"
return -1
}
# On a buggy GDB, with always-inserted on, we'd see:
# (gdb) continue
# Continuing.
# Warning:
# Cannot insert breakpoint 1.
# Cannot access memory at address 0x10000ff
gdb_test "continue" "Breakpoint 1, main.*" "continue across exec"
}
foreach always_inserted { "off" "on" } {
with_test_prefix "always-inserted $always_inserted" {
test $always_inserted
}
}