unsigned int non_elf : 1;
/* Symbol version information. */
ENUM_BITFIELD (elf_symbol_version) versioned : 2;
+ /* Symbol is a base symbol. */
+ unsigned int base_symbol : 1;
/* Symbol was forced to local scope due to a version script file. */
unsigned int forced_local : 1;
/* Symbol was forced to be dynamic due to a version script file. */
/* TRUE when we are handling DT_NEEDED entries. */
bool handling_dt_needed;
+ /* TRUE if there are base symbols. */
+ bool has_base_symbols;
+
/* The BFD used to hold special sections created by the linker.
This will be the first BFD found which requires these sections to
be created. */
bed = get_elf_backend_data (abfd);
+ htab = elf_hash_table (info);
+
/* NEW_VERSION is the symbol version of the new symbol. */
if (h->versioned != unversioned)
{
{
if (h->versioned == unknown)
{
+ /* The base symbol has an empty version. */
+ if (new_version[1] == '\0')
+ {
+ htab->has_base_symbols = true;
+ h->base_symbol = 1;
+ }
if (new_version > name && new_version[-1] != ELF_VER_CHR)
h->versioned = versioned_hidden;
else
symbols. */
bfd_elf_link_mark_dynamic_symbol (info, h, sym);
- htab = elf_hash_table (info);
-
/* NEWDYN and OLDDYN indicate whether the new or old symbol,
respectively, is from a dynamic object. */
long int shift1, shift2;
unsigned long int mask;
bool error;
+ bool base_symbol;
};
/* This function will be called though elf_link_hash_traverse to store
if (h->dynindx == -1)
return true;
+ /* Skip if base symbol doesn't match. */
+ if (s->base_symbol != !!h->base_symbol)
+ return true;
+
/* Ignore also local symbols and undefined symbols. */
if (! (*s->bed->elf_hash_symbol) (h))
{
cinfo.contents = contents;
cinfo.xlat = contents + cinfo.nsyms * 4 - s->contents;
- /* Renumber dynamic symbols, if populating .gnu.hash section.
- If using .MIPS.xhash, populate the translation table. */
+
+ if (elf_hash_table (info)->has_base_symbols)
+ {
+ /* Output base symbols first in DT_GNU_HASH so that
+ they will be picked before non-base symbols at
+ run-time. */
+ cinfo.base_symbol = true;
+
+ /* Renumber dynamic symbols, if populating .gnu.hash
+ section. If using .MIPS.xhash, populate the
+ translation table. */
+ elf_link_hash_traverse (elf_hash_table (info),
+ elf_gnu_hash_process_symidx, &cinfo);
+ }
+
+ /* Output non-base symbols last. */
+ cinfo.base_symbol = false;
elf_link_hash_traverse (elf_hash_table (info),
elf_gnu_hash_process_symidx, &cinfo);
bool failed;
bool localsyms;
bool file_sym_done;
+ bool base_symbol;
struct elf_final_link_info *flinfo;
};
int ret;
unsigned int type;
+ /* Skip if base symbol doesn't match. */
+ if (eoinfo->base_symbol != !!h->base_symbol)
+ return true;
+
if (h->root.type == bfd_link_hash_warning)
{
h = (struct elf_link_hash_entry *) h->root.u.i.link;
eoinfo.flinfo = &flinfo;
eoinfo.localsyms = true;
eoinfo.file_sym_done = false;
+ /* Output non-base symbols first. */
+ eoinfo.base_symbol = false;
bfd_hash_traverse (&info->hash->table, elf_link_output_extsym, &eoinfo);
if (eoinfo.failed)
goto error_return;
if (eoinfo.failed)
goto error_return;
+ if (htab->has_base_symbols)
+ {
+ /* Output base symbols last in DT_HASH so that they will be picked
+ before non-base symbols at run-time. */
+ eoinfo.base_symbol = true;
+ bfd_hash_traverse (&info->hash->table, elf_link_output_extsym,
+ &eoinfo);
+ if (eoinfo.failed)
+ goto error_return;
+ }
+
/* If backend needs to output some symbols not present in the hash
table, do it now. */
if (bed->elf_backend_output_arch_syms
Symbol table '\.dynsym' contains [0-9]+ entries:
+Num: +Value +Size Type +Bind +Vis +Ndx Name
-#...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +_?bar
#...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +GLOBAL +DEFAULT .*[0-9]+ _?foo
#pass
--- /dev/null
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +(FUNC|NOTYPE) +GLOBAL +DEFAULT +UND +_?bar
+#pass
Symbol table '\.dynsym' contains [0-9]+ entries:
+Num: +Value +Size Type +Bind +Vis +Ndx Name
-#...
- +[0-9]+: +[a-f0-9]+ +0 +NOTYPE +GLOBAL +DEFAULT +UND +_?bar
#...
+[0-9]+: +[0-9a-f]+ +[0-9a-f]+ +FUNC +GLOBAL +DEFAULT .*[0-9]+ _?foo@
#pass
--- /dev/null
+Symbol table '\.dynsym' contains [0-9]+ entries:
+ +Num: +Value +Size Type +Bind +Vis +Ndx Name
+#...
+ +[0-9]+: +[a-f0-9]+ +0 +(FUNC|NOTYPE) +GLOBAL +DEFAULT +UND +_?bar
+#pass
build_vers_lib_pic "vers32a" vers32a.c vers32a "" vers32.map vers32a.ver vers32a.dsym ""
build_vers_lib_pic_flags "vers32b" vers32b.c vers32b "vers32a.so" vers32.map vers32b.ver vers32b.dsym "" "--defsym foo=0"
-if [check_compiler_available] {
+proc base_symbol_test { ldflags } {
run_cc_link_tests [list \
[list \
- "Build pr33577-unversioned.so" \
- "-shared -Wl,-soname,libpr33577.so" \
+ "Build libpr33577-unversioned.so ($ldflags)" \
+ "$ldflags -shared -Wl,-soname,libpr33577.so" \
"-fPIC" \
{ pr33577-unversioned.c } \
- {{readelf {--dyn-syms -W} pr33577-unversioned.rd}} \
+ {{readelf {--dyn-syms -W} pr33577-unversioned-a.rd} \
+ {readelf {--dyn-syms -W} pr33577-unversioned-b.rd}} \
"libpr33577-unversioned.so" \
] \
[list \
- "Build pr33577-versioned.so" \
- "-shared -Wl,-soname,libpr33577.so,--version-script=pr33577.map" \
+ "Build libpr33577-versioned.so ($ldflags)" \
+ "$ldflags -shared -Wl,-soname,libpr33577.so,--version-script=pr33577.map" \
"-fPIC" \
{ pr33577-versioned.c } \
- {{readelf {--dyn-syms -W} pr33577-versioned.rd}} \
+ {{readelf {--dyn-syms -W} pr33577-versioned-a.rd} \
+ {readelf {--dyn-syms -W} pr33577-versioned-b.rd}} \
"libpr33577-versioned.so" \
] \
]
run_cc_link_tests [list \
[list \
- "Build pr33577a with tmpdir/libpr33577-unversioned.so" \
+ "Build pr33577a with tmpdir/libpr33577-unversioned.so ($ldflags)" \
"" \
"" \
{ pr33577a.c } \
if [isnative] {
run_ld_link_exec_tests [list \
[list \
- "Run pr33577a with tmpdir/libpr33577-unversioned.so" \
+ "Run pr33577a with tmpdir/libpr33577-unversioned.so ($ldflags)" \
"-Wl,-R,tmpdir" \
"" \
{ pr33577a.c } \
run_cc_link_tests [list \
[list \
- "Build pr33577b with tmpdir/libpr33577-versioned.so" \
+ "Build pr33577b with tmpdir/libpr33577-versioned.so ($ldflags)" \
"-Wl,-R,tmpdir" \
"" \
{ pr33577b.c } \
]
if [isnative] {
- set test_name "Run pr33577a with tmpdir/libpr33577-versioned.so"
+ set test_name "Run pr33577a with tmpdir/libpr33577-versioned.so ($ldflags)"
set cmd tmpdir/pr33577a
send_log "$cmd\n"
set got [remote_exec host "$cmd"]
fail "$test_name"
}
- set test_name "Run pr33577b with tmpdir/libpr33577-versioned.so"
+ set test_name "Run pr33577b with tmpdir/libpr33577-versioned.so ($ldflags)"
set cmd tmpdir/pr33577b
send_log "$cmd\n"
set got [remote_exec host "$cmd"]
}
}
}
+
+base_symbol_test "-Wl,--as-needed,--hash-style=sysv"
+base_symbol_test "-Wl,--as-needed,--hash-style=gnu"
+base_symbol_test "-Wl,--as-needed,--hash-style=both"
+base_symbol_test "-Wl,--no-as-needed,--hash-style=sysv"
+base_symbol_test "-Wl,--no-as-needed,--hash-style=gnu"
+base_symbol_test "-Wl,--no-as-needed,--hash-style=both"