1
1
mirror of https://github.com/rui314/mold.git synced 2024-10-04 08:37:28 +03:00

[ELF] Fix symbol resolution for versioned symbols

My last commit d391fd9a59 changes how we
resolve versioned symbols, but that affected too many programs.
In particular it broke GCC build, so reverted in
f378fdc495.

This commit is an attempt to fix the same issue with a minimal change.

Fixes https://github.com/rui314/mold/issues/475
This commit is contained in:
Rui Ueyama 2022-04-27 12:57:51 +08:00
parent f378fdc495
commit 8298c0ad16
2 changed files with 45 additions and 2 deletions

View File

@ -1121,10 +1121,13 @@ void parse_symbol_version(Context<E> &ctx) {
// If both symbol `foo` and `foo@VERSION` are defined, `foo@VERSION`
// hides `foo` so that all references to `foo` are resolved to a
// versioned symbol.
// versioned symbol. Likewise, if `foo@VERSION` and `foo@@VERSION` are
// defined, the default one takes precedence.
Symbol<E> *sym2 = get_symbol(ctx, sym->name());
if (sym2->file == file && !file->symvers[sym2->sym_idx - file->first_global])
sym2->ver_idx = VER_NDX_LOCAL;
if (sym2->ver_idx == ctx.default_version ||
(sym2->ver_idx & ~VERSYM_HIDDEN) == (sym->ver_idx & ~VERSYM_HIDDEN))
sym2->ver_idx = VER_NDX_LOCAL;
}
});
}

40
test/elf/symbol-version3.sh Executable file
View File

@ -0,0 +1,40 @@
#!/bin/bash
export LC_ALL=C
set -e
CC="${CC:-cc}"
CXX="${CXX:-c++}"
GCC="${GCC:-gcc}"
GXX="${GXX:-g++}"
OBJDUMP="${OBJDUMP:-objdump}"
MACHINE="${MACHINE:-$(uname -m)}"
testname=$(basename "$0" .sh)
echo -n "Testing $testname ... "
cd "$(dirname "$0")"/../..
mold="$(pwd)/mold"
t=out/test/elf/$testname
mkdir -p $t
cat <<EOF | $CC -o $t/a.o -c -xc -
void foo() {}
void foo2() {}
void foo3() {}
__asm__(".symver foo2, foo@TEST2");
__asm__(".symver foo3, foo@TEST3");
EOF
cat <<EOF > $t/b.version
TEST1 { global: foo; };
TEST2 {};
TEST3 {};
EOF
$CC -B. -o $t/c.so -shared $t/a.o -Wl,--version-script=$t/b.version
readelf -W --dyn-syms $t/c.so > $t/log
grep -q ' foo@@TEST1$' $t/log
grep -q ' foo@TEST2$' $t/log
grep -q ' foo@TEST3$' $t/log
! grep -q ' foo$' $t/log || false
echo OK