1#   Copyright 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003,
2#   2004
3#   Free Software Foundation, Inc.
4
5# This program is free software; you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation; either version 2 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program; if not, write to the Free Software
17# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
18
19# Please email any bugs, comments, and/or additions to this file to:
20# bug-dejagnu@prep.ai.mit.edu
21
22# Written by Ian Lance Taylor <ian@cygnus.com>
23
24if ![is_remote host] {
25    if {[which $OBJCOPY] == 0} then {
26        perror "$OBJCOPY does not exist"
27        return
28    }
29}
30
31send_user "Version [binutil_version $OBJCOPY]"
32
33if ![is_remote host] {
34    set tempfile tmpdir/bintest.o
35    set copyfile tmpdir/copy
36} else {
37    set tempfile [remote_download host tmpdir/bintest.o]
38    set copyfile copy
39}
40
41# Test that objcopy does not modify a file when copying it.
42
43proc objcopy_test {testname srcfile} {
44    global OBJCOPY
45    global OBJCOPYFLAGS
46    global srcdir
47    global subdir
48    global tempfile
49    global copyfile
50
51    if {![binutils_assemble $srcdir/$subdir/${srcfile} tmpdir/bintest.o]} then {
52 	perror "unresolved $testname"
53	unresolved "objcopy ($testname)"
54	return
55    }
56
57    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS $tempfile ${copyfile}.o"]
58
59    if ![string match "" $got] then {
60	fail "objcopy ($testname)"
61    } else {
62	send_log "cmp $tempfile ${copyfile}.o\n"
63	verbose "cmp $tempfile ${copyfile}.o"
64	if [is_remote host] {
65	    set src1 tmpdir/bintest.o
66	    set src2 tmpdir/copy.o
67	    remote_upload host $tempfile $src1
68	    remote_upload host ${copyfile}.o $src2
69	} else {
70	    set src1 ${tempfile}
71	    set src2 ${copyfile}.o
72	}
73	set status [remote_exec build cmp "${src1} ${src2}"]
74	set exec_output [lindex $status 1]
75	set exec_output [prune_warnings $exec_output]
76
77	# On some systems the result of objcopy will not be identical.
78	# Usually this is just because gas isn't using bfd to write the
79	# files in the first place, and may order things a little
80	# differently. Those systems should use setup_xfail here.
81
82	setup_xfail "h8300-*-rtems*" "h8300-*-coff"
83	setup_xfail "h8500-*-rtems*" "h8500-*-coff"
84	setup_xfail "hppa*-*-*"
85	setup_xfail "i960-*"
86	setup_xfail "m68*-*-*coff" "m68*-*-hpux*" "m68*-*-lynxos*"
87	setup_xfail "m68*-*-sysv*" "m68*-apple-aux*"
88	setup_xfail "m8*-*"
89	setup_xfail "or32-*-rtems*" "or32-*-coff"
90	setup_xfail "sh-*-coff*" "sh-*-rtems*"
91	setup_xfail "tic4x-*-*" "tic80-*-*" "w65-*"
92
93	clear_xfail "hppa*64*-*-hpux*" "hppa*-*-linux*" "hppa*-*-lites*"
94	clear_xfail "hppa*-*-*n*bsd*" "hppa*-*-rtems*" "*-*-*elf*"
95	clear_xfail "m68*-*-sysv4*"
96
97	if [string match "" $exec_output] then {
98	    pass "objcopy ($testname)"
99	} else {
100	    send_log "$exec_output\n"
101	    verbose "$exec_output" 1
102
103	    # On OSF/1, this succeeds with gas and fails with /bin/as.
104	    setup_xfail "alpha*-*-osf*"
105
106	    # This fails for COFF i960-vxworks targets.
107	    setup_xfail "i960-*-vxworks*"
108
109	    fail "objcopy ($testname)"
110	}
111    }
112}
113
114objcopy_test "simple copy" bintest.s
115
116# Test generating S records.
117
118# We make the srec filename 8.3 compatible. Note that the header string
119# matched against depends on the name of the file. Ugh.
120
121if [is_remote host] {
122    set srecfile copy.sre
123    set header_string S00B0000636F70792E737265C1
124} else {
125    set srecfile ${copyfile}.srec
126    set header_string S0130000746D706469722F636F70792E7372656397
127}
128
129set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $tempfile ${srecfile}"]
130
131if ![string match "" $got] then {
132    fail "objcopy -O srec"
133} else {
134    if [is_remote host] {
135	remote_upload host ${srecfile} tmpdir/copy.srec
136	set srecfile tmpdir/copy.srec
137    }
138    set file [open ${srecfile} r]
139
140    # The first S record is fixed by the file name we are using.
141    gets $file line
142    send_log "$line\n"
143    verbose $line
144    if ![regexp "$header_string.*" $line] {
145	send_log "bad header\n"
146	fail "objcopy -O srec"
147    } else {
148	while {[gets $file line] != -1 \
149	       && [regexp "^S\[123\]\[0-9a-fA-F\]+\[\r\n\]*$" $line]} {
150	    send_log "$line\n"
151	    verbose $line
152	    set line "**EOF**"
153	}
154	send_log "$line\n"
155	verbose $line
156	if ![regexp "^S\[789\]\[0-9a-fA-F\]+\[\r\n\]*$" $line] then {
157	    send_log "bad trailer\n"
158	    fail "objcopy -O srec"
159	} else {
160	    if {[gets $file line] != -1} then {
161		send_log "garbage at end\n"
162		send_log "$line\n"
163		verbose $line
164		fail "objcopy -O srec"
165	    } else {
166		set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"]
167		if ![regexp "file format srec" $got] then {
168		    send_log "objdump failed\n"
169		    fail "objcopy -O srec"
170		} else {
171		    pass "objcopy -O srec"
172		}
173	    }
174	}
175    }
176
177    close $file
178}
179
180# Test setting and adjusting the start address.  We only test this
181# while generating S records, because we may not be able to set the
182# start address for other object file formats, and the S record case
183# is the only useful one anyhow.
184
185set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f $tempfile"]
186if ![regexp "start address (\[0-9a-fA-FxX\]+)" $got all origstart] then {
187    perror "objdump can not recognize bintest.o"
188    set origstart ""
189} else {
190    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec --set-start 0x7654 $tempfile ${copyfile}.srec"]
191    if ![string match "" $got] then {
192	fail "objcopy --set-start"
193    } else {
194	set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"]
195	if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then {
196	    fail "objcopy --set-start"
197	} else {
198	    if {$srecstart != 0x7654} then {
199		send_log "$srecstart != 0x7654\n"
200		fail "objcopy --set-start"
201	    } else {
202		pass "objcopy --set-start"
203	    }
204	}
205    }
206
207    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec --adjust-start 0x123 $tempfile ${copyfile}.srec"]
208    if ![string match "" $got] then {
209	fail "objcopy --adjust-start"
210    } else {
211	set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -f ${copyfile}.srec"]
212	if ![regexp "file format srec.*start address (\[0-9a-fA-FxX\]+)" $got all srecstart] then {
213	    fail "objcopy --adjust-start"
214	} else {
215	    if {$srecstart != $origstart + 0x123} then {
216		send_log "$srecstart != $origstart + 0x123\n"
217		fail "objcopy --adjust-start"
218	    } else {
219		pass "objcopy --adjust-start"
220	    }
221	}
222    }
223}
224
225# Test adjusting the overall VMA, and adjusting the VMA of a
226# particular section.  We again only test this when generating S
227# records.
228
229set low ""
230set lowname ""
231
232set headers [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h $tempfile"]
233
234set headers_regexp "\[ 	0-9\]+(\[^ 	\]+)\[ 	\]*(\[0-9a-fA-F\]+)\[ 	\]+\[0-9a-fA-F\]+\[ 	\]+(\[0-9a-fA-F\]+)\[ 	\]+\[0-9a-fA-F\]+\[ 	\]+2\[*\]\[*\]\[0-9\]+(.*)"
235
236set got $headers
237while {[regexp $headers_regexp $got all name size vma rest]} {
238    set vma 0x$vma
239    set size 0x$size
240    if {$size != 0} {
241	if {$low == "" || $vma < $low} {
242            set low $vma
243	    set lowname $name
244	}
245    }
246    set got $rest
247}
248
249if {$low == "" || $origstart == ""} then {
250    perror "objdump can not recognize bintest.o"
251} else {
252    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec --adjust-vma 0x123 $tempfile ${copyfile}.srec"]
253    if ![string match "" $got] then {
254        fail "objcopy --adjust-vma"
255    } else {
256	set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -fh ${copyfile}.srec"]
257	set want "file format srec.*start address\[ 	\]*(\[0-9a-fA-FxX\]+).*sec1\[ 	\]+\[0-9a-fA-F\]+\[ 	\]+(\[0-9a-fA-F\]+)"
258	if ![regexp $want $got all start vma] then {
259	    fail "objcopy --adjust-vma"
260	} else {
261	    set vma 0x$vma
262	    if {$vma != $low + 0x123} then {
263		send_log "$vma != $low + 0x123\n"
264		fail "objcopy --adjust-vma"
265	    } else {
266		if {$start != $origstart + 0x123} then {
267		    send_log "$start != $origstart + 0x123\n"
268		    fail "objcopy --adjust-vma"
269		} else {
270		    pass "objcopy --adjust-vma"
271		}
272	    }
273	}
274    }
275
276    set arg ""
277    set got $headers
278    while {[regexp $headers_regexp $got all name size vma rest]} {
279	set vma 0x$vma
280	if {$vma == $low} then {
281	    set arg "$arg --adjust-section-vma $name+4"
282	}
283	set got $rest
284    }
285
286    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $arg $tempfile ${copyfile}.srec"]
287    if ![string match "" $got] then {
288	fail "objcopy --adjust-section-vma +"
289    } else {
290	set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h ${copyfile}.srec"]
291	set want "file format srec.*sec1\[ 	\]+\[0-9a-fA-F\]+\[ 	\]+(\[0-9a-fA-F\]+)"
292	if ![regexp $want $got all vma] then {
293	    fail "objcopy --adjust-section-vma +"
294	} else {
295	    set vma 0x$vma
296	    if {$vma != $low + 4} then {
297		send_log "$vma != $low + 4\n"
298		fail "objcopy --adjust-section-vma +"
299	    } else {
300		pass "objcopy --adjust-section-vma +"
301	    }
302	}
303    }
304
305    regsub -all "\\+4" $arg "=[expr $low + 4]" argeq
306    set got [binutils_run $OBJCOPY "$OBJCOPYFLAGS -O srec $argeq $tempfile ${copyfile}.srec"]
307    if ![string match "" $got] then {
308	fail "objcopy --adjust-section-vma ="
309    } else {
310	set got [binutils_run $OBJDUMP "$OBJDUMPFLAGS -h ${copyfile}.srec"]
311	set want "file format srec.*sec1\[ 	\]+\[0-9a-fA-F\]+\[ 	\]+(\[0-9a-fA-F\]+)"
312	if ![regexp $want $got all vma] then {
313	    fail "objcopy --adjust-section-vma ="
314	} else {
315	    set vma 0x$vma
316	    if {$vma != $low + 4} then {
317		send_log "$vma != $low + 4\n"
318		fail "objcopy --adjust-section-vma ="
319	    } else {
320		pass "objcopy --adjust-section-vma ="
321	    }
322	}
323    }
324}
325
326# Test stripping an object.
327
328proc strip_test { } {
329    global AR
330    global CC
331    global STRIP
332    global STRIPFLAGS
333    global NM
334    global NMFLAGS
335    global srcdir
336    global subdir
337
338    set test "strip"
339
340    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } {
341	untested $test
342	return
343    }
344
345    if [is_remote host] {
346	set archive libstrip.a
347	set objfile [remote_download host tmpdir/testprog.o]
348	remote_file host delete $archive
349    } else {
350	set archive tmpdir/libstrip.a
351	set objfile tmpdir/testprog.o
352    }
353
354    remote_file build delete tmpdir/libstrip.a
355
356    set exec_output [binutils_run $AR "rc $archive ${objfile}"]
357    if ![string match "" $exec_output] {
358	fail $test
359	return
360    }
361
362    set exec_output [binutils_run $STRIP "$STRIPFLAGS $archive"]
363    if ![string match "" $exec_output] {
364	fail $test
365	return
366    }
367
368    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } {
369	untested $test
370	return
371    }
372
373    if [is_remote host] {
374	set objfile [remote_download host tmpdir/testprog.o]
375    } else {
376	set objfile tmpdir/testprog.o
377    }
378
379    set exec_output [binutils_run $STRIP "$STRIPFLAGS $objfile"]
380    if ![string match "" $exec_output] {
381	fail $test
382	return
383    }
384
385    set exec_output [binutils_run $NM "-a $NMFLAGS $objfile"]
386    if ![string match "*: no symbols*" $exec_output] {
387	fail $test
388	return
389    }
390
391    pass $test
392}
393
394strip_test
395
396# Test stripping an object file with saving a symbol
397
398proc strip_test_with_saving_a_symbol { } {
399    global CC
400    global STRIP
401    global STRIPFLAGS
402    global NM
403    global NMFLAGS
404    global srcdir
405    global subdir
406
407    set test "strip with saving a symbol"
408
409    if { [target_compile $srcdir/$subdir/testprog.c tmpdir/testprog.o object debug] != "" } {
410	untested $test
411	return
412    }
413
414    if [is_remote host] {
415	set objfile [remote_download host tmpdir/testprog.o]
416    } else {
417	set objfile tmpdir/testprog.o
418    }
419
420    set exec_output [binutils_run $STRIP "$STRIPFLAGS -K main -K _main $objfile"]
421    if ![string match "" $exec_output] {
422	fail $test
423	return
424    }
425
426    set exec_output [binutils_run $NM "$NMFLAGS $objfile"]
427    if {![regexp {^([0-9a-fA-F]+)?[ ]+[TD] main} $exec_output] \
428         && ![regexp {^([0-9a-fA-F]+)?[ ]+T _main} $exec_output]} {
429	fail $test
430	return
431    }
432
433    pass $test
434}
435
436strip_test_with_saving_a_symbol
437
438# Build a final executable.
439
440if { [istarget *-*-cygwin] || [istarget *-*-mingw32] } {
441    set test_prog "testprog.exe"
442} else {
443    set test_prog "testprog"
444}
445
446proc copy_setup { } {
447    global srcdir
448    global subdir
449    global gcc_gas_flag
450    global test_prog
451
452    set res [build_wrapper testglue.o]
453    set flags { debug }
454
455    if { $res != "" } {
456	lappend flags "additional_flags=[lindex $res 1]"
457	set add_libs "testglue.o"
458    } else {
459	set add_libs ""
460    }
461
462    if { [istarget *-*-linux*] } {
463	foreach i $gcc_gas_flag {
464	    set flags "additional_flags=$i $flags"
465	}
466    }
467    if { [target_compile "$srcdir/$subdir/testprog.c $add_libs" tmpdir/$test_prog executable $flags]  != "" } {
468	return 2
469    }
470
471    set result [remote_load target tmpdir/$test_prog]
472    set status [lindex $result 0]
473
474    if { $status != "pass"  } {
475	perror "unresolved setup, status = $status"
476	return 3
477    }
478
479    return 0
480}
481
482# Test copying an executable.
483
484proc copy_executable { prog flags test1 test2 } {
485    global test_prog
486
487    if [is_remote host] {
488	set testfile [remote_download host tmpdir/$test_prog]
489	set testcopy copyprog
490    } else {
491	set testfile tmpdir/$test_prog
492	set testcopy tmpdir/copyprog
493    }
494    remote_file host delete $testcopy
495
496    set exec_output [binutils_run $prog "$flags $testfile $testcopy"]
497
498    if ![string match "" $exec_output] {
499	fail $test1
500	fail $test2
501	return
502    }
503
504    if [is_remote host] {
505	remote_upload host $testcopy tmpdir/copyprog
506    }
507
508    set status [remote_exec build "cmp" "tmpdir/$test_prog tmpdir/copyprog"]
509    set exec_output [lindex $status 1]
510
511    if [string match "" $exec_output] then {
512	pass $test1
513    } else {
514	send_log "$exec_output\n"
515	verbose "$exec_output"
516
517	# This will fail for many reasons.  For example, it will most
518	# likely fail if a non-GNU linker is used.  Therefore, we do
519	# not insist that it pass.  If you are using an assembler and
520	# linker based on the same BFD as objcopy, it is worth
521	# investigating to see why this failure occurs.  If we are
522	# cross compiling, we assume that a GNU linker is being used,
523	# and expect it to succeed.
524	if {[isnative]} then {
525	    setup_xfail "*-*-*"
526	}
527
528	# This also fails for mips*-*-elf targets.  See elf32-mips.c
529	# mips_elf_sym_is_global.
530	setup_xfail "mips*-*-elf"
531
532	setup_xfail "*arm*-*-coff"
533	setup_xfail "xscale-*-coff"
534	setup_xfail "arm*-*-pe"
535	setup_xfail "thumb*-*-coff"
536	setup_xfail "thumb*-*-pe"
537
538	fail $test1
539    }
540
541    set output [remote_load target tmpdir/copyprog]
542    set status [lindex $output 0]
543    if { $status != "pass" } {
544	fail $test2
545    } else {
546	pass $test2
547    }
548}
549
550# Test stripping an executable
551
552proc strip_executable { prog flags test } {
553    global NM
554    global NMFLAGS
555
556    remote_download build tmpdir/copyprog tmpdir/striprog
557    if [is_remote host] {
558	set copyfile [remote_download host tmpdir/striprog]
559    } else {
560	set copyfile tmpdir/striprog
561    }
562
563    set exec_output [binutils_run $prog "$flags ${copyfile}"]
564    if ![string match "" $exec_output] {
565	fail $test
566	return
567    }
568
569    if [is_remote host] {
570	remote_upload host ${copyfile} tmpdir/striprog
571    }
572
573    set result [remote_load target tmpdir/striprog]
574    set status [lindex $result 0]
575    if { $status != "pass" } {
576	fail $test
577        return
578    }
579
580    set exec_output [binutils_run $NM "$NMFLAGS ${copyfile}"]
581    if ![string match "*: no symbols*" $exec_output] {
582	fail $test
583	return
584    }
585    pass $test
586}
587
588# Test stripping an executable with saving a symbol
589
590proc strip_executable_with_saving_a_symbol { prog flags test } {
591    global NM
592    global NMFLAGS
593
594    remote_download build tmpdir/copyprog tmpdir/striprog
595    if [is_remote host] {
596	set copyfile [remote_download host tmpdir/striprog]
597    } else {
598	set copyfile tmpdir/striprog
599    }
600
601    set exec_output [binutils_run $prog "$flags ${copyfile}"]
602    if ![string match "" $exec_output] {
603	fail $test
604	return
605    }
606
607    if [is_remote host] {
608	remote_upload host ${copyfile} tmpdir/striprog
609    }
610
611    set result [remote_load target tmpdir/striprog]
612    set status [lindex $result 0]
613    if { $status != "pass" } {
614	fail $test
615        return
616    }
617
618    set exec_output [binutils_run $NM "$NMFLAGS ${copyfile}"]
619    if { [istarget mmix-knuth-mmixware] } {
620	# Whenever there's a symbol in the mmo format, there's the symbol
621	# Main, so remove it manually from the expected output for sake of
622	# this test.
623
624	# Using "" not {} to get the \n and \r translated.
625	regsub "^\[0-9a-fA-F\]+\[ \]+T Main\[\n\r\]+" $exec_output "" exec_output
626    }
627
628    if {![regexp {^([0-9a-fA-F]+)?[ ]+[TD] main} $exec_output] \
629         && ![regexp {^([0-9a-fA-F]+)?[ ]+[TD] _main} $exec_output]} {
630	fail $test
631	return
632    }
633    pass $test
634}
635
636set test1 "simple objcopy of executable"
637set test2 "run objcopy of executable"
638set test3 "run stripped executable"
639set test4 "run stripped executable with saving a symbol"
640
641switch [copy_setup] {
642    "1" {
643	# do nothing
644    }
645    "2" {
646	untested $test1
647	untested $test2
648	untested $test3
649	untested $test4
650    }
651    "3" {
652	unresolved $test1
653	unresolved $test2
654	unresolved $test3
655	unresolved $test4
656    }
657    "0" {
658	copy_executable "$OBJCOPY" "$OBJCOPYFLAGS" "$test1" "$test2"
659	strip_executable "$STRIP" "$STRIPFLAGS" "$test3"
660	strip_executable_with_saving_a_symbol "$STRIP" "-K main -K _main $STRIPFLAGS" "$test4"
661    }
662}
663
664proc objcopy_test_readelf {testname srcfile} {
665    global OBJCOPY
666    global OBJCOPYFLAGS
667    global READELF
668    global srcdir
669    global subdir
670
671    if {![binutils_assemble $srcdir/$subdir/${srcfile} tmpdir/bintest.o]} then {
672	unresolved "objcopy ($testname)"
673	return
674    }
675
676    verbose -log "$OBJCOPY $OBJCOPYFLAGS tmpdir/bintest.o tmpdir/copy.o"
677    catch "exec $OBJCOPY $OBJCOPYFLAGS tmpdir/bintest.o tmpdir/copy.o" exec_output
678    if ![string match "" $exec_output] then {
679	fail "objcopy ($testname)"
680	return;
681    }
682
683    verbose -log "$READELF -a tmpdir/bintest.o > tmpdir/bintest.o.out"
684    catch "exec $READELF -a tmpdir/bintest.o > tmpdir/bintest.o.out" exec_output
685    set exec_output [prune_warnings $exec_output]
686    if ![string match "" $exec_output] then {
687	unresolved "objcopy ($testname)"
688	return
689    }
690
691    verbose -log "$READELF -a tmpdir/copy.o > tmpdir/copy.o.out"
692    catch "exec $READELF -a tmpdir/copy.o > tmpdir/copy.o.out" exec_output
693    set exec_output [prune_warnings $exec_output]
694    if ![string match "" $exec_output] then {
695	unresolved "objcopy ($testname)"
696	return
697    }
698
699    verbose -log "diff tmpdir/bintest.o.out tmpdir/copy.o.out"
700    catch "exec diff tmpdir/bintest.o.out tmpdir/copy.o.out" exec_output
701    set exec_output [prune_warnings $exec_output]
702
703    if [string match "" $exec_output] then {
704	pass "objcopy ($testname)"
705    } else {
706	fail "objcopy ($testname)"
707    }
708}
709
710# ia64 specific tests
711if { ([istarget "ia64-*-elf*"]
712       || [istarget "ia64-*-linux*"]) } {
713    objcopy_test "ia64 link order" link-order.s
714}
715
716# ELF specific tests
717if [is_elf_format] {
718    objcopy_test "ELF unknown section type" unknown.s
719    objcopy_test_readelf "ELF group" group.s
720}
721