Fix direct calls to __wrap_sym when it is relocated.

Patch by Matthew Koontz!

Before, direct calls to __wrap_sym would not map to valid PLT entries,
so they would crash at runtime. This change maps such calls to the same
PLT entry as calls to sym that are then wrapped.

Differential Revision: https://reviews.llvm.org/D48502

llvm-svn: 336609
This commit is contained in:
Rui Ueyama 2018-07-09 22:03:05 +00:00
parent ec34220f5c
commit 3e730b8ae6
5 changed files with 61 additions and 1 deletions

View File

@ -1010,7 +1010,7 @@ static void scanReloc(InputSectionBase &Sec, OffsetGetter &GetOffset, RelTy *&I,
}
// If a relocation needs PLT, we create PLT and GOTPLT slots for the symbol.
if (needsPlt(Expr) && !Sym.isInPlt()) {
if (needsPlt(Expr) && !Sym.isInPlt() && Sym.IsUsedInRegularObj) {
if (Sym.isGnuIFunc() && !Sym.IsPreemptible)
addPltEntry<ELFT>(InX::Iplt, InX::IgotPlt, InX::RelaIplt,
Target->IRelativeRel, Sym);

View File

@ -212,6 +212,17 @@ void SymbolTable::applySymbolWrap() {
}
}
// Apply changes caused by relocations to wrapped symbols
// This is needed for direct calls to __wrap_sym
void SymbolTable::applySymbolWrapReloc() {
for (WrappedSymbol &W : WrappedSymbols) {
memcpy(W.Wrap, W.Sym, sizeof(SymbolUnion));
// Keep this so that this copy of the symbol remains dropped
W.Wrap->IsUsedInRegularObj = false;
}
}
static uint8_t getMinVisibility(uint8_t VA, uint8_t VB) {
if (VA == STV_DEFAULT)
return VB;

View File

@ -39,6 +39,7 @@ public:
template <class ELFT> void addCombinedLTOObject();
template <class ELFT> void addSymbolWrap(StringRef Name);
void applySymbolWrap();
void applySymbolWrapReloc();
ArrayRef<Symbol *> getSymbols() const { return SymVector; }

View File

@ -1579,6 +1579,9 @@ template <class ELFT> void Writer<ELFT>::finalizeSections() {
if (!Config->Relocatable)
forEachRelSec(scanRelocations<ELFT>);
// Apply changes caused by relocations to wrapped symbols
Symtab->applySymbolWrapReloc();
if (InX::Plt && !InX::Plt->empty())
InX::Plt->addSymbols();
if (InX::Iplt && !InX::Iplt->empty())

45
lld/test/ELF/wrap-plt.s Normal file
View File

@ -0,0 +1,45 @@
// REQUIRES: x86
// RUN: llvm-mc -filetype=obj -triple=x86_64-pc-linux %s -o %t
// RUN: ld.lld -o %t2 %t -wrap foo -shared
// RUN: llvm-readobj -s -r %t2 | FileCheck %s
// RUN: llvm-objdump -d %t2 | FileCheck --check-prefix=DISASM %s
// CHECK: Name: .plt
// CHECK-NEXT: Type: SHT_PROGBITS
// CHECK-NEXT: Flags [
// CHECK-NEXT: SHF_ALLOC
// CHECK-NEXT: SHF_EXECINSTR
// CHECK-NEXT: ]
// CHECK-NEXT: Address: 0x1020
// CHECK-NEXT: Offset:
// CHECK-NEXT: Size: 48
// CHECK-NEXT: Link: 0
// CHECK-NEXT: Info: 0
// CHECK-NEXT: AddressAlignment: 16
// CHECK: Relocations [
// CHECK-NEXT: Section ({{.*}}) .rela.plt {
// CHECK-NEXT: 0x2018 R_X86_64_JUMP_SLOT __wrap_foo 0x0
// CHECK-NEXT: 0x2020 R_X86_64_JUMP_SLOT _start 0x0
// CHECK-NEXT: }
// CHECK-NEXT: ]
// DISASM: _start:
// DISASM-NEXT: jmp 41
// DISASM-NEXT: jmp 36
// DISASM-NEXT: jmp 47
.global foo
foo:
nop
.global __wrap_foo
__wrap_foo:
nop
.global _start
_start:
jmp foo@plt
jmp __wrap_foo@plt
jmp _start@plt