Home | History | Annotate | Download | only in ld-unique
      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