summaryrefslogtreecommitdiff
path: root/ld/testsuite/ld-vsb
diff options
context:
space:
mode:
authorClément Chigot <clement.chigot@atos.net>2021-11-23 15:41:35 +0100
committerClément Chigot <clement.chigot@atos.net>2022-01-12 09:08:21 +0100
commit59e31fd742a53e8404039e1c4be4ba192672287c (patch)
tree3ac11fa165478f180af35f30b59811d816288fba /ld/testsuite/ld-vsb
parent09d4578fd96e7ceb262628cf27d8d9d8b903b529 (diff)
ld/testsuite: prepare ld-elfvsb to support XCOFF
A following patch will add visibility support in ld for XCOFF. Thus, ld-elfvsb is renamed ld-vsb and a suffix is added to files targeting only ELF format. ld/ChangeLog: * testsuite/ld-elfvsb: rename as ld-vsb. * testsuite/ld-elfvsb/hidden0.d: move to ld-vsb and rename with suffix -elf.d. * testsuite/ld-elfvsb/hidden1.d: Likewise. * testsuite/ld-elfvsb/hidden2.d: Likewise. * testsuite/ld-elfvsb/internal0.d: Likewise. * testsuite/ld-elfvsb/internal1.d: Likewise. * testsuite/ld-elfvsb/protected0.d: Likewise. * testsuite/ld-elfvsb/protected1.d: Likewise.
Diffstat (limited to 'ld/testsuite/ld-vsb')
-rw-r--r--ld/testsuite/ld-vsb/common.c14
-rw-r--r--ld/testsuite/ld-vsb/define.s10
-rw-r--r--ld/testsuite/ld-vsb/elf-offset.ld173
-rw-r--r--ld/testsuite/ld-vsb/elfvsb.dat26
-rw-r--r--ld/testsuite/ld-vsb/hidden0-elf.d9
-rw-r--r--ld/testsuite/ld-vsb/hidden1-elf.d8
-rw-r--r--ld/testsuite/ld-vsb/hidden2-elf.d9
-rw-r--r--ld/testsuite/ld-vsb/hidden2.ld7
-rw-r--r--ld/testsuite/ld-vsb/hidden2.s5
-rw-r--r--ld/testsuite/ld-vsb/internal0-elf.d10
-rw-r--r--ld/testsuite/ld-vsb/internal1-elf.d9
-rw-r--r--ld/testsuite/ld-vsb/main.c306
-rw-r--r--ld/testsuite/ld-vsb/protected0-elf.d10
-rw-r--r--ld/testsuite/ld-vsb/protected1-elf.d9
-rw-r--r--ld/testsuite/ld-vsb/sh1.c421
-rw-r--r--ld/testsuite/ld-vsb/sh2.c61
-rw-r--r--ld/testsuite/ld-vsb/sh3.c7
-rw-r--r--ld/testsuite/ld-vsb/test.c26
-rw-r--r--ld/testsuite/ld-vsb/undef.s3
-rw-r--r--ld/testsuite/ld-vsb/vsb.exp479
20 files changed, 1602 insertions, 0 deletions
diff --git a/ld/testsuite/ld-vsb/common.c b/ld/testsuite/ld-vsb/common.c
new file mode 100644
index 0000000000..0432a07915
--- /dev/null
+++ b/ld/testsuite/ld-vsb/common.c
@@ -0,0 +1,14 @@
+int foo;
+__asm__ (".hidden foo");
+
+int
+_start (void)
+{
+ return foo;
+}
+
+int
+__start (void)
+{
+ return _start ();
+}
diff --git a/ld/testsuite/ld-vsb/define.s b/ld/testsuite/ld-vsb/define.s
new file mode 100644
index 0000000000..b38e3e0c05
--- /dev/null
+++ b/ld/testsuite/ld-vsb/define.s
@@ -0,0 +1,10 @@
+ .data
+ .globl protected
+ .type protected,"object"
+protected:
+ .globl hidden
+ .type hidden,"object"
+hidden:
+ .globl internal
+ .type internal,"object"
+internal:
diff --git a/ld/testsuite/ld-vsb/elf-offset.ld b/ld/testsuite/ld-vsb/elf-offset.ld
new file mode 100644
index 0000000000..b60861a8d8
--- /dev/null
+++ b/ld/testsuite/ld-vsb/elf-offset.ld
@@ -0,0 +1,173 @@
+SECTIONS
+{
+ /* Read-only sections, merged into text segment: */
+ . = 0x100000;
+ .hash : { *(.hash) }
+ .dynsym : { *(.dynsym) }
+ .dynstr : { *(.dynstr) }
+ .gnu.version : { *(.gnu.version) }
+ .gnu.version_d : { *(.gnu.version_d) }
+ .gnu.version_r : { *(.gnu.version_r) }
+ .rel.text :
+ {
+ *(.rel.text)
+ *(.rel.text.*)
+ *(.rel.gnu.linkonce.t*)
+ }
+ .rela.text :
+ {
+ *(.rela.text)
+ *(.rela.text.*)
+ *(.rela.gnu.linkonce.t*)
+ }
+ .rel.data :
+ {
+ *(.rel.data)
+ *(.rel.data.*)
+ *(.rel.gnu.linkonce.d*)
+ }
+ .rela.data :
+ {
+ *(.rela.data)
+ *(.rela.data.*)
+ *(.rela.gnu.linkonce.d*)
+ }
+ .rel.rodata :
+ {
+ *(.rel.rodata)
+ *(.rel.rodata.*)
+ *(.rel.gnu.linkonce.r*)
+ }
+ .rela.rodata :
+ {
+ *(.rela.rodata)
+ *(.rela.rodata.*)
+ *(.rela.gnu.linkonce.r*)
+ }
+ .rel.got : { *(.rel.got) }
+ .rela.got : { *(.rela.got) }
+ .rel.toc : { *(.rel.toc) }
+ .rela.toc : { *(.rela.toc) }
+ .rel.ctors : { *(.rel.ctors) }
+ .rela.ctors : { *(.rela.ctors) }
+ .rel.dtors : { *(.rel.dtors) }
+ .rela.dtors : { *(.rela.dtors) }
+ .rel.init : { *(.rel.init) }
+ .rela.init : { *(.rela.init) }
+ .rel.fini : { *(.rel.fini) }
+ .rela.fini : { *(.rela.fini) }
+ .rel.bss : { *(.rel.bss) }
+ .rela.bss : { *(.rela.bss) }
+ .rel.plt : { *(.rel.plt) }
+ .rela.plt : { *(.rela.plt) }
+ .rel.eh_frame : { *(.rel.eh_frame) }
+ .rela.eh_frame : { *(.rela.eh_frame) }
+ .init : { KEEP (*(.init)) }
+ .plt : { *(.plt) }
+ .text :
+ {
+ *(.text)
+ *(.text.*)
+ *(.stub)
+ /* .gnu.warning sections are handled specially by elf.em. */
+ *(.gnu.warning)
+ *(.gnu.linkonce.t*)
+ }
+ _etext = .;
+ PROVIDE (etext = .);
+ .fini : { KEEP (*(.fini)) } =0x9090
+ .rodata :
+ {
+ *(.rodata)
+ *(.rodata.*)
+ *(.gnu.linkonce.r*)
+ }
+ .rodata1 : { *(.rodata1) }
+ /* Adjust the address for the data segment. We want to adjust up to
+ the same address within the page on the next page up. */
+ . = ALIGN(0x1000) + (. & (0x1000 - 1));
+ .data :
+ {
+ *(.data)
+ *(.data.*)
+ *(.gnu.linkonce.d*)
+ SORT(CONSTRUCTORS)
+ }
+ .data1 : { *(.data1) }
+ .ctors :
+ {
+ /* gcc uses crtbegin.o to find the start of the constructors, so
+ we make sure it is first. Because this is a wildcard, it
+ doesn't matter if the user does not actually link against
+ crtbegin.o; the linker won't look for a file to match a
+ wildcard. The wildcard also means that it doesn't matter which
+ directory crtbegin.o is in. */
+ KEEP (*crtbegin.o(.ctors))
+ KEEP (*(SORT(.ctors.*)))
+ KEEP (*(.ctors))
+ }
+ .dtors :
+ {
+ KEEP (*crtbegin.o(.dtors))
+ KEEP (*(SORT(.dtors.*)))
+ KEEP (*(.dtors))
+ }
+ .got : { *(.got.plt) *(.got) }
+ .toc : { *(.toc) }
+ .dynamic : { *(.dynamic) }
+ /* We want the small data sections together, so single-instruction offsets
+ can access them all, and initialized data all before uninitialized, so
+ we can shorten the on-disk segment size. */
+ .sdata : { *(.sdata) *(.sdata.*) }
+ _edata = .;
+ PROVIDE (edata = .);
+ __bss_start = .;
+ .sbss : { *(.sbss) *(.scommon) }
+ .bss :
+ {
+ *(.dynbss)
+ *(.bss)
+ *(COMMON)
+ /* Align here to ensure that the .bss section occupies space up to
+ _end. Align after .bss to ensure correct alignment even if the
+ .bss section disappears because there are no input sections. */
+ . = ALIGN(. != 0 ? 32 / 8 : 1);
+ }
+ . = ALIGN(32 / 8);
+ _end = . ;
+ PROVIDE (end = .);
+ /* Stabs debugging sections. */
+ .stab 0 : { *(.stab) }
+ .stabstr 0 : { *(.stabstr) }
+ .stab.excl 0 : { *(.stab.excl) }
+ .stab.exclstr 0 : { *(.stab.exclstr) }
+ .stab.index 0 : { *(.stab.index) }
+ .stab.indexstr 0 : { *(.stab.indexstr) }
+ .comment 0 : { *(.comment) }
+ /* DWARF debug sections.
+ Symbols in the DWARF debugging sections are relative to the beginning
+ of the section so we begin them at 0. */
+ /* DWARF 1 */
+ .debug 0 : { *(.debug) }
+ .line 0 : { *(.line) }
+ /* GNU DWARF 1 extensions */
+ .debug_srcinfo 0 : { *(.debug_srcinfo) }
+ .debug_sfnames 0 : { *(.debug_sfnames) }
+ /* DWARF 1.1 and DWARF 2 */
+ .debug_aranges 0 : { *(.debug_aranges) }
+ .debug_pubnames 0 : { *(.debug_pubnames) }
+ /* DWARF 2 */
+ .debug_info 0 : { *(.debug_info) }
+ .debug_abbrev 0 : { *(.debug_abbrev) }
+ .debug_line 0 : { *(.debug_line) }
+ .debug_frame 0 : { *(.debug_frame) }
+ .debug_str 0 : { *(.debug_str) }
+ .debug_loc 0 : { *(.debug_loc) }
+ .debug_macinfo 0 : { *(.debug_macinfo) }
+ /* SGI/MIPS DWARF 2 extensions */
+ .debug_weaknames 0 : { *(.debug_weaknames) }
+ .debug_funcnames 0 : { *(.debug_funcnames) }
+ .debug_typenames 0 : { *(.debug_typenames) }
+ .debug_varnames 0 : { *(.debug_varnames) }
+ /* These must appear regardless of . */
+}
diff --git a/ld/testsuite/ld-vsb/elfvsb.dat b/ld/testsuite/ld-vsb/elfvsb.dat
new file mode 100644
index 0000000000..bad3b1ec14
--- /dev/null
+++ b/ld/testsuite/ld-vsb/elfvsb.dat
@@ -0,0 +1,26 @@
+mainvar == 1
+overriddenvar == 2
+shlibvar1 == 3
+shlib_mainvar () == 1
+shlib_overriddenvar () == 2
+shlib_shlibvar1 () == 3
+shlib_shlibvar2 () == 4
+shlib_shlibcall () == 5
+shlib_shlibcall2 () == 8
+shlib_maincall () == 6
+main_called () == 6
+shlib_checkfunptr1 (shlib_shlibvar1) == 1
+shlib_checkfunptr2 (main_called) == 1
+shlib_getfunptr1 () == shlib_shlibvar1
+shlib_getfunptr2 () == main_called
+shlib_check () == 1
+visibility_check () == 1
+visibility_checkfunptr () == 1
+main_visibility_check () == 1
+visibility_checkvar () == 1
+visibility_checkvarptr () == 1
+main_visibility_checkvar () == 1
+main_visibility_checkcom () == 1
+shlib_visibility_checkcom () == 1
+main_visibility_checkweak () == 1
+shlib_visibility_checkweak () == 1
diff --git a/ld/testsuite/ld-vsb/hidden0-elf.d b/ld/testsuite/ld-vsb/hidden0-elf.d
new file mode 100644
index 0000000000..abd26a2b22
--- /dev/null
+++ b/ld/testsuite/ld-vsb/hidden0-elf.d
@@ -0,0 +1,9 @@
+#source: define.s
+#source: undef.s
+#ld: -r
+#readelf: -s
+
+Symbol table '.symtab' contains .* entries:
+#...
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +GLOBAL +HIDDEN +. hidden
+#pass
diff --git a/ld/testsuite/ld-vsb/hidden1-elf.d b/ld/testsuite/ld-vsb/hidden1-elf.d
new file mode 100644
index 0000000000..7820c21450
--- /dev/null
+++ b/ld/testsuite/ld-vsb/hidden1-elf.d
@@ -0,0 +1,8 @@
+#source: undef.s
+#ld: -r
+#readelf: -s
+
+Symbol table '.symtab' contains .* entries:
+#...
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +NOTYPE +GLOBAL +HIDDEN +UND hidden
+#pass
diff --git a/ld/testsuite/ld-vsb/hidden2-elf.d b/ld/testsuite/ld-vsb/hidden2-elf.d
new file mode 100644
index 0000000000..5d299746f5
--- /dev/null
+++ b/ld/testsuite/ld-vsb/hidden2-elf.d
@@ -0,0 +1,9 @@
+#source: hidden2.s
+#ld: -shared -T hidden2.ld --hash-style=sysv
+#readelf: -Ds
+# It is also ok to remove this symbol, but we currently make it local.
+
+Symbol table for image contains [0-9]+ entries:
+#...
+[ ]*[0-9]+: [0-9a-fA-F]* +0 +OBJECT +LOCAL +DEFAULT .* foo
+#pass
diff --git a/ld/testsuite/ld-vsb/hidden2.ld b/ld/testsuite/ld-vsb/hidden2.ld
new file mode 100644
index 0000000000..3c414dba48
--- /dev/null
+++ b/ld/testsuite/ld-vsb/hidden2.ld
@@ -0,0 +1,7 @@
+SECTIONS
+{
+ . = 0x1000;
+ PROVIDE (foo = .);
+ .data : { *(.data) }
+ .dynamic : { *(.dynamic) }
+}
diff --git a/ld/testsuite/ld-vsb/hidden2.s b/ld/testsuite/ld-vsb/hidden2.s
new file mode 100644
index 0000000000..62f110702d
--- /dev/null
+++ b/ld/testsuite/ld-vsb/hidden2.s
@@ -0,0 +1,5 @@
+ .data
+ .hidden foo
+ .global foo
+ .type foo,%object
+ .dc.a foo
diff --git a/ld/testsuite/ld-vsb/internal0-elf.d b/ld/testsuite/ld-vsb/internal0-elf.d
new file mode 100644
index 0000000000..9d37ae8e66
--- /dev/null
+++ b/ld/testsuite/ld-vsb/internal0-elf.d
@@ -0,0 +1,10 @@
+#source: define.s
+#source: undef.s
+#ld: -r
+#readelf: -s
+
+Symbol table '.symtab' contains .* entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+#...
+ +[0-9]+: [0-9a-fA-F]+ +0 +OBJECT +GLOBAL +INTERNAL +. internal
+#pass
diff --git a/ld/testsuite/ld-vsb/internal1-elf.d b/ld/testsuite/ld-vsb/internal1-elf.d
new file mode 100644
index 0000000000..5cacdafed8
--- /dev/null
+++ b/ld/testsuite/ld-vsb/internal1-elf.d
@@ -0,0 +1,9 @@
+#source: undef.s
+#ld: -r
+#readelf: -s
+
+Symbol table '.symtab' contains .* entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+#...
+ +[0-9]+: [0-9a-fA-F]+ +0 +NOTYPE +GLOBAL +INTERNAL +UND internal
+#pass
diff --git a/ld/testsuite/ld-vsb/main.c b/ld/testsuite/ld-vsb/main.c
new file mode 100644
index 0000000000..c2c9291134
--- /dev/null
+++ b/ld/testsuite/ld-vsb/main.c
@@ -0,0 +1,306 @@
+#ifdef PROTECTED_CHECK
+#include <features.h>
+#include <stdio.h>
+
+int
+main (void)
+{
+#if defined (__GLIBC__) && (__GLIBC__ > 2 \
+ || (__GLIBC__ == 2 \
+ && __GLIBC_MINOR__ >= 2))
+ puts ("yes");
+#else
+ puts ("no");
+#endif
+ return 0;
+}
+#else
+/* This is the main program for the shared library test. */
+
+#include <stdio.h>
+
+int mainvar = 1;
+int overriddenvar = 2;
+extern int shlibvar1;
+
+extern int shlib_mainvar ();
+extern int shlib_overriddenvar ();
+extern int shlib_shlibvar1 ();
+extern int shlib_shlibvar2 ();
+extern int shlib_shlibcall ();
+extern int shlib_maincall ();
+extern int shlib_checkfunptr1 ();
+extern int shlib_checkfunptr2 ();
+extern int (*shlib_getfunptr1 ()) ();
+extern int (*shlib_getfunptr2 ()) ();
+extern int shlib_check ();
+extern int shlib_shlibcall2 ();
+extern int visibility_check ();
+extern int visibility_checkfunptr ();
+extern void *visibility_funptr ();
+extern int visibility_checkvar ();
+extern int visibility_checkvarptr ();
+extern int visibility_varval ();
+extern void *visibility_varptr ();
+extern int shlib_visibility_checkcom ();
+extern int shlib_visibility_checkweak ();
+
+int shlib_visibility_com = 1;
+
+int shlib_visibility_var_weak = 1;
+
+int
+shlib_visibility_func_weak ()
+{
+ return 1;
+}
+
+#ifdef HIDDEN_WEAK_TEST
+#define WEAK_TEST
+#endif
+
+#ifdef PROTECTED_WEAK_TEST
+#define WEAK_TEST
+#endif
+
+#ifdef PROTECTED_UNDEF_TEST
+#define PROTECTED_TEST
+#endif
+
+#ifndef WEAK_TEST
+extern int visibility ();
+extern int visibility_var;
+#endif
+
+#if !defined (HIDDEN_TEST) && defined (PROTECTED_TEST)
+int
+visibility (void)
+{
+ return 1;
+}
+
+static int
+main_visibility_check (void)
+{
+ return ((int (*) (void)) visibility_funptr ()) != visibility;
+}
+
+int visibility_var = 1;
+
+static int
+main_visibility_checkvar (void)
+{
+ return visibility_varval () != visibility_var
+ && visibility_varptr () != &visibility_var;
+}
+
+#ifndef PROTECTED_UNDEF_TEST
+int shared_data = 1;
+__asm__ (".protected shared_data");
+
+int
+shared_func (void)
+{
+ return 1;
+}
+
+__asm__ (".protected shared_func");
+
+extern int * shared_data_p ();
+typedef int (*func) ();
+extern func shared_func_p ();
+#endif
+#else
+static int
+main_visibility_check (void)
+{
+#ifdef WEAK_TEST
+ return visibility_funptr () == NULL;
+#else
+ return ((int (*) (void)) visibility_funptr ()) == visibility;
+#endif
+}
+
+static int
+main_visibility_checkvar (void)
+{
+#ifdef WEAK_TEST
+ return visibility_varval () == 0
+ && visibility_varptr () == NULL;
+#else
+ return visibility_varval () == visibility_var
+ && visibility_varptr () == &visibility_var;
+#endif
+}
+#endif
+
+/* This function is called by the shared library. */
+
+int
+main_called (void)
+{
+ return 6;
+}
+
+/* This function overrides a function in the shared library. */
+
+int
+shlib_overriddencall2 (void)
+{
+ return 8;
+}
+
+#ifdef HIDDEN_NORMAL_TEST
+int visibility_com;
+__asm__ (".hidden visibility_com");
+
+int
+main_visibility_checkcom (void)
+{
+ return visibility_com == 0;
+}
+
+int
+main_visibility_checkweak (void)
+{
+ return 1;
+}
+#elif defined (HIDDEN_WEAK_TEST)
+int
+main_visibility_checkcom (void)
+{
+ return 1;
+}
+
+#pragma weak visibility_undef_var_weak
+extern int visibility_undef_var_weak;
+__asm__ (".hidden visibility_undef_var_weak");
+
+#pragma weak visibility_undef_func_weak
+extern int visibility_undef_func_weak ();
+__asm__ (".hidden visibility_undef_func_weak");
+
+#pragma weak visibility_var_weak
+extern int visibility_var_weak;
+__asm__ (".hidden visibility_var_weak");
+
+#pragma weak visibility_func_weak
+extern int visibility_func_weak ();
+__asm__ (".hidden visibility_func_weak");
+
+int
+main_visibility_checkweak ()
+{
+ return &visibility_undef_var_weak == NULL
+ && &visibility_undef_func_weak == NULL
+ && &visibility_func_weak == NULL
+ && &visibility_var_weak == NULL;
+}
+#elif defined (HIDDEN_UNDEF_TEST)
+extern int visibility_def;
+__asm__ (".hidden visibility_def");
+extern int visibility_func ();
+__asm__ (".hidden visibility_func");
+
+int
+main_visibility_checkcom (void)
+{
+ return visibility_def == 2;
+}
+
+int
+main_visibility_checkweak (void)
+{
+ return visibility_func () == 2;
+}
+#else
+int
+main_visibility_checkcom (void)
+{
+ return 1;
+}
+
+int
+main_visibility_checkweak (void)
+{
+ return 1;
+}
+#endif
+
+int
+main (void)
+{
+ int (*p) ();
+ int ret = 0;
+
+ printf ("mainvar == %d\n", mainvar);
+ printf ("overriddenvar == %d\n", overriddenvar);
+ printf ("shlibvar1 == %d\n", shlibvar1);
+#ifndef XCOFF_TEST
+ printf ("shlib_mainvar () == %d\n", shlib_mainvar ());
+ printf ("shlib_overriddenvar () == %d\n", shlib_overriddenvar ());
+#endif
+ printf ("shlib_shlibvar1 () == %d\n", shlib_shlibvar1 ());
+ printf ("shlib_shlibvar2 () == %d\n", shlib_shlibvar2 ());
+ printf ("shlib_shlibcall () == %d\n", shlib_shlibcall ());
+#ifndef XCOFF_TEST
+ printf ("shlib_shlibcall2 () == %d\n", shlib_shlibcall2 ());
+ printf ("shlib_maincall () == %d\n", shlib_maincall ());
+#endif
+ printf ("main_called () == %d\n", main_called ());
+ printf ("shlib_checkfunptr1 (shlib_shlibvar1) == %d\n",
+ shlib_checkfunptr1 (shlib_shlibvar1));
+#ifndef XCOFF_TEST
+ printf ("shlib_checkfunptr2 (main_called) == %d\n",
+ shlib_checkfunptr2 (main_called));
+#endif
+ p = shlib_getfunptr1 ();
+ printf ("shlib_getfunptr1 () ");
+ if (p == shlib_shlibvar1)
+ printf ("==");
+ else
+ printf ("!=");
+ printf (" shlib_shlibvar1\n");
+#ifndef XCOFF_TEST
+ p = shlib_getfunptr2 ();
+ printf ("shlib_getfunptr2 () ");
+ if (p == main_called)
+ printf ("==");
+ else
+ printf ("!=");
+ printf (" main_called\n");
+#endif
+ printf ("shlib_check () == %d\n", shlib_check ());
+ printf ("visibility_check () == %d\n", visibility_check ());
+ printf ("visibility_checkfunptr () == %d\n",
+ visibility_checkfunptr ());
+ printf ("main_visibility_check () == %d\n", main_visibility_check ());
+ printf ("visibility_checkvar () == %d\n", visibility_checkvar ());
+ printf ("visibility_checkvarptr () == %d\n",
+ visibility_checkvarptr ());
+ printf ("main_visibility_checkvar () == %d\n",
+ main_visibility_checkvar ());
+ printf ("main_visibility_checkcom () == %d\n",
+ main_visibility_checkcom ());
+ printf ("shlib_visibility_checkcom () == %d\n",
+ shlib_visibility_checkcom ());
+ printf ("main_visibility_checkweak () == %d\n",
+ main_visibility_checkweak ());
+ printf ("shlib_visibility_checkweak () == %d\n",
+ shlib_visibility_checkweak ());
+
+#if !defined (PROTECTED_UNDEF_TEST) && defined (PROTECTED_TEST)
+ if (&shared_data != shared_data_p ())
+ ret = 1;
+ p = shared_func_p ();
+ if (shared_func != p)
+ ret = 1;
+ if (shared_data != *shared_data_p ())
+ ret = 1;
+ if (shared_func () != (*p) () )
+ ret = 1;
+#endif
+
+ return ret;
+}
+#endif
diff --git a/ld/testsuite/ld-vsb/protected0-elf.d b/ld/testsuite/ld-vsb/protected0-elf.d
new file mode 100644
index 0000000000..ea781dd3db
--- /dev/null
+++ b/ld/testsuite/ld-vsb/protected0-elf.d
@@ -0,0 +1,10 @@
+#source: define.s
+#source: undef.s
+#ld: -r
+#readelf: -s
+
+Symbol table '.symtab' contains .* entries:
+ +Num: +Value +Size +Type +Bind +Vis +Ndx +Name
+#...
+ +[0-9]+: [0-9a-fA-F]* +0 +OBJECT +GLOBAL +PROTECTED +. protected
+#pass
diff --git a/ld/testsuite/ld-vsb/protected1-elf.d b/ld/testsuite/ld-vsb/protected1-elf.d
new file mode 100644
index 0000000000..235db0011a
--- /dev/null
+++ b/ld/testsuite/ld-vsb/protected1-elf.d
@@ -0,0 +1,9 @@
+#source: undef.s
+#ld: -r
+#readelf: -s
+
+Symbol table '.symtab' contains .* entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx +Name
+#...
+ +[0-9]+: [0-9a-fA-F]* +0 +NOTYPE +GLOBAL +PROTECTED +UND protected
+#pass
diff --git a/ld/testsuite/ld-vsb/sh1.c b/ld/testsuite/ld-vsb/sh1.c
new file mode 100644
index 0000000000..1aba63c754
--- /dev/null
+++ b/ld/testsuite/ld-vsb/sh1.c
@@ -0,0 +1,421 @@
+#ifndef NULL
+#define NULL ((void *) 0)
+#endif
+
+/* This is part of the shared library ld test. This file becomes part
+ of a shared library. */
+
+/* This variable is supplied by the main program. */
+#ifndef XCOFF_TEST
+extern int mainvar;
+#endif
+
+/* This variable is defined in the shared library, and overridden by
+ the main program. */
+#ifndef XCOFF_TEST
+#ifdef SHARED
+/* SHARED is defined if we are compiling with -fpic/-fPIC. */
+int overriddenvar = -1;
+#else
+/* Without -fpic, newer versions of gcc assume that we are not
+ compiling for a shared library, and thus that overriddenvar is
+ local. */
+extern int overriddenvar;
+#endif
+#endif
+
+/* This variable is defined in the shared library. */
+int shlibvar1 = 3;
+
+/* This variable is defined by another object in the shared library. */
+extern int shlibvar2;
+
+/* These functions return the values of the above variables as seen in
+ the shared library. */
+
+#ifndef XCOFF_TEST
+int
+shlib_mainvar ()
+{
+ return mainvar;
+}
+#endif
+
+#ifndef XCOFF_TEST
+int
+shlib_overriddenvar ()
+{
+ return overriddenvar;
+}
+#endif
+
+int
+shlib_shlibvar1 ()
+{
+ return shlibvar1;
+}
+
+int
+shlib_shlibvar2 ()
+{
+ return shlibvar2;
+}
+
+/* This function calls a function defined by another object in the
+ shared library. */
+
+extern int shlib_shlibcalled ();
+
+int
+shlib_shlibcall ()
+{
+ return shlib_shlibcalled ();
+}
+
+#ifndef XCOFF_TEST
+/* This function calls a function defined in this object in the shared
+ library. The main program will override the called function. */
+
+extern int shlib_overriddencall2 ();
+
+int
+shlib_shlibcall2 ()
+{
+ return shlib_overriddencall2 ();
+}
+
+#ifdef SHARED
+int
+shlib_overriddencall2 ()
+{
+ return 7;
+}
+#endif
+#endif
+
+/* This function calls a function defined by the main program. */
+
+#ifndef XCOFF_TEST
+extern int main_called ();
+
+int
+shlib_maincall ()
+{
+ return main_called ();
+}
+#endif
+
+/* This function is passed a function pointer to shlib_mainvar. It
+ confirms that the pointer compares equally. */
+
+int
+shlib_checkfunptr1 (p)
+ int (*p) ();
+{
+ return p == shlib_shlibvar1;
+}
+
+/* This function is passed a function pointer to main_called. It
+ confirms that the pointer compares equally. */
+
+#ifndef XCOFF_TEST
+int
+shlib_checkfunptr2 (p)
+ int (*p) ();
+{
+ return p == main_called;
+}
+#endif
+
+/* This function returns a pointer to shlib_mainvar. */
+
+int
+(*shlib_getfunptr1 ()) ()
+{
+ return shlib_shlibvar1;
+}
+
+/* This function returns a pointer to main_called. */
+
+#ifndef XCOFF_TEST
+int
+(*shlib_getfunptr2 ()) ()
+{
+ return main_called;
+}
+#endif
+
+/* This function makes sure that constant data and local functions
+ work. */
+
+#ifndef __STDC__
+#define const
+#endif
+
+static int i = 6;
+static const char *str = "Hello, world\n";
+
+int
+shlib_check ()
+{
+ const char *s1, *s2;
+
+ if (i != 6)
+ return 0;
+
+ /* To isolate the test, don't rely on any external functions, such
+ as strcmp. */
+ s1 = "Hello, world\n";
+ s2 = str;
+ while (*s1 != '\0')
+ if (*s1++ != *s2++)
+ return 0;
+ if (*s2 != '\0')
+ return 0;
+
+ if (shlib_shlibvar1 () != 3)
+ return 0;
+
+ return 1;
+}
+
+#ifdef HIDDEN_WEAK_TEST
+#define HIDDEN_UNDEF_TEST
+#define WEAK_TEST
+#endif
+
+#ifdef PROTECTED_WEAK_TEST
+#define PROTECTED_UNDEF_TEST
+#define WEAK_TEST
+#endif
+
+#if defined (HIDDEN_UNDEF_TEST) || defined (PROTECTED_UNDEF_TEST)
+#ifdef WEAK_TEST
+#pragma weak visibility
+#endif
+extern int visibility ();
+#else
+int
+visibility ()
+{
+ return 2;
+}
+#endif
+
+#ifdef HIDDEN_NORMAL_TEST
+__asm__ (".hidden visibility_normal");
+
+int
+visibility_normal ()
+{
+ return 2;
+}
+#endif
+
+int
+visibility_checkfunptr ()
+{
+#ifdef WEAK_TEST
+ return 1;
+#else
+#ifdef HIDDEN_NORMAL_TEST
+ int (*v) () = visibility_normal;
+#else
+ int (*v) () = visibility;
+#endif
+ return (*v) () == 2;
+#endif
+}
+
+int
+visibility_check ()
+{
+#ifdef WEAK_TEST
+ if (&visibility)
+ return visibility () == 1;
+ else
+ return 1;
+#else
+#ifdef HIDDEN_NORMAL_TEST
+ return visibility_normal () == 2;
+#else
+ return visibility () == 2;
+#endif
+#endif
+}
+
+void *
+visibility_funptr ()
+{
+#ifdef WEAK_TEST
+ if (&visibility == NULL)
+ return NULL;
+ else
+#endif
+ return visibility;
+}
+
+#if defined (HIDDEN_UNDEF_TEST) || defined (PROTECTED_UNDEF_TEST)
+#ifdef WEAK_TEST
+#pragma weak visibility_var
+#endif
+extern int visibility_var;
+#else
+int visibility_var = 2;
+#endif
+
+#ifdef HIDDEN_NORMAL_TEST
+__asm__ (".hidden visibility_var_normal");
+
+int visibility_var_normal = 2;
+#endif
+
+int
+visibility_checkvarptr ()
+{
+#ifdef WEAK_TEST
+ if (&visibility_var)
+ return visibility_var == 1;
+ else
+ return 1;
+#else
+#ifdef HIDDEN_NORMAL_TEST
+ int *v = &visibility_var_normal;
+#else
+ int *v = &visibility_var;
+#endif
+ return *v == 2;
+#endif
+}
+
+int
+visibility_checkvar ()
+{
+#ifdef WEAK_TEST
+ return 1;
+#else
+#ifdef HIDDEN_NORMAL_TEST
+ return visibility_var_normal == 2;
+#else
+ return visibility_var == 2;
+#endif
+#endif
+}
+
+void *
+visibility_varptr ()
+{
+#ifdef WEAK_TEST
+ if (&visibility_var == NULL)
+ return NULL;
+ else
+#endif
+ return &visibility_var;
+}
+
+int
+visibility_varval ()
+{
+#ifdef WEAK_TEST
+ if (&visibility_var == NULL)
+ return 0;
+ else
+#endif
+ return visibility_var;
+}
+
+#if defined (HIDDEN_TEST) || defined (HIDDEN_UNDEF_TEST)
+__asm__ (".hidden visibility");
+__asm__ (".hidden visibility_var");
+#else
+#if defined (PROTECTED_TEST) || defined (PROTECTED_UNDEF_TEST) || defined (PROTECTED_WEAK_TEST)
+__asm__ (".protected visibility");
+__asm__ (".protected visibility_var");
+#endif
+#endif
+
+#ifdef HIDDEN_NORMAL_TEST
+int shlib_visibility_com;
+__asm__ (".hidden shlib_visibility_com");
+
+int
+shlib_visibility_checkcom ()
+{
+ return shlib_visibility_com == 0;
+}
+
+int
+shlib_visibility_checkweak ()
+{
+ return 1;
+}
+#elif defined (HIDDEN_WEAK_TEST)
+#pragma weak shlib_visibility_undef_var_weak
+extern int shlib_visibility_undef_var_weak;
+__asm__ (".hidden shlib_visibility_undef_var_weak");
+
+#pragma weak shlib_visibility_undef_func_weak
+extern int shlib_visibility_undef_func_weak ();
+__asm__ (".hidden shlib_visibility_undef_func_weak");
+
+#pragma weak shlib_visibility_var_weak
+extern int shlib_visibility_var_weak;
+__asm__ (".hidden shlib_visibility_var_weak");
+
+#pragma weak shlib_visibility_func_weak
+extern int shlib_visibility_func_weak ();
+__asm__ (".hidden shlib_visibility_func_weak");
+
+int
+shlib_visibility_checkcom ()
+{
+ return 1;
+}
+
+int
+shlib_visibility_checkweak ()
+{
+ return &shlib_visibility_undef_var_weak == NULL
+ && &shlib_visibility_undef_func_weak == NULL
+ && &shlib_visibility_func_weak == NULL
+ && &shlib_visibility_var_weak == NULL;
+}
+#else
+int
+shlib_visibility_checkcom ()
+{
+ return 1;
+}
+
+int
+shlib_visibility_checkweak ()
+{
+ return 1;
+}
+#endif
+
+#ifdef PROTECTED_TEST
+#ifdef SHARED
+int shared_data = 100;
+#else
+extern int shared_data;
+#endif
+
+int *
+shared_data_p ()
+{
+ return &shared_data;
+}
+
+int
+shared_func ()
+{
+ return 100;
+}
+
+void *
+shared_func_p ()
+{
+ return shared_func;
+}
+#endif
diff --git a/ld/testsuite/ld-vsb/sh2.c b/ld/testsuite/ld-vsb/sh2.c
new file mode 100644
index 0000000000..e9a9687bcc
--- /dev/null
+++ b/ld/testsuite/ld-vsb/sh2.c
@@ -0,0 +1,61 @@
+/* This is part of the shared library ld test. This file becomes part
+ of a shared library. */
+
+/* This variable is defined here, and referenced by another file in
+ the shared library. */
+int shlibvar2 = 4;
+
+/* This variable is defined here, and shouldn't be used to resolve a
+ reference with non-default visibility in another shared library. */
+int visibility_com = 2;
+
+/* This function is called by another file in the shared library. */
+
+int
+shlib_shlibcalled ()
+{
+ return 5;
+}
+
+#ifdef DSO_DEFINE_TEST
+int
+visibility ()
+{
+ return 2;
+}
+
+int visibility_var = 2;
+
+int visibility_def = 2;
+
+int
+visibility_func ()
+{
+ return 2;
+}
+#endif
+
+#ifdef HIDDEN_WEAK_TEST
+int visibility_var_weak = 2;
+
+int
+visibility_func_weak ()
+{
+ return 2;
+}
+#endif
+
+#ifndef SHARED
+# ifndef XCOFF_TEST
+int overriddenvar = -1;
+
+int
+shlib_overriddencall2 ()
+{
+ return 7;
+}
+# endif
+# ifdef PROTECTED_TEST
+int shared_data = 100;
+# endif
+#endif
diff --git a/ld/testsuite/ld-vsb/sh3.c b/ld/testsuite/ld-vsb/sh3.c
new file mode 100644
index 0000000000..a6d5dc8863
--- /dev/null
+++ b/ld/testsuite/ld-vsb/sh3.c
@@ -0,0 +1,7 @@
+int main_hidden_data = 1;
+
+int
+main_hidden_func ()
+{
+ return 1;
+}
diff --git a/ld/testsuite/ld-vsb/test.c b/ld/testsuite/ld-vsb/test.c
new file mode 100644
index 0000000000..d2210accc6
--- /dev/null
+++ b/ld/testsuite/ld-vsb/test.c
@@ -0,0 +1,26 @@
+#pragma weak main_hidden_data
+extern int main_hidden_data;
+__asm__ (".hidden main_hidden_data");
+
+#pragma weak main_hidden_func
+extern int main_hidden_func ();
+__asm__ (".hidden main_hidden_func");
+
+int
+_start (void)
+{
+ int ret = 0;
+
+ if (&main_hidden_data != 0)
+ ret = 1;
+ if (main_hidden_func != 0)
+ ret = 1;
+
+ return ret;
+}
+
+int
+__start (void)
+{
+ return _start ();
+}
diff --git a/ld/testsuite/ld-vsb/undef.s b/ld/testsuite/ld-vsb/undef.s
new file mode 100644
index 0000000000..5b99d6f6fc
--- /dev/null
+++ b/ld/testsuite/ld-vsb/undef.s
@@ -0,0 +1,3 @@
+ .protected protected
+ .hidden hidden
+ .internal internal
diff --git a/ld/testsuite/ld-vsb/vsb.exp b/ld/testsuite/ld-vsb/vsb.exp
new file mode 100644
index 0000000000..52a7d6b5f7
--- /dev/null
+++ b/ld/testsuite/ld-vsb/vsb.exp
@@ -0,0 +1,479 @@
+# Expect script for ld-visibility tests
+# Copyright (C) 2000-2022 Free Software Foundation, Inc.
+#
+# This file is part of the GNU Binutils.
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation; either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program; if not, write to the Free Software
+# Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
+# MA 02110-1301, USA.
+#
+# Written by Ian Lance Taylor (ian@cygnus.com)
+# and H.J. Lu (hjl@gnu.org)
+#
+
+# Make sure that ld can generate ELF shared libraries with visibility.
+
+# Check to see if the C compiler works
+if { ![check_compiler_available] } {
+ return
+}
+
+# This test can only be run on a couple of ELF platforms.
+# Square bracket expressions seem to confuse istarget.
+if { ![istarget hppa*64*-*-hpux*] \
+ && ![istarget hppa*-*-linux*] \
+ && ![istarget i?86-*-linux*] \
+ && ![istarget i?86-*-gnu*] \
+ && ![istarget *-*-nacl*] \
+ && ![istarget ia64-*-linux*] \
+ && ![istarget m68k-*-linux*] \
+ && ![istarget mips*-*-linux*] \
+ && ![istarget powerpc*-*-linux*] \
+ && ![istarget arm*-*-linux*] \
+ && ![istarget alpha*-*-linux*] \
+ && ![istarget sparc*-*-linux*] \
+ && ![istarget s390*-*-linux*] \
+ && ![istarget sh\[34\]*-*-linux*] \
+ && ![istarget x86_64-*-linux*] } {
+ return
+}
+
+set test_list [lsort [glob -nocomplain $srcdir/$subdir/*-elf.d]]
+foreach t $test_list {
+ # We need to strip the ".d", but can leave the dirname.
+ verbose [file rootname $t]
+ run_dump_test [file rootname $t]
+}
+
+set tmpdir tmpdir
+set SHCFLAG ""
+set shared_needs_pic "no"
+set COMPRESS_LDFLAG "-Wl,--compress-debug-sections=zlib-gabi"
+
+if [istarget arm*-*-linux*] {
+ # On ARM section anchors can change the symbol pre-emptability for
+ # non-PIC shared libraries, causing these tests to fail. Turn section
+ # anchors off.
+ set SHCFLAG "-fno-section-anchors"
+
+ # On targets that have MOVW the compiler will emit relocations which
+ # the linker doesn't support when compiling -shared without -fpic. The
+ # test to find out whether we want to XFAIL the non-PIC tests requires
+ # a compile - so we pre-calculate it here. We also note that this can
+ # only affect arm*-*-*eabi* targets as the old ABI doesn't support v7.
+ if [istarget arm*-*-*eabi*] {
+ set file [open $tmpdir/movw-detect.c w]
+ puts $file "void foo(void) { __asm (\"movw r0, #0\"); }"
+ close $file
+ if [run_host_cmd_yesno "$CC_FOR_TARGET" "$CFLAGS_FOR_TARGET -c $tmpdir/movw-detect.c -o $tmpdir/movw-detect.o"] {
+ set shared_needs_pic "yes"
+ }
+ }
+}
+
+set support_protected "no"
+
+if { [istarget *-*-linux*]
+ || [istarget *-*-nacl*]
+ || [istarget *-*-gnu*] } {
+ if [ld_compile "$CC_FOR_TARGET -g -DPROTECTED_CHECK" $srcdir/$subdir/main.c $tmpdir/main.o] {
+ if [ld_link $CC_FOR_TARGET $tmpdir/main "$tmpdir/main.o"] {
+ catch "exec $tmpdir/main" support_protected
+ }
+ }
+}
+
+# The test procedure.
+proc visibility_test { visibility progname testname main sh1 sh2 dat args } {
+ global CC_FOR_TARGET
+ global srcdir
+ global subdir
+ global exec_output
+ global link_output
+ global host_triplet
+ global tmpdir
+
+ if [llength $args] { set shldflags [lindex $args 0] } else { set shldflags "" }
+
+ # Build the shared library.
+ set shared -shared
+ if { [is_elf_format] && [check_shared_lib_support] } {
+ append shared " -Wl,-z,notext"
+ }
+ if {![ld_link $CC_FOR_TARGET $tmpdir/$progname.so "$shared $shldflags $tmpdir/$sh1 $tmpdir/$sh2"]} {
+ if { [ string match $visibility "hidden_undef" ]
+ && [regexp "undefined reference to \`\.?visibility\'" $link_output]
+ && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
+ pass "$testname"
+ } else { if { [ string match $visibility "protected_undef" ]
+ && [regexp "undefined reference to \`\.?visibility\'" $link_output]
+ && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
+ pass "$testname"
+ } else {
+ fail "$testname"
+ }}
+ return
+ }
+
+ # Link against the shared library. Use -rpath so that the
+ # dynamic linker can locate the shared library at runtime.
+ set rpath $tmpdir
+ if ![ld_link $CC_FOR_TARGET $tmpdir/$progname "-Wl,-rpath,$rpath $tmpdir/$main $tmpdir/$progname.so"] {
+ if { [ string match $visibility "hidden" ]
+ && [regexp "undefined reference to \`\.?visibility\'" $link_output]
+ && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
+ pass "$testname"
+ } else { if { [ string match $visibility "hidden_undef_def" ]
+ && [regexp "undefined reference to \`\.?visibility\'" $link_output]
+ && [regexp "undefined reference to \`visibility_def\'" $link_output]
+ && [regexp "undefined reference to \`\.?visibility_func\'" $link_output]
+ && [regexp "undefined reference to \`visibility_var\'" $link_output] } {
+ pass "$testname"
+ } else {
+ fail "$testname"
+ }}
+ return
+ }
+
+ if { [ string match $visibility "hidden" ]
+ || [ string match $visibility "hidden_undef" ]
+ || [ string match $visibility "protected_undef" ] } {
+ fail "$testname"
+ }
+
+ if ![isnative] {
+ unsupported "$testname"
+ return
+ }
+
+ # Run the resulting program
+ send_log "$tmpdir/$progname >$tmpdir/$progname.out\n"
+ verbose "$tmpdir/$progname >$tmpdir/$progname.out"
+ catch "exec $tmpdir/$progname >$tmpdir/$progname.out" exec_output
+ if ![string match "" $exec_output] then {
+ send_log "$exec_output\n"
+ verbose "$exec_output"
+ fail "$testname"
+ return
+ }
+
+ send_log "diff $tmpdir/$progname.out $srcdir/$subdir/$dat.dat\n"
+ verbose "diff $tmpdir/$progname.out $srcdir/$subdir/$dat.dat"
+ catch "exec diff $tmpdir/$progname.out $srcdir/$subdir/$dat.dat" exec_output
+ set exec_output [prune_warnings $exec_output]
+
+ if {![string match "" $exec_output]} then {
+ send_log "$exec_output\n"
+ verbose "$exec_output"
+ fail "$testname"
+ return
+ }
+
+ pass "$testname"
+}
+
+proc visibility_run {visibility} {
+ global CC_FOR_TARGET
+ global SHCFLAG
+ global srcdir
+ global subdir
+ global tmpdir
+ global picflag
+ global target_triplet
+ global support_protected
+ global shared_needs_pic
+ global PLT_CFLAGS
+ global NOPIE_CFLAGS
+ global COMPRESS_LDFLAG
+ global NOSANITIZE_CFLAGS
+ global NOLTO_CFLAGS
+
+ if [ string match $visibility "hidden" ] {
+ set VSBCFLAG "-DHIDDEN_TEST"
+ } else { if [ string match $visibility "hidden_normal" ] {
+ set VSBCFLAG "-DHIDDEN_NORMAL_TEST"
+ } else { if [ string match $visibility "hidden_undef" ] {
+ set VSBCFLAG "-DHIDDEN_UNDEF_TEST"
+ } else { if [ string match $visibility "hidden_undef_def" ] {
+ set VSBCFLAG "-DHIDDEN_UNDEF_TEST -DDSO_DEFINE_TEST"
+ } else { if [ string match $visibility "hidden_weak" ] {
+ set VSBCFLAG "-DHIDDEN_WEAK_TEST"
+ } else { if [ string match $visibility "protected" ] {
+ set VSBCFLAG "-DPROTECTED_TEST"
+ } else { if [ string match $visibility "protected_undef" ] {
+ set VSBCFLAG "-DPROTECTED_UNDEF_TEST"
+ } else { if [ string match $visibility "protected_undef_def" ] {
+ set VSBCFLAG "-DPROTECTED_UNDEF_TEST -DDSO_DEFINE_TEST"
+ } else { if [ string match $visibility "protected_weak" ] {
+ set VSBCFLAG "-DPROTECTED_WEAK_TEST"
+ } else {
+ set VSBCFLAG ""
+ }}}}}}}}}
+
+ # Ensure we always start with a clean slate, for the "file exists"
+ # tests below.
+ remote_file host delete $tmpdir/sh1p.o $tmpdir/sh2p.o $tmpdir/sh1np.o $tmpdir/sh2np.o
+
+ if { [istarget powerpc*-*-linux*] \
+ || ( [istarget mips*-*-linux*] && [at_least_gcc_version 4 3] )} {
+ # Testing non-PIC libraries is a waste of effort on any target.
+ # If you don't pass -fpic or -fPIC to gcc, gcc will assume quite
+ # reasonably that you are not compiling for a shared library.
+ # It can then make optimisations that result in shared library
+ # functions and variables not being overridable. Newer versions
+ # of gcc are more likely to do this.
+ } else {
+ # Compile the main program. Make sure that PLT is used since PLT
+ # is expected.
+ if ![ld_compile "$CC_FOR_TARGET -g $PLT_CFLAGS $SHCFLAG $VSBCFLAG $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" $srcdir/$subdir/main.c $tmpdir/mainnp.o] {
+ unsupported "visibility ($visibility) (non PIC)"
+ unsupported "visibility ($visibility)"
+ } else {
+ # The shared library is composed of two files. First compile them
+ # without using -fpic. That should work on an ELF system,
+ # although it will be less efficient because the dynamic linker
+ # will need to do more relocation work. However, note that not
+ # using -fpic will cause some of the tests to return different
+ # results. Make sure that PLT is used since PLT is expected.
+ if { ![ld_compile "$CC_FOR_TARGET -g $NOPIE_CFLAGS $PLT_CFLAGS $SHCFLAG $VSBCFLAG $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" $srcdir/$subdir/sh1.c $tmpdir/sh1np.o]
+ || ![ld_compile "$CC_FOR_TARGET -g $NOPIE_CFLAGS $PLT_CFLAGS $SHCFLAG $VSBCFLAG $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" $srcdir/$subdir/sh2.c $tmpdir/sh2np.o] } {
+ unsupported "visibility ($visibility) (non PIC)"
+ } else {
+ # SunOS non PIC shared libraries don't permit some cases of
+ # overriding.
+ if { [ string match $visibility "protected" ]
+ || [ string match $visibility "protected_undef_def" ] } {
+ if [ string match $support_protected "no" ] {
+ setup_xfail $target_triplet
+ }
+ }
+
+ # Non-pic code uses name binding rules for applications to
+ # reference variables by gp-relative relocs, which can't be
+ # used with overridable symbols.
+ if { ![ string match $visibility "hidden_undef" ]
+ && ![ string match $visibility "protected_undef" ] } {
+ setup_xfail "ia64-*-linux*"
+ setup_xfail "alpha*-*-linux*"
+ }
+ if { ![ string match $visibility "hidden" ]
+ && ![ string match $visibility "hidden_undef" ]
+ && ![ string match $visibility "hidden_undef_def" ]
+ && ![ string match $visibility "protected_undef" ] } {
+ setup_xfail "s390x-*-linux*"
+ if { [istarget sparc*-*-linux*] && [is_elf64 $tmpdir/mainnp.o] } {
+ setup_xfail "sparc*-*-linux*"
+ }
+ }
+ if { [is_elf64 $tmpdir/mainnp.o] } {
+ setup_xfail "x86_64-*-linux*"
+ }
+ setup_xfail "x86_64-*-linux-gnux32"
+ if { ![istarget hppa*64*-*-linux*] } {
+ setup_xfail "hppa*-*-linux*"
+ }
+ if [ string match $shared_needs_pic "yes" ] {
+ setup_xfail "arm*-*-linux*"
+ }
+
+ visibility_test $visibility vnp "visibility ($visibility) (non PIC)" mainnp.o sh1np.o sh2np.o elfvsb
+
+ # Test ELF shared library relocations with a non-zero load
+ # address for the library. Near as I can tell, the R_*_RELATIVE
+ # relocations for various targets are broken in the case where
+ # the load address is not zero (which is the default).
+ if { [ string match $visibility "protected" ]
+ || [ string match $visibility "protected_undef_def" ] } {
+ if [ string match $support_protected "no" ] {
+ setup_xfail $target_triplet
+ }
+ }
+ if { [ string match $visibility "hidden_normal" ]
+ || [ string match $visibility "hidden_weak" ]
+ || [ string match $visibility "protected" ]
+ || [ string match $visibility "protected_undef_def" ]
+ || [ string match $visibility "protected_weak" ]
+ || [ string match $visibility "normal" ] } {
+ setup_xfail "powerpc-*-linux*"
+ setup_xfail "s390x-*-linux*"
+ if { [istarget sparc*-*-linux*] && [is_elf64 $tmpdir/mainnp.o] } {
+ setup_xfail "sparc*-*-linux*"
+ }
+ }
+ if { ![ string match $visibility "hidden_undef" ]
+ && ![ string match $visibility "protected_undef" ] } {
+ setup_xfail "ia64-*-linux*"
+ setup_xfail "alpha*-*-linux*"
+ setup_xfail "mips*-*-linux*"
+ }
+ if { [is_elf64 $tmpdir/mainnp.o] } {
+ setup_xfail "x86_64-*-linux*"
+ }
+ setup_xfail "x86_64-*-linux-gnux32"
+ if { ![istarget hppa*64*-*-linux*] } {
+ setup_xfail "hppa*-*-linux*"
+ }
+ if [ string match $shared_needs_pic "yes" ] {
+ setup_xfail "arm*-*-linux*"
+ }
+
+ visibility_test $visibility vnp "visibility ($visibility) (non PIC, load offset)" \
+ mainnp.o sh1np.o sh2np.o elfvsb \
+ "-Wl,-T,$srcdir/$subdir/elf-offset.ld,--hash-style=sysv"
+ }
+
+ # Now compile the code using -fpic.
+
+ if { ![ld_compile "$CC_FOR_TARGET -g $SHCFLAG $VSBCFLAG $NOSANITIZE_CFLAGS $NOLTO_CFLAGS -DSHARED $picflag" $srcdir/$subdir/sh1.c $tmpdir/sh1p.o]
+ || ![ld_compile "$CC_FOR_TARGET -g $SHCFLAG $VSBCFLAG $NOSANITIZE_CFLAGS $NOLTO_CFLAGS -DSHARED $picflag" $srcdir/$subdir/sh2.c $tmpdir/sh2p.o] } {
+ unsupported "visibility ($visibility)"
+ } else {
+ if { [ string match $visibility "protected" ]
+ || [ string match $visibility "protected_undef_def" ] } {
+ if [ string match $support_protected "no" ] {
+ setup_xfail $target_triplet
+ }
+ }
+ visibility_test $visibility vp "visibility ($visibility)" mainnp.o sh1p.o sh2p.o elfvsb $COMPRESS_LDFLAG
+ }
+ }}
+
+ if { [istarget powerpc*-*-linux*] } {
+ # Don't bother.
+ } else {
+ # Now do the same tests again, but this time compile main.c PIC.
+ if ![ld_compile "$CC_FOR_TARGET -g $SHCFLAG $VSBCFLAG $NOSANITIZE_CFLAGS $NOLTO_CFLAGS -DSHARED $picflag" $srcdir/$subdir/main.c $tmpdir/mainp.o] {
+ unsupported "visibility ($visibility) (PIC main, non PIC so)"
+ unsupported "visibility ($visibility) (PIC main)"
+ } else {
+ if { [ remote_file host exists $tmpdir/sh1np.o ]
+ && [ remote_file host exists $tmpdir/sh2np.o ] } {
+ # SunOS non PIC shared libraries don't permit some cases of
+ # overriding.
+ if { [ string match $visibility "protected" ]
+ || [ string match $visibility "protected_undef_def" ] } {
+ if [ string match $support_protected "no" ] {
+ setup_xfail $target_triplet
+ }
+ }
+ if { ![ string match $visibility "hidden_undef" ]
+ && ![ string match $visibility "protected_undef" ] } {
+ setup_xfail "ia64-*-linux*"
+ setup_xfail "alpha*-*-linux*"
+ }
+ if { ![ string match $visibility "hidden" ]
+ && ![ string match $visibility "hidden_undef" ]
+ && ![ string match $visibility "hidden_undef_def" ]
+ && ![ string match $visibility "protected_undef" ] } {
+ setup_xfail "s390x-*-linux*"
+ if { [istarget sparc*-*-linux*] && [is_elf64 $tmpdir/mainp.o] } {
+ setup_xfail "sparc*-*-linux*"
+ }
+ }
+ if { [is_elf64 $tmpdir/mainp.o] } {
+ setup_xfail "x86_64-*-linux*"
+ }
+ setup_xfail "x86_64-*-linux-gnux32"
+ if { ![istarget hppa*64*-*-linux*] } {
+ setup_xfail "hppa*-*-linux*"
+ }
+ if [ string match $shared_needs_pic "yes" ] {
+ setup_xfail "arm*-*-linux*"
+ }
+
+ visibility_test $visibility vmpnp "visibility ($visibility) (PIC main, non PIC so)" mainp.o sh1np.o sh2np.o elfvsb
+ } else {
+ unsupported "visibility (PIC main, non PIC so)"
+ }
+
+ if { [ remote_file host exists $tmpdir/sh1p.o ]
+ && [ remote_file host exists $tmpdir/sh2p.o ] } {
+ if { [ string match $visibility "protected" ]
+ || [ string match $visibility "protected_undef_def" ] } {
+ if [ string match $support_protected "no" ] {
+ setup_xfail $target_triplet
+ }
+ }
+ visibility_test $visibility vmpp "visibility ($visibility) (PIC main)" mainp.o sh1p.o sh2p.o elfvsb
+ } else {
+ unsupported "visibility ($visibility) (PIC main)"
+ }
+ }}
+}
+
+# Old version of GCC for MIPS default to enabling -fpic
+# and get confused if it is used on the command line.
+if { [istarget mips*-*-*] && ! [at_least_gcc_version 4 3] } then {
+ set picflag ""
+} else {
+ # Unfortunately, the gcc argument is -fpic and the cc argument is
+ # -KPIC. We have to try both.
+ set picflag "-fpic"
+ send_log "$CC_FOR_TARGET $picflag\n"
+ verbose "$CC_FOR_TARGET $picflag"
+ catch "exec $CC_FOR_TARGET $picflag" exec_output
+ send_log "$exec_output\n"
+ verbose "--" "$exec_output"
+ if { [string match "*illegal option*" $exec_output] \
+ || [string match "*option ignored*" $exec_output] \
+ || [string match "*unrecognized option*" $exec_output] \
+ || [string match "*passed to ld*" $exec_output] } {
+ set picflag "-KPIC"
+ }
+}
+verbose "Using $picflag to compile PIC code"
+
+visibility_run hidden
+visibility_run hidden_normal
+visibility_run hidden_undef
+visibility_run hidden_undef_def
+visibility_run hidden_weak
+visibility_run protected
+visibility_run protected_undef
+visibility_run protected_undef_def
+visibility_run protected_weak
+visibility_run normal
+
+if { ![ld_compile "$CC_FOR_TARGET -g $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" $srcdir/$subdir/common.c tmpdir/common.o] } {
+ unsupported "common hidden symbol"
+} else {
+ if ![ld_link $ld tmpdir/common "tmpdir/common.o"] {
+ fail "common hidden symbol"
+ } else {
+ pass "common hidden symbol"
+ }
+}
+
+if { ![ld_compile "$CC_FOR_TARGET -g $NOSANITIZE_CFLAGS $NOLTO_CFLAGS" $srcdir/$subdir/test.c tmpdir/test.o] } {
+ unsupported "weak hidden symbol"
+} else {
+ if { ![ld_compile "$CC_FOR_TARGET -g $NOSANITIZE_CFLAGS $NOLTO_CFLAGS -DSHARED $picflag" $srcdir/$subdir/sh3.c tmpdir/sh3.o] } {
+ unsupported "weak hidden symbol"
+ } else {
+ if ![ld_link $ld tmpdir/sh3.so "-shared tmpdir/sh3.o"] {
+ fail "weak hidden symbol"
+ } else {
+ if ![ld_link $ld tmpdir/weak "tmpdir/test.o tmpdir/sh3.so"] {
+ fail "weak hidden symbol DSO last"
+ } else {
+ pass "weak hidden symbol DSO last"
+ }
+ if ![ld_link $ld tmpdir/weak "tmpdir/sh3.so tmpdir/test.o"] {
+ fail "weak hidden symbol DSO first"
+ } else {
+ pass "weak hidden symbol DSO first"
+ }
+ }
+ }
+}