1# Test linking directly to S-records. 2# By Ian Lance Taylor, Cygnus Support. 3# Copyright (C) 1999-2016 Free Software Foundation, Inc. 4# 5# This file is part of the GNU Binutils. 6# 7# This program is free software; you can redistribute it and/or modify 8# it under the terms of the GNU General Public License as published by 9# the Free Software Foundation; either version 3 of the License, or 10# (at your option) any later version. 11# 12# This program is distributed in the hope that it will be useful, 13# but WITHOUT ANY WARRANTY; without even the implied warranty of 14# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15# GNU General Public License for more details. 16# 17# You should have received a copy of the GNU General Public License 18# along with this program; if not, write to the Free Software 19# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, 20# MA 02110-1301, USA. 21 22# Get the offset from an S-record line to the start of the data. 23 24proc srec_off { l } { 25 if [string match "S1*" $l] { 26 return 8 27 } else { if [string match "S2*" $l] { 28 return 10 29 } else { if [string match "S3*" $l] { 30 return 12 31 } else { 32 return -1 33 } } } 34} 35 36# See if an S-record line contains only zero data. 37 38proc srec_zero { l } { 39 if [string match "S\[0789\]*" $l] { 40 return 1 41 } 42 43 # Strip the address and checksum. 44 if [string match "S\[123\]*" $l] { 45 set l [string range $l [srec_off $l] [expr [string length $l] - 3]] 46 } else { 47 return 0 48 } 49 50 # The rest must be zero. 51 return [string match "" [string trim $l "0"]] 52} 53 54# Get the address of an S-record line. 55 56proc srec_addr { l } { 57 if [string match "S\[123\]*" $l] { 58 set addr [string range $l 4 [expr [srec_off $l] - 1]] 59 } else { 60 return -1 61 } 62 63 return "0x$addr" 64} 65 66# Get the number of data bytes in an S-record line. 67 68proc srec_len { l } { 69 if ![string match "S\[123\]*" $l] { 70 return 0 71 } 72 73 return [expr "0x[string range $l 2 3]" - ([srec_off $l] - 4) / 2 - 1] 74} 75 76# Extract bytes from an S-record line. 77 78proc srec_extract { l start len } { 79 set off [srec_off $l] 80 set rlen [srec_len $l] 81 set stop [expr $start + $len] 82 if { $stop > $rlen } { 83 set stop [expr $rlen] 84 } 85 set start [expr $start * 2 + $off] 86 set stop [expr $stop * 2 + $off - 1] 87 return [string range $l $start $stop] 88} 89 90# See if a range of bytes in an S-record line is all zeroes. 91 92proc srec_zero_range { l start len } { 93 return [string match "" [string trim [srec_extract $l $start $len] "0"]] 94} 95 96# Trim an S-record line such that the specified number of bytes remain 97# at the end. 98 99proc srec_trim { l leave } { 100 set off [srec_off $l] 101 set addr [srec_addr $l] 102 set len [srec_len $l] 103 104 if { $leave >= $len } { 105 return $l 106 } 107 108 set s1 [string range $l 0 1] 109 set s2 [format "%02x" [expr ($off - 4) / 2 + $leave + 1]] 110 set s3 [format "%0[expr $off - 4]x" [expr $addr + $len - $leave]] 111 set s4 [string range $l [expr [string length $l] - ($leave * 2) - 2] end] 112 set s "${s1}${s2}${s3}${s4}" 113 114 verbose "srec_trim { '$l' $leave } returning '$s'" 2 115 116 return $s 117} 118 119# Report failure when comparing S-record lines 120 121proc srec_compare_fail { which l1 l2 } { 122 send_log "comparison failure $which:\n$l1\n$l2\n" 123 verbose "comparison failure $which:\n$l1\n$l2" 124} 125 126# Compare S-record files. We don't want to fuss about things like 127# extra zeroes. Note that BFD always sorts S-records by address. 128 129proc srec_compare { f1 f2 } { 130 set e1 [gets $f1 l1] 131 set e2 [gets $f2 l2] 132 133 while { $e1 != -1 } { 134 set l1 [string trimright $l1 "\r\n"] 135 set l2 [string trimright $l2 "\r\n"] 136 if { $e2 == -1 } { 137 # If l1 contains data, it must be zero. 138 if ![srec_zero $l1] { 139 send_log "data after EOF: $l1\n" 140 verbose "data after EOF: $l1" 141 return 0 142 } 143 } else { if { [string compare $l1 $l2] == 0 } { 144 set e1 [gets $f1 l1] 145 set e2 [gets $f2 l2] 146 } else { if { [srec_zero $l1] } { 147 set e1 [gets $f1 l1] 148 } else { if { [srec_zero $l2] } { 149 set e2 [gets $f2 l2] 150 } else { 151 # The strings are not the same, and neither is all zeroes. 152 set a1 [srec_addr $l1] 153 set n1 [srec_len $l1] 154 set a2 [srec_addr $l2] 155 set n2 [srec_len $l2] 156 157 if { $a1 < $a2 && ![srec_zero_range $l1 0 [expr $a2 - $a1]] } { 158 verbose "$a1 $a2 [srec_extract $l1 0 [expr $a2 - $a1]]" 2 159 srec_compare_fail 1 $l1 $l2 160 return 0 161 } 162 if { $a2 < $a1 && ![srec_zero_range $l2 0 [expr $a1 - $a2]] } { 163 srec_compare_fail 2 $l1 $l2 164 return 0 165 } 166 167 # Here we know that any initial data in both lines is 168 # zero. Now make sure that any overlapping data matches. 169 if { $a1 < $a2 } { 170 set os1 [expr $a2 - $a1] 171 set os2 0 172 } else { 173 set os1 0 174 set os2 [expr $a1 - $a2] 175 } 176 if { $a1 + $n1 < $a2 + $n2 } { 177 set ol [expr $n1 - $os1] 178 } else { 179 set ol [expr $n2 - $os2] 180 } 181 182 set x1 [srec_extract $l1 $os1 $ol] 183 set x2 [srec_extract $l2 $os2 $ol] 184 if { [string compare $x1 $x2] != 0 } { 185 verbose "$os1 $ol $x1" 2 186 verbose "$os2 $ol $x2" 2 187 srec_compare_fail 3 $l1 $l2 188 return 0 189 } 190 191 # These strings match. Trim the data from the larger 192 # string, read a new copy of the smaller string, and 193 # continue. 194 if { $a1 + $n1 < $a2 + $n2 } { 195 set l2 [srec_trim $l2 [expr ($a2 + $n2) - ($a1 + $n1)]] 196 set e1 [gets $f1 l1] 197 } else { if { $a1 + $n1 > $a2 + $n2 } { 198 set l1 [srec_trim $l1 [expr ($a1 + $n1) - ($a2 + $n2)]] 199 set e2 [gets $f2 l2] 200 } else { 201 set e1 [gets $f1 l1] 202 set e2 [gets $f2 l2] 203 } } 204 } } } } 205 } 206 207 # We've reached the end of the first file. The remainder of the 208 # second file must contain only zeroes. 209 while { $e2 != -1 } { 210 set l2 [string trimright $l2 "\r\n"] 211 if ![srec_zero $l2] { 212 send_log "data after EOF: $l2\n" 213 verbose "data after EOF: $l2" 214 return 0 215 } 216 set e2 [gets $f2 l2] 217 } 218 219 return 1 220} 221 222# Link twice, objcopy, and compare 223 224proc run_srec_test { test objs } { 225 global ld 226 global objcopy 227 global sizeof_headers 228 global host_triplet 229 230 # Tell the ELF linker to not do anything clever with .eh_frame, 231 # not to put anything in small data, and define various symbols. 232 set flags "--traditional-format -G 0 " 233 append flags [ld_simple_link_defsyms] 234 235 # If the linker script uses SIZEOF_HEADERS, use a -Ttext argument 236 # to force both the normal link and the S-record link to be put in 237 # the same place. We don't always use -Ttext because it interacts 238 # poorly with a.out. 239 240 if { $sizeof_headers } { 241 set flags "$flags -Ttext 0x1000" 242 } 243 244 # ARM targets cannot convert format in the linker 245 # using the --oformat command line switch 246 if {[istarget aarch64*-*-*] || \ 247 [istarget arm*-*-*]} { 248 setup_xfail "aarch64-*-*" 249 setup_xfail "aarch64_be-*-*" 250 setup_xfail "arm*-*-*" 251 } 252 253 # The AVR target does not correctly process 254 # relocs when output format is not ELF. 255 if [istarget avr-*-*] { 256 setup_xfail "avr-*-*" 257 } 258 259 # Epiphany needs some help too 260 if [istarget epiphany*-*-*] { 261 set flags "$flags --defsym _start=00000060" 262 setup_xfail "epiphany*-*-*" 263 } 264 265 if [istarget m681*-*-*] { 266 set flags "$flags --defsym _start=0xc000" 267 setup_xfail "m681*-*-*" 268 } 269 270 if [istarget m68hc1*-*-*] { 271 set flags "$flags --defsym _start=0xc000" 272 setup_xfail "m68hc1*-*-*" 273 } 274 275 if [istarget m9s12x*-*-*] { 276 set flags "$flags --defsym _start=0xc000" 277 setup_xfail "m9s12x*-*-*" 278 } 279 280 # MSP430 targets always relax. 281 if [istarget msp430*-*-*] { 282 setup_xfail "msp430*-*-*" 283 } 284 285 # SH64 targets cannot convert format in the linker 286 # using the -oformat command line switch. 287 if [istarget sh64*-*-elf] { 288 # This is what gcc passes to ld by default. 289 set flags "$flags -mshelf32" 290 setup_xfail "sh64*-*-*" 291 } 292 293 # V850 targets need libgcc.a 294 if [istarget v850*-*-elf] { 295 set objs "$objs -L ../gcc -lgcc" 296 } 297 298 # Xtensa ELF targets relax by default; S-Record linker does not 299 if [istarget xtensa*-*-*] { 300 set flags "$flags -no-relax" 301 } 302 303 if { ![ld_simple_link $ld tmpdir/sr1 "$flags $objs"] \ 304 || ![ld_simple_link $ld tmpdir/sr2.sr "$flags --oformat srec $objs"] } { 305 fail $test 306 return 307 } 308 309 send_log "$objcopy -O srec tmpdir/sr1 tmpdir/sr1.sr\n" 310 set exec_output [run_host_cmd "$objcopy" "-O srec tmpdir/sr1 tmpdir/sr1.sr"] 311 set exec_output [prune_warnings $exec_output] 312 if ![string match "" $exec_output] { 313 send_log "$exec_output\n" 314 verbose "$exec_output" 315 unresolved $test 316 return 317 } 318 319 set f1 [open tmpdir/sr1.sr r] 320 set f2 [open tmpdir/sr2.sr r] 321 if [srec_compare $f1 $f2] { 322 pass $test 323 } else { 324 fail $test 325 } 326 close $f1 327 close $f2 328} 329 330set test1 "S-records" 331set test2 "S-records with constructors" 332 333# See whether the default linker script uses SIZEOF_HEADERS. 334set exec_output [run_host_cmd "$ld" "--verbose"] 335set sizeof_headers [string match "*SIZEOF_HEADERS*" $exec_output] 336 337# First test linking a C program. We don't require any libraries. We 338# link it normally, and objcopy to the S-record format, and then link 339# directly to the S-record format, and require that the two files 340# contain the same data. 341 342if { ![is_remote host] && [which $CC] == 0 } { 343 untested $test1 344 untested $test2 345 return 346} 347 348# Pass -fplt to CC and CXX since -fno-plt doesn't work with S-records 349# tests. 350global PLT_CFLAGS 351set old_CC "$CC" 352set CC "$CC $PLT_CFLAGS" 353set old_CXX "$CXX" 354set CXX "$CXX $PLT_CFLAGS" 355 356if { ![ld_compile $CC $srcdir/$subdir/sr1.c tmpdir/sr1.o] \ 357 || ![ld_compile $CC $srcdir/$subdir/sr2.c tmpdir/sr2.o] } { 358 unresolved $test1 359 unresolved $test2 360 set CC "$old_CC" 361 set CXX "$old_CXX" 362 return 363} 364 365# The i386-aout target is confused: the linker does not put the 366# sections where objdump finds them. I don't know which is wrong. 367setup_xfail "i*86-*-aout*" 368 369# These tests fail on the native MIPS ELF targets because the GP value 370# in the .reginfo section is not updated when the S-record version is 371# written out. The mips-elf target itself does not use a .reginfo section. 372setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-linux*" 373 374# The S-record linker doesn't do the magic TOC handling that XCOFF 375# linkers do. 376setup_xfail "*-*-aix*" "*-*-xcoff*" 377 378# The S-record linker is not supported for ARC. 379setup_xfail "arc*-*-*" 380 381# The S-record linker doesn't build ARM/Thumb stubs. 382setup_xfail "arm-*-coff" 383setup_xfail "arm-*-pe*" 384# setup_xfail "arm-*elf*" 385setup_xfail "arm*-*-linux*" 386 387# The S-record linker doesn't include the .{zda} sections. 388setup_xfail "v850*-*-elf" 389 390# The S-record linker doesn't handle Alpha Elf relaxation. 391setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" 392setup_xfail "alpha*-*-netbsd*" 393 394# The S-record linker hasn't any hope of coping with HPPA relocs. 395# Or MeP complex relocs. 396setup_xfail "hppa*-*-*" "mep-*-*" 397 398# The S-record linker doesn't handle IA64 Elf relaxation. 399setup_xfail "ia64-*-*" 400 401# The S-record linker doesn't support the special PE headers - the PE 402# emulation tries to write pe-specific information to the PE headers 403# in the output bfd, but it's not a PE bfd (it's an srec bfd) 404setup_xfail "*-*-cygwin*" "*-*-mingw*" "*-*-pe*" "*-*-winnt*" 405setup_xfail "score-*-*" 406 407# The S-record linker doesn't support Blackfin ELF FDPIC ABI. 408setup_xfail "bfin-*-linux-uclibc" 409 410# On tile, we appear to be getting some random-seeming zeroing or 24-bit 411# rightshifts (!) in the output when directly generating S-records from 412# the linker. Not clear what could be causing this but we don't 413# anticipate creating s-records (and could always use objcopy to 414# generate the format if need be). 415setup_xfail "tile*-*-*" 416 417run_srec_test $test1 "tmpdir/sr1.o tmpdir/sr2.o" 418 419# Now try linking a C++ program with global constructors and 420# destructors. Note that since we are not linking against any 421# libraries, this program won't actually work or anything. 422 423if { ![is_remote host] && [which $CXX] == 0 } { 424 untested $test2 425 set CC "$old_CC" 426 set CXX "$old_CXX" 427 return 428} 429 430if ![ld_compile "$CXX $CXXFLAGS -fno-exceptions" $srcdir/$subdir/sr3.cc tmpdir/sr3.o] { 431 unresolved $test2 432 set CC "$old_CC" 433 set CXX "$old_CXX" 434 return 435} 436 437# See above. 438setup_xfail "i*86-*-aout*" 439setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-linux*" 440setup_xfail "*-*-aix*" "*-*-xcoff*" 441setup_xfail "arc*-*-*" 442setup_xfail "arm*-*-*" 443setup_xfail "v850*-*-elf" 444setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" 445setup_xfail "alpha*-*-netbsd*" 446setup_xfail "hppa*-*-*" "mep-*-*" 447setup_xfail "ia64-*-*" 448setup_xfail "*-*-cygwin*" "*-*-mingw*" "*-*-pe*" "*-*-winnt*" 449setup_xfail "score-*-*" 450setup_xfail "bfin-*-linux-uclibc" 451setup_xfail "tile*-*-*" 452 453run_srec_test $test2 "tmpdir/sr3.o" 454 455set CC "$old_CC" 456set CXX "$old_CXX" 457