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