1
1
mirror of https://github.com/rui314/mold.git synced 2024-11-14 07:18:42 +03:00

Fix an issue that local symbols are exported

We sometimes put local symbols into .dynsym, but if they are
global symbols hidden by a version script, they were exported
from .dynsym. This patch correctly makes them local symbols.
This commit is contained in:
Rui Ueyama 2021-08-29 13:04:20 +09:00
parent d06e2f71f3
commit c50dd18881
2 changed files with 37 additions and 2 deletions

View File

@ -911,7 +911,7 @@ void DynsymSection<E>::finalize(Context<E> &ctx) {
// In any symtab, local symbols must precede global symbols.
auto first_global = std::stable_partition(symbols.begin() + 1, symbols.end(),
[](Symbol<E> *sym) {
return sym->esym().st_bind == STB_LOCAL;
return !sym->is_imported && !sym->is_exported;
});
i64 global_offset = first_global - symbols.begin();
@ -978,7 +978,9 @@ void DynsymSection<E>::copy_buf(Context<E> &ctx) {
esym.st_type = sym.esym().st_type;
esym.st_size = sym.esym().st_size;
if (sym.is_weak)
if (i < this->shdr.sh_info)
esym.st_bind = STB_LOCAL;
else if (sym.is_weak)
esym.st_bind = STB_WEAK;
else if (sym.file->is_dso)
esym.st_bind = STB_GLOBAL;

33
test/tls-gd2.sh Executable file
View File

@ -0,0 +1,33 @@
#!/bin/bash
set -e
cd $(dirname $0)
mold=`pwd`/../mold
echo -n "Testing $(basename -s .sh $0) ... "
t=$(pwd)/tmp/$(basename -s .sh $0)
mkdir -p $t
if [ $(uname -m) = x86_64 ]; then
dialect=gnu
elif [ $(uname -m) = aarch64 ]; then
dialect=trad
else
echo skipped
exit 0
fi
echo '{ global: bar; local: *; };' > $t/a.ver
cat <<EOF | gcc -mtls-dialect=$dialect -fPIC -c -o $t/b.o -xc -
_Thread_local int foo;
int bar() {
return foo;
}
EOF
clang -fuse-ld=$mold -shared -o $t/c.so $t/b.o -Wl,--version-script=$t/a.ver \
-Wl,--no-relax
readelf -W --dyn-syms $t/c.so | grep -Pq 'TLS LOCAL DEFAULT \d+ foo'
echo OK