1# Expect script for ld-visibility tests
2#   Copyright (C) 2000-2017 Free Software Foundation, Inc.
3#
4# This file is part of the GNU Binutils.
5#
6# This program is free software; you can redistribute it and/or modify
7# it under the terms of the GNU General Public License as published by
8# the Free Software Foundation; either version 3 of the License, or
9# (at your option) any later version.
10#
11# This program is distributed in the hope that it will be useful,
12# but WITHOUT ANY WARRANTY; without even the implied warranty of
13# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14# GNU General Public License for more details.
15#
16# You should have received a copy of the GNU General Public License
17# along with this program; if not, write to the Free Software
18# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
19# MA 02110-1301, USA.
20#
21# Written by Ian Lance Taylor (ian@cygnus.com)
22#	     and H.J. Lu (hjl@gnu.org)
23#
24
25# Make sure that ld can generate ELF shared libraries with visibility.
26
27# This test can only be run on a couple of ELF platforms.
28# Square bracket expressions seem to confuse istarget.
29if { ![istarget hppa*64*-*-hpux*] \
30     && ![istarget hppa*-*-linux*] \
31     && ![istarget i?86-*-linux*] \
32     && ![istarget i?86-*-gnu*] \
33     && ![istarget *-*-nacl*] \
34     && ![istarget ia64-*-linux*] \
35     && ![istarget m68k-*-linux*] \
36     && ![istarget mips*-*-linux*] \
37     && ![istarget powerpc*-*-linux*] \
38     && ![istarget arm*-*-linux*] \
39     && ![istarget alpha*-*-linux*] \
40     && ![istarget sparc*-*-linux*] \
41     && ![istarget s390*-*-linux*] \
42     && ![istarget sh\[34\]*-*-linux*] \
43     && ![istarget x86_64-*-linux*] } {
44    return
45}
46
47if { [istarget *-*-linux*aout*] \
48     || [istarget *-*-linux*oldld*] } {
49    return
50}
51
52set test_list [lsort [glob -nocomplain $srcdir/$subdir/*.d]]
53foreach t $test_list {
54    # We need to strip the ".d", but can leave the dirname.
55    verbose [file rootname $t]
56    run_dump_test [file rootname $t]
57}
58
59# The remaining tests can only be run if ld generates native executables.
60if ![isnative] then {return}
61
62set tmpdir tmpdir
63set SHCFLAG ""
64set shared_needs_pic "no"
65set COMPRESS_LDFLAG "-Wl,--compress-debug-sections=zlib-gabi"
66
67if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
68
69    # AIX shared libraries do not seem to support useful features,
70    # like overriding the shared library function or letting the
71    # shared library refer to objects defined in the main program.  We
72    # avoid testing those features.
73    set SHCFLAG "-DXCOFF_TEST"
74
75    # The AIX 3.2.5 loader appears to randomly fail when loading
76    # shared libraries from NSF mounted partitions, so we avoid any
77    # potential problems by using a local directory.
78    catch {exec /bin/sh -c "echo $$"} pid
79    set tmpdir /usr/tmp/ld.$pid
80    catch "exec mkdir $tmpdir" exec_status
81
82    # On AIX, we need to explicitly export the symbols the shared
83    # library is going to provide, and need.
84    set file [open $tmpdir/xcoff.exp w]
85    puts $file shlibvar1
86    puts $file shlibvar2
87    puts $file shlib_shlibvar1
88    puts $file shlib_shlibvar2
89    puts $file shlib_shlibcall
90    puts $file shlib_shlibcalled
91    puts $file shlib_checkfunptr1
92    puts $file shlib_getfunptr1
93    puts $file shlib_check
94    close $file
95}
96
97if [istarget arm*-*-linux*] {
98    # On ARM section anchors can change the symbol pre-emptability for
99    # non-PIC shared libraries, causing these tests to fail.  Turn section
100    # anchors off.
101    set SHCFLAG "-fno-section-anchors"
102
103    # On targets that have MOVW the compiler will emit relocations which
104    # the linker doesn't support when compiling -shared without -fpic.  The
105    # test to find out whether we want to XFAIL the non-PIC tests requires
106    # a compile - so we pre-calculate it here.  We also note that this can
107    # only affect arm*-*-*eabi* targets as the old ABI doesn't support v7.
108    if [istarget arm*-*-*eabi*] {
109	set file [open $tmpdir/movw-detect.c w]
110	puts $file "void foo(void) { __asm (\"movw r0, #0\"); }"
111	close $file
112	if [run_host_cmd_yesno "$CC" "$CFLAGS -c $tmpdir/movw-detect.c -o $tmpdir/movw-detect.o"] {
113	    set shared_needs_pic "yes"
114	}
115    }
116}
117
118set support_protected "no"
119
120if { [istarget *-*-linux*]
121     || [istarget *-*-nacl*]
122     || [istarget *-*-gnu*] } {
123    if [ld_compile "$CC -g $CFLAGS -DPROTECTED_CHECK" $srcdir/$subdir/main.c $tmpdir/main.o] {
124      if [ld_simple_link $CC $tmpdir/main "$tmpdir/main.o"] {
125	catch "exec $tmpdir/main" support_protected
126      }
127    }
128}
129
130# The test procedure.
131proc visibility_test { visibility progname testname main sh1 sh2 dat args } {
132    global CC
133    global srcdir
134    global subdir
135    global exec_output
136    global link_output
137    global host_triplet
138    global tmpdir
139
140    if [llength $args] { set shldflags [lindex $args 0] } else { set shldflags "" }
141
142    # Build the shared library.
143    # On AIX, we need to use an export file.
144    set shared -shared
145    if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
146	set shared "-bM:SRE -bE:$tmpdir/xcoff.exp"
147    }
148    if {![ld_simple_link $CC $tmpdir/$progname.so "$shared $shldflags $tmpdir/$sh1 $tmpdir/$sh2"]} {
149	if { [ string match $visibility "hidden_undef" ]
150	     && [regexp "undefined reference to \`\.?visibility\'" $link_output]
151	     && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
152    	    pass "$testname"
153	} else { if { [ string match $visibility "protected_undef" ]
154	     && [regexp "undefined reference to \`\.?visibility\'" $link_output]
155	     && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
156    	    pass "$testname"
157	} else {
158	    fail "$testname"
159	}}
160    	return
161    }
162
163    # Link against the shared library.  Use -rpath so that the
164    # dynamic linker can locate the shared library at runtime.
165    # On AIX, we must include /lib in -rpath, as otherwise the loader
166    # can not find -lc.
167    set rpath $tmpdir
168    if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
169	set rpath /lib:$tmpdir
170    }
171    if ![ld_simple_link $CC $tmpdir/$progname "-Wl,-rpath,$rpath $tmpdir/$main $tmpdir/$progname.so"] {
172	if { [ string match $visibility "hidden" ]
173	     && [regexp "undefined reference to \`\.?visibility\'" $link_output]
174	     && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
175    	    pass "$testname"
176	} else { if { [ string match $visibility "hidden_undef_def" ]
177	     && [regexp "undefined reference to \`\.?visibility\'" $link_output]
178	     && [regexp "undefined reference to \`visibility_def\'" $link_output]
179	     && [regexp "undefined reference to \`\.?visibility_func\'" $link_output]
180	     && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
181    	    pass "$testname"
182	} else {
183    	    fail "$testname"
184	}}
185    	return
186    }
187
188    if { [ string match $visibility "hidden" ]
189	 || [ string match $visibility "hidden_undef" ]
190	 || [ string match $visibility "protected_undef" ] } {
191	fail "$testname"
192    }
193
194    # Run the resulting program
195    send_log "$tmpdir/$progname >$tmpdir/$progname.out\n"
196    verbose "$tmpdir/$progname >$tmpdir/$progname.out"
197    catch "exec $tmpdir/$progname >$tmpdir/$progname.out" exec_output
198    if ![string match "" $exec_output] then {
199	send_log "$exec_output\n"
200	verbose "$exec_output"
201	fail "$testname"
202    	return
203    }
204
205    send_log "diff $tmpdir/$progname.out $srcdir/$subdir/$dat.dat\n"
206    verbose "diff $tmpdir/$progname.out $srcdir/$subdir/$dat.dat"
207    catch "exec diff $tmpdir/$progname.out $srcdir/$subdir/$dat.dat" exec_output
208    set exec_output [prune_warnings $exec_output]
209
210    if {![string match "" $exec_output]} then {
211	send_log "$exec_output\n"
212	verbose "$exec_output"
213	fail "$testname"
214        return
215    }
216
217    pass "$testname"
218}
219
220proc visibility_run {visibility} {
221    global CC
222    global CFLAGS
223    global SHCFLAG
224    global srcdir
225    global subdir
226    global tmpdir
227    global picflag
228    global target_triplet
229    global support_protected
230    global shared_needs_pic
231    global PLT_CFLAGS
232    global COMPRESS_LDFLAG
233
234    if [ string match $visibility "hidden" ] {
235	set VSBCFLAG "-DHIDDEN_TEST"
236    } else { if [ string match $visibility "hidden_normal" ] {
237	set VSBCFLAG "-DHIDDEN_NORMAL_TEST"
238    } else { if [ string match $visibility "hidden_undef" ] {
239	set VSBCFLAG "-DHIDDEN_UNDEF_TEST"
240    } else { if [ string match $visibility "hidden_undef_def" ] {
241	set VSBCFLAG "-DHIDDEN_UNDEF_TEST -DDSO_DEFINE_TEST"
242    } else { if [ string match $visibility "hidden_weak" ] {
243	set VSBCFLAG "-DHIDDEN_WEAK_TEST"
244    } else { if [ string match $visibility "protected" ] {
245	set VSBCFLAG "-DPROTECTED_TEST"
246    } else { if [ string match $visibility "protected_undef" ] {
247	set VSBCFLAG "-DPROTECTED_UNDEF_TEST"
248    } else { if [ string match $visibility "protected_undef_def" ] {
249	set VSBCFLAG "-DPROTECTED_UNDEF_TEST -DDSO_DEFINE_TEST"
250    } else { if [ string match $visibility "protected_weak" ] {
251	set VSBCFLAG "-DPROTECTED_WEAK_TEST"
252    } else {
253	set VSBCFLAG ""
254    }}}}}}}}}
255
256    if { [istarget powerpc*-*-linux*] \
257	 || ( [istarget mips*-*-linux*] && [at_least_gcc_version 4 3] )} {
258	# Testing non-PIC libraries is a waste of effort on any target.
259	# If you don't pass -fpic or -fPIC to gcc, gcc will assume quite
260	# reasonably that you are not compiling for a shared library.
261	# It can then make optimisations that result in shared library
262	# functions and variables not being overridable.  Newer versions
263	# of gcc are more likely to do this.
264    } else {
265    # Compile the main program.  Make sure that PLT is used since PLT
266    # is expected.
267    if ![ld_compile "$CC -g $PLT_CFLAGS $CFLAGS $SHCFLAG $VSBCFLAG" $srcdir/$subdir/main.c $tmpdir/mainnp.o] {
268	unresolved "visibility ($visibility) (non PIC)"
269	unresolved "visibility ($visibility)"
270    } else {
271	# The shared library is composed of two files.  First compile them
272	# without using -fpic.  That should work on an ELF system,
273	# although it will be less efficient because the dynamic linker
274	# will need to do more relocation work.  However, note that not
275	# using -fpic will cause some of the tests to return different
276	# results.  Make sure that PLT is used since PLT is expected.
277	if { ![ld_compile "$CC -g $PLT_CFLAGS $CFLAGS $SHCFLAG $VSBCFLAG" $srcdir/$subdir/sh1.c $tmpdir/sh1np.o]
278	     || ![ld_compile "$CC -g $PLT_CFLAGS $CFLAGS $SHCFLAG $VSBCFLAG" $srcdir/$subdir/sh2.c $tmpdir/sh2np.o] } {
279	    unresolved "visibility ($visibility) (non PIC)"
280	} else { if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
281	    visibility_test $visibility vnp "visibility ($visibility) (non PIC)" mainnp.o sh1np.o sh2np.o xcoff
282	} else {
283	    # SunOS non PIC shared libraries don't permit some cases of
284	    # overriding.
285	    if { [ string match $visibility "protected" ]
286		 || [ string match $visibility "protected_undef_def" ] } {
287		if [ string match $support_protected "no" ] {
288		    setup_xfail $target_triplet
289		}
290	    } else {
291		setup_xfail "*-*-sunos4*"
292	    }
293
294	    # Non-pic code uses name binding rules for applications to
295	    # reference variables by gp-relative relocs, which can't be
296	    # used with overridable symbols.
297	    if { ![ string match $visibility "hidden_undef" ]
298		 && ![ string match $visibility "protected_undef" ] } {
299		setup_xfail "ia64-*-linux*"
300		setup_xfail "alpha*-*-linux*"
301	    }
302	    if { ![ string match $visibility "hidden" ]
303		 && ![ string match $visibility "hidden_undef" ]
304		 && ![ string match $visibility "hidden_undef_def" ]
305		 && ![ string match $visibility "protected_undef" ] } {
306		setup_xfail "s390x-*-linux*"
307		if { [istarget sparc*-*-linux*] && [is_elf64 $tmpdir/mainnp.o] } {
308		    setup_xfail "sparc*-*-linux*"
309		}
310	    }
311	    if { [is_elf64 $tmpdir/mainnp.o] } {
312		setup_xfail "x86_64-*-linux*"
313	    }
314	    setup_xfail "x86_64-*-linux-gnux32"
315	    if { ![istarget hppa*64*-*-linux*] } {
316		setup_xfail "hppa*-*-linux*"
317	    }
318	    if [ string match $shared_needs_pic "yes" ] {
319		setup_xfail "arm*-*-linux*"
320	    }
321
322	    visibility_test $visibility vnp "visibility ($visibility) (non PIC)" mainnp.o sh1np.o sh2np.o elfvsb
323
324	    # Test ELF shared library relocations with a non-zero load
325	    # address for the library.  Near as I can tell, the R_*_RELATIVE
326	    # relocations for various targets are broken in the case where
327	    # the load address is not zero (which is the default).
328	    if { [ string match $visibility "protected" ]
329		 || [ string match $visibility "protected_undef_def" ] } {
330		if [ string match $support_protected "no" ] {
331		    setup_xfail $target_triplet
332		}
333	    } else {
334		setup_xfail "*-*-sunos4*"
335		setup_xfail "*-*-linux*libc1"
336	    }
337	    if { [ string match $visibility "hidden_normal" ]
338		 || [ string match $visibility "hidden_weak" ]
339		 || [ string match $visibility "protected" ]
340		 || [ string match $visibility "protected_undef_def" ]
341		 || [ string match $visibility "protected_weak" ]
342		 || [ string match $visibility "normal" ] } {
343		setup_xfail "powerpc-*-linux*"
344		setup_xfail "s390x-*-linux*"
345		if { [istarget sparc*-*-linux*] && [is_elf64 $tmpdir/mainnp.o] } {
346		    setup_xfail "sparc*-*-linux*"
347		}
348	    }
349	    if { ![ string match $visibility "hidden_undef" ]
350		 && ![ string match $visibility "protected_undef" ] } {
351		setup_xfail "ia64-*-linux*"
352		setup_xfail "alpha*-*-linux*"
353		setup_xfail "mips*-*-linux*"
354	    }
355	    if { [is_elf64 $tmpdir/mainnp.o] } {
356		setup_xfail "x86_64-*-linux*"
357	    }
358	    setup_xfail "x86_64-*-linux-gnux32"
359	    if { ![istarget hppa*64*-*-linux*] } {
360		setup_xfail "hppa*-*-linux*"
361	    }
362	    if [ string match $shared_needs_pic "yes" ] {
363		setup_xfail "arm*-*-linux*"
364	    }
365
366	    visibility_test $visibility vnp "visibility ($visibility) (non PIC, load offset)" \
367		mainnp.o sh1np.o sh2np.o elfvsb \
368		"-T $srcdir/$subdir/elf-offset.ld"
369	} }
370
371	# Now compile the code using -fpic.
372
373	if { ![ld_compile "$CC -g $CFLAGS $SHCFLAG $VSBCFLAG -DSHARED $picflag" $srcdir/$subdir/sh1.c $tmpdir/sh1p.o]
374	    || ![ld_compile "$CC -g $CFLAGS $SHCFLAG $VSBCFLAG -DSHARED $picflag" $srcdir/$subdir/sh2.c $tmpdir/sh2p.o] } {
375	    unresolved "visibility ($visibility)"
376	} else {
377	    if { [ string match $visibility "protected" ]
378		 || [ string match $visibility "protected_undef_def" ] } {
379		if [ string match $support_protected "no" ] {
380		    setup_xfail $target_triplet
381		}
382	    }
383	    # SunOS can not compare function pointers correctly
384	    if [istarget "*-*-sunos4*"] {
385		visibility_test $visibility vp "visibility ($visibility)" mainnp.o sh1p.o sh2p.o sun4
386	    } else { if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
387		visibility_test $visibility vp "visibility ($visibility)" mainnp.o sh1p.o sh2p.o xcoff
388	    } else {
389		visibility_test $visibility vp "visibility ($visibility)" mainnp.o sh1p.o sh2p.o elfvsb $COMPRESS_LDFLAG
390	    } }
391	}
392    }}
393
394    if { [istarget powerpc*-*-linux*] } {
395	# Don't bother.
396    } else {
397    # Now do the same tests again, but this time compile main.c PIC.
398    if ![ld_compile "$CC -g $CFLAGS $SHCFLAG $VSBCFLAG -DSHARED $picflag" $srcdir/$subdir/main.c $tmpdir/mainp.o] {
399	unresolved "visibility ($visibility) (PIC main, non PIC so)"
400	unresolved "visibility ($visibility) (PIC main)"
401    } else {
402	if { [file exists $tmpdir/sh1np.o ] && [ file exists $tmpdir/sh2np.o ] } {
403	    if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
404		visibility_test $visibility vmpnp "visibility ($visibility) (PIC main, non PIC so)" mainp.o sh1np.o sh2np.o xcoff
405	    } else {
406		# SunOS non PIC shared libraries don't permit some cases of
407		# overriding.
408		if { [ string match $visibility "protected" ]
409		     || [ string match $visibility "protected_undef_def" ] } {
410		    if [ string match $support_protected "no" ] {
411			setup_xfail $target_triplet
412		    }
413		} else {
414		    setup_xfail "*-*-sunos4*"
415		}
416		if { ![ string match $visibility "hidden_undef" ]
417		     && ![ string match $visibility "protected_undef" ] } {
418		    setup_xfail "ia64-*-linux*"
419		    setup_xfail "alpha*-*-linux*"
420		}
421		if { ![ string match $visibility "hidden" ]
422		     && ![ string match $visibility "hidden_undef" ]
423		     && ![ string match $visibility "hidden_undef_def" ]
424		     && ![ string match $visibility "protected_undef" ] } {
425		    setup_xfail "s390x-*-linux*"
426		    if { [istarget sparc*-*-linux*] && [is_elf64 $tmpdir/mainp.o] } {
427			setup_xfail "sparc*-*-linux*"
428		    }
429		}
430		if { [is_elf64 $tmpdir/mainp.o] } {
431		    setup_xfail "x86_64-*-linux*"
432		}
433		setup_xfail "x86_64-*-linux-gnux32"
434		if { ![istarget hppa*64*-*-linux*] } {
435		    setup_xfail "hppa*-*-linux*"
436		}
437		if [ string match $shared_needs_pic "yes" ] {
438		    setup_xfail "arm*-*-linux*"
439		}
440
441		visibility_test $visibility vmpnp "visibility ($visibility) (PIC main, non PIC so)" mainp.o sh1np.o sh2np.o elfvsb
442	    }
443	} else {
444	    unresolved "visibility (PIC main, non PIC so)"
445	}
446
447	if { [file exists $tmpdir/sh1p.o ] && [ file exists $tmpdir/sh2p.o ] } {
448	    if { [ string match $visibility "protected" ]
449		 || [ string match $visibility "protected_undef_def" ] } {
450		if [ string match $support_protected "no" ] {
451		    setup_xfail $target_triplet
452		}
453	    }
454	    if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
455		visibility_test $visibility vmpp "visibility ($visibility) (PIC main)" mainp.o sh1p.o sh2p.o xcoff
456	    } else {
457		visibility_test $visibility vmpp "visibility ($visibility) (PIC main)" mainp.o sh1p.o sh2p.o elfvsb
458	    }
459	} else {
460	    unresolved "visibility ($visibility) (PIC main)"
461	}
462    }}
463}
464
465# Old version of GCC for MIPS default to enabling -fpic
466# and get confused if it is used on the command line.
467if { [istarget mips*-*-*] && ! [at_least_gcc_version 4 3] } then {
468    set picflag ""
469} else {
470    # Unfortunately, the gcc argument is -fpic and the cc argument is
471    # -KPIC.  We have to try both.
472    set picflag "-fpic"
473    send_log "$CC $picflag\n"
474    verbose "$CC $picflag"
475    catch "exec $CC $picflag" exec_output
476    send_log "$exec_output\n"
477    verbose "--" "$exec_output"
478    if { [string match "*illegal option*" $exec_output] \
479	 || [string match "*option ignored*" $exec_output] \
480	 || [string match "*unrecognized option*" $exec_output] \
481	 || [string match "*passed to ld*" $exec_output] } {
482	if [istarget *-*-sunos4*] {
483	    set picflag "-pic"
484	} else {
485	    set picflag "-KPIC"
486	}
487    }
488}
489verbose "Using $picflag to compile PIC code"
490
491visibility_run hidden
492visibility_run hidden_normal
493visibility_run hidden_undef
494visibility_run hidden_undef_def
495visibility_run hidden_weak
496visibility_run protected
497visibility_run protected_undef
498visibility_run protected_undef_def
499visibility_run protected_weak
500visibility_run normal
501
502if { ![ld_compile "$CC -g $CFLAGS" $srcdir/$subdir/common.c tmpdir/common.o] } {
503    unresolved "common hidden symbol"
504} else {
505    if ![ld_simple_link $ld tmpdir/common "tmpdir/common.o"] {
506	fail "common hidden symbol"
507    } else {
508	pass "common hidden symbol"
509    }
510}
511
512if { ![ld_compile "$CC -g $CFLAGS" $srcdir/$subdir/test.c tmpdir/test.o] } {
513    unresolved "weak hidden symbol"
514} else {
515   if { ![ld_compile "$CC -g $CFLAGS -DSHARED $picflag" $srcdir/$subdir/sh3.c tmpdir/sh3.o] } {
516	unresolved "weak hidden symbol"
517    } else {
518	if ![ld_simple_link $ld tmpdir/sh3.so "-shared tmpdir/sh3.o"] {
519	    fail "weak hidden symbol"
520	} else {
521	    if ![ld_simple_link $ld tmpdir/weak "tmpdir/test.o tmpdir/sh3.o"] {
522		fail "weak hidden symbol DSO last"
523	    } else {
524		pass "weak hidden symbol DSO last"
525	    }
526	    if ![ld_simple_link $ld tmpdir/weak "tmpdir/sh3.so tmpdir/test.o"] {
527		fail "weak hidden symbol DSO first"
528	    } else {
529		pass "weak hidden symbol DSO first"
530	    }
531	}
532    }
533}
534
535if { [istarget rs6000*-*-aix*] || [istarget powerpc*-*-aix*] } {
536    # Remove the temporary directory.
537    catch "exec rm -rf $tmpdir" exec_status
538}
539