1# Test linking directly to S-records. 2# By Ian Lance Taylor, Cygnus Support. 3# Copyright (C) 1999-2014 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 if [istarget sh64*-*-elf] { 245 # This is what gcc passes to ld by default. 246 set flags "$flags -mshelf32" 247 # SH64 targets cannot convert format in the linker 248 # using the -oformat command line switch. 249 setup_xfail "sh64*-*-*" 250 } 251 252 if {[istarget aarch64*-*-*] || \ 253 [istarget arm*-*-*]} { 254 # ARM targets cannot convert format in the linker 255 # using the --oformat command line switch 256 setup_xfail "aarch64-*-*" 257 setup_xfail "aarch64_be-*-*" 258 setup_xfail "arm*-*-*" 259 } 260 261 # V850 targets need libgcc.a 262 if [istarget v850*-*-elf] { 263 set objs "$objs -L ../gcc -lgcc" 264 } 265 266 # Xtensa ELF targets relax by default; S-Record linker does not 267 if [istarget xtensa*-*-*] { 268 set flags "$flags -no-relax" 269 } 270 271 # MSP430 targets always relax. 272 if [istarget msp430*-*-*] { 273 setup_xfail "msp430*-*-*" 274 } 275 276 # Epiphany needs some help too 277 if [istarget epiphany*-*-*] { 278 set flags "$flags --defsym _start=00000060" 279 setup_xfail "epiphany*-*-*" 280 } 281 282 if [istarget m681*-*-*] { 283 set flags "$flags --defsym _start=0xc000" 284 setup_xfail "m681*-*-*" 285 } 286 287 if [istarget m68hc1*-*-*] { 288 set flags "$flags --defsym _start=0xc000" 289 setup_xfail "m68hc1*-*-*" 290 } 291 292 if [istarget m9s12x*-*-*] { 293 set flags "$flags --defsym _start=0xc000" 294 setup_xfail "m9s12x*-*-*" 295 } 296 297 if { ![ld_simple_link $ld tmpdir/sr1 "$flags $objs"] \ 298 || ![ld_simple_link $ld tmpdir/sr2.sr "$flags --oformat srec $objs"] } { 299 fail $test 300 return 301 } 302 303 send_log "$objcopy -O srec tmpdir/sr1 tmpdir/sr1.sr\n" 304 set exec_output [run_host_cmd "$objcopy" "-O srec tmpdir/sr1 tmpdir/sr1.sr"] 305 set exec_output [prune_warnings $exec_output] 306 if ![string match "" $exec_output] { 307 send_log "$exec_output\n" 308 verbose "$exec_output" 309 unresolved $test 310 return 311 } 312 313 set f1 [open tmpdir/sr1.sr r] 314 set f2 [open tmpdir/sr2.sr r] 315 if [srec_compare $f1 $f2] { 316 pass $test 317 } else { 318 fail $test 319 } 320 close $f1 321 close $f2 322} 323 324set test1 "S-records" 325set test2 "S-records with constructors" 326 327# See whether the default linker script uses SIZEOF_HEADERS. 328set exec_output [run_host_cmd "$ld" "--verbose"] 329set sizeof_headers [string match "*SIZEOF_HEADERS*" $exec_output] 330 331# First test linking a C program. We don't require any libraries. We 332# link it normally, and objcopy to the S-record format, and then link 333# directly to the S-record format, and require that the two files 334# contain the same data. 335 336if { ![is_remote host] && [which $CC] == 0 } { 337 untested $test1 338 untested $test2 339 return 340} 341 342if { ![ld_compile $CC $srcdir/$subdir/sr1.c tmpdir/sr1.o] \ 343 || ![ld_compile $CC $srcdir/$subdir/sr2.c tmpdir/sr2.o] } { 344 unresolved $test1 345 unresolved $test2 346 return 347} 348 349# The i386-aout target is confused: the linker does not put the 350# sections where objdump finds them. I don't know which is wrong. 351setup_xfail "i*86-*-aout*" 352 353# These tests fail on the native MIPS ELF targets because the GP value 354# in the .reginfo section is not updated when the S-record version is 355# written out. The mips-elf target itself does not use a .reginfo section. 356setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-linux*" 357 358# The S-record linker doesn't do the magic TOC handling that XCOFF 359# linkers do. 360setup_xfail "*-*-aix*" "*-*-xcoff*" 361 362# The S-record linker doesn't build ARM/Thumb stubs. 363setup_xfail "arm-*-coff" 364setup_xfail "arm-*-pe*" 365# setup_xfail "arm-*elf*" 366setup_xfail "arm*-*-linux*" 367 368# The S-record linker doesn't include the .{zda} sections. 369setup_xfail "v850*-*-elf" 370 371# The S-record linker doesn't handle Alpha Elf relaxation. 372setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" 373setup_xfail "alpha*-*-netbsd*" 374 375# The S-record linker hasn't any hope of coping with HPPA relocs. 376# Or MeP complex relocs. 377setup_xfail "hppa*-*-*" "mep-*-*" 378 379# The S-record linker doesn't handle IA64 Elf relaxation. 380setup_xfail "ia64-*-*" 381 382# The S-record linker doesn't support the special PE headers - the PE 383# emulation tries to write pe-specific information to the PE headers 384# in the output bfd, but it's not a PE bfd (it's an srec bfd) 385setup_xfail "*-*-cygwin*" "*-*-mingw*" "*-*-pe*" "*-*-winnt*" 386setup_xfail "score-*-*" 387 388# The S-record linker doesn't support Blackfin ELF FDPIC ABI. 389setup_xfail "bfin-*-linux-uclibc" 390 391# On tile, we appear to be getting some random-seeming zeroing or 24-bit 392# rightshifts (!) in the output when directly generating S-records from 393# the linker. Not clear what could be causing this but we don't 394# anticipate creating s-records (and could always use objcopy to 395# generate the format if need be). 396setup_xfail "tile*-*-*" 397 398run_srec_test $test1 "tmpdir/sr1.o tmpdir/sr2.o" 399 400# Now try linking a C++ program with global constructors and 401# destructors. Note that since we are not linking against any 402# libraries, this program won't actually work or anything. 403 404if { ![is_remote host] && [which $CXX] == 0 } { 405 untested $test2 406 return 407} 408 409if ![ld_compile "$CXX $CXXFLAGS -fno-exceptions" $srcdir/$subdir/sr3.cc tmpdir/sr3.o] { 410 unresolved $test2 411 return 412} 413 414# See above. 415setup_xfail "i*86-*-aout*" 416setup_xfail "mips*-*-irix5*" "mips*-*-irix6*" "mips*-*-linux*" 417setup_xfail "*-*-aix*" "*-*-xcoff*" 418setup_xfail "arm*-*-*" 419setup_xfail "v850*-*-elf" 420setup_xfail "alpha*-*-elf*" "alpha*-*-linux-*" "alpha*-*-gnu*" 421setup_xfail "alpha*-*-netbsd*" 422setup_xfail "hppa*-*-*" "mep-*-*" 423setup_xfail "ia64-*-*" 424setup_xfail "*-*-cygwin*" "*-*-mingw*" "*-*-pe*" "*-*-winnt*" 425setup_xfail "score-*-*" 426setup_xfail "bfin-*-linux-uclibc" 427setup_xfail "tile*-*-*" 428 429run_srec_test $test2 "tmpdir/sr3.o" 430