1# Copyright (C) 2003 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 2 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, write to the Free Software 15# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 16# 17 18# Please email any bugs, comments, and/or additions to this file to: 19# bug-gdb@prep.ai.mit.edu 20 21# Tests for shared object file relocation. If two shared objects have 22# the same load address (actually, overlapping load spaces), one of 23# them gets relocated at load-time. Check that gdb gets the right 24# values for the debugging and minimal symbols. 25 26if {[istarget *-elf*] || [istarget *-coff] || [istarget *-aout]} then { 27 verbose "test skipped - shared object files not supported by this target." 28 return 0 29} 30 31if $tracelevel then { 32 strace $tracelevel 33} 34 35# 36# This file uses shreloc.c, shreloc1.c and shreloc2.c 37# 38 39set prms_id 0 40set bug_id 0 41 42set workdir ${objdir}/${subdir} 43 44foreach module [list "shreloc" "shreloc1" "shreloc2"] { 45 if {[gdb_compile "${srcdir}/${subdir}/${module}.c" "${workdir}/${module}.o" object {debug}] != ""} { 46 untested "Couldn't compile ${module}.c" 47 return -1 48 } 49} 50 51set additional_flags "additional_flags=-shared" 52 53if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } { 54 set additional_flags "${additional_flags} -Wl,--image-base,0x04000000" 55} 56 57foreach module [list "shreloc1" "shreloc2"] { 58 if {[gdb_compile "${workdir}/${module}.o" "${workdir}/${module}.dll" executable [list debug $additional_flags]] != ""} { 59 untested "Couldn't link ${module}.dll" 60 return -1 61 } 62} 63 64if {[gdb_compile [list "${workdir}/shreloc.o" "${workdir}/shreloc1.dll" "${workdir}/shreloc2.dll"] "${workdir}/shreloc" executable debug] != ""} { 65 untested "Couldn't link shreloc executable" 66 return -1 67} 68 69gdb_exit 70gdb_start 71gdb_reinitialize_dir $srcdir/$subdir 72gdb_load ${workdir}/shreloc 73 74# Load up the shared objects 75if ![runto_main] then { 76 fail "Can't run to main" 77 return 0 78} 79 80proc get_var_address { var } { 81 global gdb_prompt hex 82 83 send_gdb "print &${var}\n" 84 # Match output like: 85 # $1 = (int *) 0x0 86 # $5 = (int (*)()) 0 87 # $6 = (int (*)()) 0x24 <function_bar> 88 gdb_expect { 89 -re "\\\$\[0-9\]+ = \\(.*\\) (0|$hex)( <${var}>)?\[\r\n\]+${gdb_prompt} $" 90 { 91 pass "get address of ${var}" 92 if { $expect_out(1,string) == "0" } { 93 return "0x0" 94 } else { 95 return $expect_out(1,string) 96 } 97 } 98 -re "${gdb_prompt} $" 99 { fail "get address of ${var} (unknown output)" } 100 timeout 101 { fail "get address of ${var} (timeout)" } 102 } 103 return "" 104} 105 106# 107# Check debugging symbol relocations 108# 109 110# Check extern function for relocation 111set fn_1_addr [get_var_address fn_1] 112set fn_2_addr [get_var_address fn_2] 113 114if { "${fn_1_addr}" == "${fn_2_addr}" } { 115 fail "relocated extern functions have different addresses" 116} else { 117 pass "relocated extern functions have different addresses" 118} 119 120# Check extern var for relocation 121set extern_var_1_addr [get_var_address extern_var_1] 122set extern_var_2_addr [get_var_address extern_var_2] 123 124if { "${extern_var_1_addr}" == "${extern_var_2_addr}" } { 125 fail "relocated extern variables have different addresses" 126} else { 127 pass "relocated extern variables have different addresses" 128} 129 130# Check static var for relocation 131set static_var_1_addr [get_var_address static_var_1] 132set static_var_2_addr [get_var_address static_var_2] 133 134if { "${static_var_1_addr}" == "${static_var_2_addr}" } { 135 fail "relocated static variables have different addresses" 136} else { 137 pass "relocated static variables have different addresses" 138} 139 140# 141# Check minimal symbol relocations 142# 143 144proc send_gdb_discard { command } { 145 # Send a command to gdb and discard output up to the next prompt 146 147 global gdb_prompt 148 149 send_gdb "${command}\n" 150 151 # Discard output 152 gdb_expect { 153 -re ".*\[\r\n]+${gdb_prompt} $" { 154 return 1 155 } 156 timeout { 157 fail "{$command} (timeout)" 158 return 0 159 } 160 } 161} 162 163proc get_msym_addrs { var msymfile } { 164 # Extract the list of values for symbols matching var in the 165 # minimal symbol output file 166 167 global gdb_prompt hex 168 set result "" 169 170 send_gdb "shell grep -E \" ${var}(\[ \t\]+.*)?\$\" ${msymfile}\n" 171 172 while 1 { 173 gdb_expect { 174 -re "\[\[\]\[ 0-9\]+\] . (${hex}) ${var}(\[ \t\]+\[^\r\n\]*)?\[\r\n\]+" { 175 set result [concat $result $expect_out(1,string)] 176 } 177 178 -re "$gdb_prompt $" { 179 pass "get_msym_addrs ${var} (${result})" 180 return "${result}" 181 } 182 183 -re "\[^\r\n\]*\[\r\n\]+" { 184 # Skip 185 } 186 187 timeout { 188 fail "get_msym_addrs ${var} (timeout)" 189 return -1 190 } 191 } 192 } 193} 194 195proc check_same {var msymfile} { 196 # Check that the minimal symbol values matching var are the same 197 198 set len [llength [lsort -unique [get_msym_addrs "${var}" "${msymfile}"]]] 199 200 if { $len == 1 } { 201 return 1 202 } else { 203 return 0 204 } 205} 206 207proc check_different {var msymfile} { 208 # Check that the minimal symbol values matching var are different 209 210 set addr_list [lsort [get_msym_addrs "${var}" "${msymfile}"]] 211 set prev "" 212 213 if { [llength ${addr_list}] < 2 } { 214 return 0 215 } 216 217 foreach addr ${addr_list} { 218 if { ${prev} == ${addr} } { 219 return 0 220 } 221 set prev ${addr} 222 } 223 224 return 1 225} 226 227set msymfile "${workdir}/shreloc.txt" 228 229if [send_gdb_discard "maint print msymbols ${msymfile}"] { 230 if {[check_different "static_var_\[12\]" "${msymfile}"]} { 231 pass "(msymbol) relocated static vars have different addresses" 232 } else { 233 fail "(msymbol) relocated static vars have different addresses" 234 } 235 236 if {[check_different "extern_var_\[12\]" "${msymfile}"]} { 237 pass "(msymbol) relocated extern vars have different addresses" 238 } else { 239 fail "(msymbol) relocated extern vars have different addresses" 240 } 241 242 if {[check_different "fn_\[12\]" "${msymfile}"]} { 243 pass "(msymbol) relocated functions have different addresses" 244 } else { 245 fail "(msymbol) relocated functions have different addresses" 246 } 247} 248 249if {([istarget "*pc-cygwin"] || [istarget "*pc-mingw32"]) } { 250 # 251 # We know the names of some absolute symbols included in the 252 # portable-executable (DLL) format. Check that they didn't get 253 # relocated. 254 # 255 # A better approach would be include absolute symbols via the assembler. 256 # 257 if {[check_same "_minor_os_version__" "${msymfile}"]} { 258 pass "Absolute symbols not relocated" 259 } else { 260 fail "Absolute symbols not relocated" 261 } 262} 263