1 # Expect script for linker support of STB_GNU_UNIQUE symbols 2 # 3 # Copyright (C) 2009-2014 Free Software Foundation, Inc. 4 # Contributed by Red Hat. 5 # 6 # This file is part of the GNU Binutils. 7 # 8 # This program is free software; you can redistribute it and/or modify 9 # it under the terms of the GNU General Public License as published by 10 # the Free Software Foundation; either version 3 of the License, or 11 # (at your option) any later version. 12 # 13 # This program is distributed in the hope that it will be useful, 14 # but WITHOUT ANY WARRANTY; without even the implied warranty of 15 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 # GNU General Public License for more details. 17 # 18 # You should have received a copy of the GNU General Public License 19 # along with this program; if not, write to the Free Software 20 # Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 21 # MA 02110-1301, USA. 22 # 23 # Written by Nick Clifton <nickc (at) redhat.com> 24 # Adapted for unique checking by Mark J. Wielaard <mjw (at) redhat.com> 25 26 27 # STB_GNU_UNIQUE support has only been implemented for the ix86, x86_64, 28 # arm, powerpc, and sparc so far. 29 if {!(([istarget "i?86-*-*"] 30 || [istarget "x86_64-*-*"] 31 || [istarget "arm*-*-*"] 32 || [istarget "powerpc*-*-*"] 33 || [istarget "sparc*-*-*"]) 34 && ([istarget "*-*-elf*"] 35 || [istarget "*-*-nacl*"] 36 || (([istarget "*-*-linux*"] 37 || [istarget "*-*-gnu*"]) 38 && ![istarget "*-*-*aout*"] 39 && ![istarget "*-*-*oldld*"]))) } { 40 verbose "UNIQUE tests not run - target does not support UNIQUE" 41 return 42 } 43 44 # We need a native system. FIXME: Strictly speaking this 45 # is not true, we just need to know how to create a fully 46 # linked executable, including the C and Z libraries, using 47 # the linker that is under test. 48 if ![isnative] { 49 verbose "UNIQUE tests not run - not a native toolchain" 50 return 51 } 52 53 # We need a working compiler. (Strictly speaking this is 54 # not true, we could use target specific assembler files). 55 if { [which $CC] == 0 } { 56 verbose "UNIQUE tests not run - no compiler available" 57 return 58 } 59 60 # A procedure to check the OS/ABI field in the ELF header of a binary file. 61 proc check_osabi { binary_file expected_osabi } { 62 global READELF 63 global READELFFLAGS 64 65 catch "exec $READELF $READELFFLAGS --file-header $binary_file > readelf.out" got 66 67 if ![string match "" $got] then { 68 verbose "proc check_osabi: Readelf produced unexpected out processing $binary_file: $got" 69 return 0 70 } 71 72 if { ![regexp "\n\[ \]*OS/ABI:\[ \]*(.+)\n\[ \]*ABI" \ 73 [file_contents readelf.out] nil osabi] } { 74 verbose "proc check_osabi: Readelf failed to extract an ELF header from $binary_file" 75 return 0 76 } 77 78 if { $osabi == $expected_osabi } { 79 return 1 80 } 81 82 verbose "Expected OSABI: $expected_osabi, Obtained osabi: $osabi" 83 84 return 0 85 } 86 87 # A procedure to confirm that a file contains the UNIQUE symbol. 88 # Returns -1 upon error, 0 if the symbol was not found and 1 if it was found. 89 proc contains_unique_symbol { binary_file } { 90 global READELF 91 global READELFFLAGS 92 93 catch "exec $READELF $READELFFLAGS --symbols $binary_file > readelf.out" got 94 95 if ![string match "" $got] then { 96 verbose "proc contains_unique_symbol: Readelf produced unexpected out processing $binary_file: $got" 97 return -1 98 } 99 100 # Look for a line like this: 101 # 54: 0000000000400474 4 OBJECT UNIQUE DEFAULT 13 a 102 103 if { ![regexp ".*\[ \]*OBJECT\[ \]+UNIQUE\[ \]+DEFAULT\[ \]+\[UND0-9\]+\[ \]+\[ab\]\n" [file_contents readelf.out]] } { 104 return 0 105 } 106 107 return 1 108 } 109 110 set fails 0 111 112 # Create object file containing unique symbol. 113 if ![ld_compile "$CC -c" "$srcdir/$subdir/unique.s" "tmpdir/unique.o"] { 114 fail "Could not create a unique object" 115 set fails [expr $fails + 1] 116 } 117 118 # Create object file NOT containing unique symbol. 119 if ![ld_compile "$CC -c" "$srcdir/$subdir/unique_empty.s" "tmpdir/unique_empty.o"] { 120 fail "Could not create a non-unique object" 121 set fails [expr $fails + 1] 122 } 123 124 # Create pic object file containing unique symbol. 125 if ![ld_compile "$CC -c -fPIC" "$srcdir/$subdir/unique_shared.s" "tmpdir/unique_shared.o"] { 126 fail "Could not create a pic unique object" 127 set fails [expr $fails + 1] 128 } 129 130 # Create executable containing unique symbol. 131 if ![default_ld_link $ld "tmpdir/unique_prog" "tmpdir/unique.o"] { 132 fail "Could not link a unique executable" 133 set fails [expr $fails + 1] 134 } 135 136 # Create shared library containing unique symbol. 137 if ![ld_simple_link $ld "tmpdir/libunique_shared.so" "-shared tmpdir/unique_shared.o"] { 138 fail "Could not create a shared library containing an unique symbol" 139 set fails [expr $fails + 1] 140 } 141 142 # Create executable NOT containing unique symbol linked against library. 143 if ![default_ld_link $ld "tmpdir/unique_shared_prog" "-Ltmpdir tmpdir/unique_empty.o -Bdynamic -lunique_shared -rpath ./tmpdir"] { 144 fail "Could not link a dynamic executable" 145 set fails [expr $fails + 1] 146 } 147 148 # Create shared library containing unique symbol with reference. 149 if ![ld_simple_link $ld "tmpdir/libunique_shared_ref.so" "-shared tmpdir/unique_shared.o tmpdir/unique_empty.o"] { 150 fail "Could not create a shared library containing an unique symbol with reference" 151 set fails [expr $fails + 1] 152 } 153 154 if { $fails != 0 } { 155 return 156 } 157 158 # Check the object file. 159 if {! [check_osabi tmpdir/unique.o {UNIX - GNU}]} { 160 fail "Object containing unique does not have an OS/ABI field of GNU" 161 set fails [expr $fails + 1] 162 } 163 164 if {[contains_unique_symbol tmpdir/unique.o] != 1} { 165 fail "Object containing unique does not contain an UNIQUE symbol" 166 set fails [expr $fails + 1] 167 } 168 169 if { $fails == 0 } { 170 pass "Checking unique object" 171 } 172 173 # Check the executable. 174 if {! [check_osabi tmpdir/unique_prog {UNIX - GNU}]} { 175 fail "Executable containing unique does not have an OS/ABI field of GNU" 176 set fails [expr $fails + 1] 177 } 178 179 if {[contains_unique_symbol tmpdir/unique_prog] != 1} { 180 fail "Executable containing unique does not contain an UNIQUE symbol" 181 set fails [expr $fails + 1] 182 } 183 184 if { $fails == 0 } { 185 pass "Checking unique executable" 186 } 187 188 # Check the empty object file. 189 if {! [check_osabi tmpdir/unique_empty.o {UNIX - System V}]} { 190 fail "Object NOT containing unique does not have an OS/ABI field of System V" 191 set fails [expr $fails + 1] 192 } 193 194 if {[contains_unique_symbol tmpdir/unique_empty.o] == 1} { 195 fail "Object NOT containing unique does contain an UNIQUE symbol" 196 set fails [expr $fails + 1] 197 } 198 199 if { $fails == 0 } { 200 pass "Checking empty unique object" 201 } 202 203 # Check the unique PIC file. 204 if {! [check_osabi tmpdir/unique_shared.o {UNIX - GNU}]} { 205 fail "PIC Object containing unique does not have an OS/ABI field of GNU" 206 set fails [expr $fails + 1] 207 } 208 209 if {[contains_unique_symbol tmpdir/unique_shared.o] != 1} { 210 fail "PIC Object containing unique does not contain an UNIQUE symbol" 211 set fails [expr $fails + 1] 212 } 213 214 if { $fails == 0 } { 215 pass "Checking unique PIC object" 216 } 217 218 # Check the unique shared library. 219 if {! [check_osabi tmpdir/libunique_shared.so {UNIX - GNU}]} { 220 fail "Shared library containing unique does not have an OS/ABI field of GNU" 221 set fails [expr $fails + 1] 222 } 223 224 if {[contains_unique_symbol tmpdir/libunique_shared.so] != 1} { 225 fail "Shared library containing unique does not contain an UNIQUE symbol" 226 set fails [expr $fails + 1] 227 } 228 229 # Check the unique shared library with reference. 230 if {! [check_osabi tmpdir/libunique_shared_ref.so {UNIX - GNU}]} { 231 fail "Shared library containing unique with reference does not have an OS/ABI field of GNU" 232 set fails [expr $fails + 1] 233 } 234 235 if {[contains_unique_symbol tmpdir/libunique_shared_ref.so] != 1} { 236 fail "Shared library containing unique with reference does not contain an UNIQUE symbol" 237 set fails [expr $fails + 1] 238 } 239 240 if { $fails == 0 } { 241 pass "Checking unique PIC object" 242 } 243 244 # Check the empty executable linked against unique shared library. 245 if {! [check_osabi tmpdir/unique_shared_prog {UNIX - System V}]} { 246 fail "Executable NOT containing unique does not have an OS/ABI field of System V" 247 set fails [expr $fails + 1] 248 } 249 250 if {[contains_unique_symbol tmpdir/unique_shared_prog] == 1} { 251 fail "Executable NOT containing unique does contain an UNIQUE symbol" 252 set fails [expr $fails + 1] 253 } 254 255 if { $fails == 0 } { 256 pass "Checking shared empty executable" 257 } 258 259 # Clean up, unless we are being verbose, in which case we leave the files available. 260 if { $verbose < 1 } { 261 remote_file host delete "tmpdir/unique_empty.o" 262 remote_file host delete "tmpdir/unique.o" 263 remote_file host delete "tmpdir/unique_shared.o" 264 remote_file host delete "tmpdir/libunique_shared.so" 265 remote_file host delete "tmpdir/libunique_shared_ref.so" 266 remote_file host delete "tmpdir/unique_prog" 267 remote_file host delete "tmpdir/unique_shared_prog" 268 } 269