1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
# Copyright 2010-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/>.
# This test only works on GNU/Linux.
if { ![isnative] || [is_remote host] || [target_info exists use_gdb_stub]
|| ![istarget *-linux*] || [skip_shlib_tests]} {
continue
}
load_lib prelink-support.exp
standard_testfile .c
set genfile [standard_output_file ${testfile}-gen.h]
set executable $testfile
if {[build_executable_own_libs ${testfile}.exp $executable $srcfile [list additional_flags=-fPIE ldflags=-pie]] == ""} {
return -1
}
# Program Headers:
# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
# LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x134f5ec 0x134f5ec R E 0x200000
# LOAD 0x134f5f0 0x000000000194f5f0 0x000000000194f5f0 0x1dbc60 0x214088 RW 0x200000
# DYNAMIC 0x134f618 0x000000000194f618 0x000000000194f618 0x000200 0x000200 RW 0x8
#
proc read_phdr {binfile test} {
set readelf_program [gdb_find_readelf]
set command "exec $readelf_program -Wl $binfile"
verbose -log "command is $command"
set result [catch $command output]
verbose -log "result is $result"
verbose -log "output is $output"
if {$result != 0} {
fail $test
return
}
if ![regexp {\nProgram Headers:\n *Type [^\n]* Align\n(.*?)\n\n} $output trash phdr] {
fail "$test (no Program Headers)"
return
}
if ![regexp -line {^ *DYNAMIC +0x[0-9a-f]+ +(0x[0-9a-f]+) } $phdr trash dynamic_vaddr] {
fail "$test (no DYNAMIC found)"
return
}
verbose -log "dynamic_vaddr is $dynamic_vaddr"
set align_max -1
foreach {trash align} [regexp -line -all -inline {^ *LOAD .* (0x[0-9]+)$} $phdr] {
if {$align_max < $align} {
set align_max $align
}
}
verbose -log "align_max is $align_max"
if {$align_max == -1} {
fail "$test (no LOAD found)"
return
}
pass $test
return [list $dynamic_vaddr $align_max]
}
set phdr [read_phdr $binfile "readelf initial scan"]
set dynamic_vaddr [lindex $phdr 0]
set align_max [lindex $phdr 1]
set stub_size [format 0x%x [expr "2 * $align_max - ($dynamic_vaddr & ($align_max - 1))"]]
verbose -log "stub_size is $stub_size"
# On x86_64 it is commonly about 4MB.
if {$stub_size > 25000000} {
xfail "stub size $stub_size is too large"
return
}
set test "generate stub"
set command "exec $binfile $stub_size >$genfile"
verbose -log "command is $command"
set result [catch $command output]
verbose -log "result is $result"
verbose -log "output is $output"
if {$result == 0} {
pass $test
} else {
fail $test
}
set prelink_args [build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -DGEN=\"$genfile\"" "ldflags=-pie"]]
if {$prelink_args == ""} {
return -1
}
# x86_64 file has 25MB, no need to keep it.
file delete -- $genfile
set phdr [read_phdr $binfile "readelf rebuilt with stub_size"]
set dynamic_vaddr_prelinkno [lindex $phdr 0]
if ![prelink_yes $prelink_args] {
return -1
}
set phdr [read_phdr $binfile "readelf with prelink -R"]
set dynamic_vaddr_prelinkyes [lindex $phdr 0]
set first_offset [format 0x%x [expr $dynamic_vaddr_prelinkyes - $dynamic_vaddr_prelinkno]]
verbose -log "first_offset is $first_offset"
set test "first offset is non-zero"
if {$first_offset == 0} {
fail "$test (-fPIE -pie in effect?)"
} else {
pass $test
}
set test "start inferior"
gdb_exit
set res [remote_spawn host $binfile]
if { $res < 0 || $res == "" } {
perror "Spawning $binfile failed."
fail $test
return
}
set pid [exp_pid -i $res]
gdb_expect {
-re "sleeping\r\n" {
pass $test
}
eof {
fail "$test (eof)"
remote_exec host "kill -9 $pid"
return
}
timeout {
fail "$test (timeout)"
remote_exec host "kill -9 $pid"
return
}
}
# Due to alignments it was reproducible with 1 on x86_64 but 2 on i686.
foreach align_mult {1 2} { with_test_prefix "shift-by-$align_mult" {
# FIXME: We believe there is enough room under FIRST_OFFSET.
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]
verbose -log "result is $result"
verbose -log "output is $output"
set test "prelink -r"
if {$result == 0 && $output == ""} {
pass $test
} else {
fail $test
}
clean_restart $executable
set test "attach"
gdb_test_multiple "attach $pid" $test {
-re "Attaching to program: .*, process $pid\r\n" {
# Missing "$gdb_prompt $" is intentional.
pass $test
}
}
set test "error on Cannot access memory at address"
gdb_test_multiple "" $test {
-re "\r\nCannot access memory at address .*$gdb_prompt $" {
fail $test
}
-re "$gdb_prompt $" {
pass $test
}
}
gdb_test "detach" "Detaching from program: .*"
}}
remote_exec host "kill -9 $pid"
|