[ELF] Drop unused original symbol after wrapping if not defined

We were previously only omitting the original of a wrapped symbol if it
was not used by an object file and undefined. We can tighten the second
condition to drop any symbol that isn't defined instead, which lets us
drop a previous check (added in https://reviews.llvm.org/D118756) that
was only covering some such symbols.

Reviewed By: MaskRay

Differential Revision: https://reviews.llvm.org/D124065
This commit is contained in:
Shoaib Meenai 2022-04-19 21:45:54 -07:00
parent b985b6e3c1
commit 2a04f5c455
5 changed files with 57 additions and 11 deletions

View File

@ -2179,11 +2179,7 @@ static std::vector<WrappedSymbol> addWrappedSymbols(opt::InputArgList &args) {
continue;
Symbol *sym = symtab->find(name);
// Avoid wrapping symbols that are lazy and unreferenced at this point, to
// not create undefined references. The isUsedInRegularObj check handles the
// case of a weak reference, which we still want to wrap even though it
// doesn't cause lazy symbols to be extracted.
if (!sym || (sym->isLazy() && !sym->isUsedInRegularObj))
if (!sym)
continue;
Symbol *real = addUnusedUndefined(saver().save("__real_" + name));

View File

@ -44,7 +44,10 @@ void SymbolTable::wrap(Symbol *sym, Symbol *real, Symbol *wrap) {
wrap->isUsedInRegularObj = true;
if (real->isUsedInRegularObj)
sym->isUsedInRegularObj = true;
else if (sym->isUndefined())
else if (!sym->isDefined())
// Now that all references to sym have been redirected to wrap, if there are
// no references to real (which has been redirected to sym), we only need to
// keep sym if it was defined, otherwise it's unused and can be dropped.
sym->isUsedInRegularObj = false;
// Now renaming is complete, and no one refers to real. We drop real from

View File

@ -19,10 +19,9 @@
# UNWIND-DISASM-LABEL: <__wrap__Unwind_Resume@plt>:
# UNWIND-DISASM-NEXT: jmpq *[[#]](%rip) # [[#%#x,RELOC]]
# UNWIND-DYNSYM: Symbol table '.dynsym' contains 5 entries:
# UNWIND-DYNSYM: Symbol table '.dynsym' contains 4 entries:
# UNWIND-DYNSYM: NOTYPE LOCAL DEFAULT UND
# UNWIND-DYNSYM-NEXT: NOTYPE GLOBAL DEFAULT UND throw
# UNWIND-DYNSYM-NEXT: NOTYPE GLOBAL DEFAULT UND _Unwind_Resume
# UNWIND-DYNSYM-NEXT: NOTYPE GLOBAL DEFAULT UND __wrap__Unwind_Resume
# UNWIND-DYNSYM-NEXT: FUNC GLOBAL DEFAULT 9 _Z1fv
@ -43,9 +42,8 @@
# USETLS-DISASM-LABEL: <__wrap_malloc@plt>:
# USETLS-DISASM-NEXT: jmpq *[[#]](%rip) # [[#%#x,RELOC]]
# USETLS-DYNSYM: Symbol table '.dynsym' contains 6 entries:
# USETLS-DYNSYM: Symbol table '.dynsym' contains 5 entries:
# USETLS-DYNSYM: NOTYPE LOCAL DEFAULT UND
# USETLS-DYNSYM-NEXT: NOTYPE GLOBAL DEFAULT UND malloc
# USETLS-DYNSYM-NEXT: NOTYPE GLOBAL DEFAULT UND __wrap_malloc
# USETLS-DYNSYM-NEXT: FUNC GLOBAL DEFAULT 6 f
# USETLS-DYNSYM-NEXT: NOTYPE GLOBAL DEFAULT 6 __emutls_get_address

View File

@ -0,0 +1,48 @@
## If the original of a wrapped symbol becomes unreferenced after wrapping, it
## should be dropped from the dynamic symbol table even if defined in a shared
## library.
# REQUIRES: x86
# RUN: rm -rf %t && split-file %s %t
# RUN: llvm-mc -filetype=obj -triple=x86_64-elf %t/original.s -o %t/original.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-elf %t/wrapped.s -o %t/wrapped.o
# RUN: llvm-mc -filetype=obj -triple=x86_64-elf %t/ref.s -o %t/ref.o
# RUN: ld.lld -shared -o %t/liboriginal.so -soname liboriginal.so %t/original.o
# RUN: ld.lld -shared -o %t/liboriginal-and-wrapped.so \
# RUN: -soname liboriginal-and-wrapped.so %t/original.o %t/wrapped.o
# RUN: ld.lld -shared -o %t/libref-with-original.so %t/ref.o \
# RUN: --as-needed %t/liboriginal.so --wrap foo
# RUN: llvm-readelf --dynamic --dyn-syms %t/libref-with-original.so | \
# RUN: FileCheck --check-prefix=ORIGINAL %s
# RUN: ld.lld -shared -o %t/libref-with-original-and-wrapped.so %t/ref.o \
# RUN: --as-needed %t/liboriginal-and-wrapped.so --wrap foo
# RUN: llvm-readelf --dynamic --dyn-syms %t/libref-with-original-and-wrapped.so | \
# RUN: FileCheck --check-prefix=ORIGINAL-AND-WRAPPED %s
# ORIGINAL-NOT: (NEEDED) Shared library: [liboriginal.so]
# ORIGINAL: Symbol table '.dynsym' contains 3 entries:
# ORIGINAL: NOTYPE LOCAL DEFAULT UND
# ORIGINAL-NEXT: NOTYPE GLOBAL DEFAULT UND __wrap_foo
# ORIGINAL-NEXT: NOTYPE GLOBAL DEFAULT 6 ref
# ORIGINAL-AND-WRAPPED: (NEEDED) Shared library: [liboriginal-and-wrapped.so]
# ORIGINAL-AND-WRAPPED: Symbol table '.dynsym' contains 3 entries:
# ORIGINAL-AND-WRAPPED: NOTYPE LOCAL DEFAULT UND
# ORIGINAL-AND-WRAPPED-NEXT: NOTYPE GLOBAL DEFAULT UND __wrap_foo
# ORIGINAL-AND-WRAPPED-NEXT: NOTYPE GLOBAL DEFAULT 6 ref
#--- original.s
.globl foo
foo:
retq
#--- wrapped.s
.globl __wrap_foo
__wrap_foo:
retq
#--- ref.s
.globl ref
ref:
jmp foo@plt

View File

@ -30,8 +30,9 @@
# LAZY-DEF-DAG: [[#]] lazy
# LAZY-DEF-DAG: UND __wrap_lazy
# LAZY-REF-DAG: UND lazy
# LAZY-REF-NOT: UND lazy
# LAZY-REF-DAG: UND __wrap_lazy
# LAZY-REF-NOT: UND lazy
#--- dummy.s
.globl dummy