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