1# Copyright 2010, 2011 Free Software Foundation, Inc. 2 3# This program is free software; you can redistribute it and/or modify 4# it under the terms of the GNU General Public License as published by 5# the Free Software Foundation; either version 3 of the License, or 6# (at your option) any later version. 7# 8# This program is distributed in the hope that it will be useful, 9# but WITHOUT ANY WARRANTY; without even the implied warranty of 10# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11# GNU General Public License for more details. 12# 13# You should have received a copy of the GNU General Public License 14# along with this program. If not, see <http://www.gnu.org/licenses/>. 15 16# This test only works on GNU/Linux. 17if { ![isnative] || [is_remote host] || ![istarget *-linux*] || [skip_shlib_tests]} { 18 continue 19} 20 21load_lib prelink-support.exp 22 23set test "attach-pie-misread" 24set srcfile ${test}.c 25set genfile ${objdir}/${subdir}/${test}-gen.h 26set executable ${test} 27set binfile ${objdir}/${subdir}/${executable} 28 29if {[build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie"]] == ""} { 30 return -1 31} 32 33# Program Headers: 34# Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align 35# LOAD 0x000000 0x0000000000400000 0x0000000000400000 0x134f5ec 0x134f5ec R E 0x200000 36# LOAD 0x134f5f0 0x000000000194f5f0 0x000000000194f5f0 0x1dbc60 0x214088 RW 0x200000 37# DYNAMIC 0x134f618 0x000000000194f618 0x000000000194f618 0x000200 0x000200 RW 0x8 38# 39proc read_phdr {binfile test} { 40 set readelf_program [transform readelf] 41 set command "exec $readelf_program -Wl $binfile" 42 verbose -log "command is $command" 43 set result [catch $command output] 44 verbose -log "result is $result" 45 verbose -log "output is $output" 46 if {$result != 0} { 47 fail $test 48 return 49 } 50 if ![regexp {\nProgram Headers:\n *Type [^\n]* Align\n(.*?)\n\n} $output trash phdr] { 51 fail "$test (no Program Headers)" 52 return 53 } 54 if ![regexp -line {^ *DYNAMIC +0x[0-9a-f]+ +(0x[0-9a-f]+) } $phdr trash dynamic_vaddr] { 55 fail "$test (no DYNAMIC found)" 56 return 57 } 58 verbose -log "dynamic_vaddr is $dynamic_vaddr" 59 set align_max -1 60 foreach {trash align} [regexp -line -all -inline {^ *LOAD .* (0x[0-9]+)$} $phdr] { 61 if {$align_max < $align} { 62 set align_max $align 63 } 64 } 65 verbose -log "align_max is $align_max" 66 if {$align_max == -1} { 67 fail "$test (no LOAD found)" 68 return 69 } 70 pass $test 71 return [list $dynamic_vaddr $align_max] 72} 73 74set phdr [read_phdr $binfile "readelf initial scan"] 75set dynamic_vaddr [lindex $phdr 0] 76set align_max [lindex $phdr 1] 77 78set stub_size [format 0x%x [expr "2 * $align_max - ($dynamic_vaddr & ($align_max - 1))"]] 79verbose -log "stub_size is $stub_size" 80 81# On x86_64 it is commonly about 4MB. 82if {$stub_size > 25000000} { 83 xfail "stub size $stub_size is too large" 84 return 85} 86 87set test "generate stub" 88set command "exec $binfile $stub_size >$genfile" 89verbose -log "command is $command" 90set result [catch $command output] 91verbose -log "result is $result" 92verbose -log "output is $output" 93if {$result == 0} { 94 pass $test 95} else { 96 fail $test 97} 98 99set prelink_args [build_executable_own_libs ${test}.exp $executable $srcfile [list "additional_flags=-fPIE -pie -DGEN=\"$genfile\""]] 100if {$prelink_args == ""} { 101 return -1 102} 103 104# x86_64 file has 25MB, no need to keep it. 105file delete -- $genfile 106 107set phdr [read_phdr $binfile "readelf rebuilt with stub_size"] 108set dynamic_vaddr_prelinkno [lindex $phdr 0] 109 110if ![prelink_yes $prelink_args] { 111 return -1 112} 113 114set phdr [read_phdr $binfile "readelf with prelink -R"] 115set dynamic_vaddr_prelinkyes [lindex $phdr 0] 116 117set first_offset [format 0x%x [expr $dynamic_vaddr_prelinkyes - $dynamic_vaddr_prelinkno]] 118verbose -log "first_offset is $first_offset" 119 120set test "first offset is non-zero" 121if {$first_offset == 0} { 122 fail "$test (-fPIE -pie in effect?)" 123} else { 124 pass $test 125} 126 127set test "start inferior" 128gdb_exit 129 130set res [remote_spawn host $binfile]; 131if { $res < 0 || $res == "" } { 132 perror "Spawning $binfile failed." 133 fail $test 134 return 135} 136set pid [exp_pid -i $res] 137gdb_expect { 138 -re "sleeping\r\n" { 139 pass $test 140 } 141 eof { 142 fail "$test (eof)" 143 remote_exec host "kill -9 $pid" 144 return 145 } 146 timeout { 147 fail "$test (timeout)" 148 remote_exec host "kill -9 $pid" 149 return 150 } 151} 152 153# Due to alignments it was reproducible with 1 on x86_64 but 2 on i686. 154foreach align_mult {1 2} { 155 set old_ldprefix $pf_prefix 156 lappend pf_prefix "shift-by-$align_mult:" 157 158 # FIXME: We believe there is enough room under FIRST_OFFSET. 159 set shifted_offset [format 0x%x [expr "$first_offset - $align_mult * $align_max"]] 160 verbose -log "shifted_offset is $shifted_offset" 161 162 # For normal prelink (prelink_yes call), we need to supply $prelink_args. 163 # For the prelink `-r' option below, $prelink_args is not required. 164 # Moreover, if it was used, the problem would not longer be reproducible 165 # as the libraries would also get relocated. 166 set command "exec /usr/sbin/prelink -q -N --no-exec-shield -r $shifted_offset $binfile" 167 verbose -log "command is $command" 168 set result [catch $command output] 169 verbose -log "result is $result" 170 verbose -log "output is $output" 171 172 set test "prelink -r" 173 if {$result == 0 && $output == ""} { 174 pass $test 175 } else { 176 fail $test 177 } 178 179 clean_restart $executable 180 181 set test "attach" 182 gdb_test_multiple "attach $pid" $test { 183 -re "Attaching to program: .*, process $pid\r\n" { 184 # Missing "$gdb_prompt $" is intentional. 185 pass $test 186 } 187 } 188 189 set test "error on Cannot access memory at address" 190 gdb_test_multiple "" $test { 191 -re "\r\nCannot access memory at address .*$gdb_prompt $" { 192 fail $test 193 } 194 -re "$gdb_prompt $" { 195 pass $test 196 } 197 } 198 199 gdb_test "detach" "Detaching from program: .*" 200 201 set pf_prefix $old_ldprefix 202} 203 204remote_exec host "kill -9 $pid" 205