diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -2179,11 +2179,7 @@ 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)); diff --git a/lld/ELF/SymbolTable.cpp b/lld/ELF/SymbolTable.cpp --- a/lld/ELF/SymbolTable.cpp +++ b/lld/ELF/SymbolTable.cpp @@ -44,7 +44,10 @@ 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 diff --git a/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test b/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test --- a/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test +++ b/lld/test/ELF/lto/wrap-unreferenced-before-codegen.test @@ -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 diff --git a/lld/test/ELF/wrap-drop-shared-original.s b/lld/test/ELF/wrap-drop-shared-original.s new file mode 100644 --- /dev/null +++ b/lld/test/ELF/wrap-drop-shared-original.s @@ -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 diff --git a/lld/test/ELF/wrap-lazy.test b/lld/test/ELF/wrap-lazy.test --- a/lld/test/ELF/wrap-lazy.test +++ b/lld/test/ELF/wrap-lazy.test @@ -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