From 575f7d4f1c1e1d818103e8b6b2c8d69c1f08836f Mon Sep 17 00:00:00 2001 From: Denis Protivensky Date: Fri, 22 May 2015 11:23:39 +0000 Subject: [PATCH] [ARM] Ability to add GOT and PLTGOT entries for same symbol These two serve different purpose: PLTGOT entries are (usually) lazily resolved and serve as trampolines to correctly call dynamically linked functions. They often have R_*_JUMP_SLOT dynamic relocation type used. Simple GOT entries hold other things, one of them may be R_*_GLOB_DAT to correctly reference global and static data. This is also used to hold dynamically linked function's address. To properly handle cases when shared object's function is called and at the same time its address is taken, we need to be able to have both GOT and PLTGOT entries bearing different dynamic relocation types for the same symbol. llvm-svn: 238015 --- .../ELF/ARM/ARMRelocationPass.cpp | 20 ++++-- lld/test/elf/ARM/two-got-for-symbol.test | 63 +++++++++++++++++++ 2 files changed, 77 insertions(+), 6 deletions(-) create mode 100644 lld/test/elf/ARM/two-got-for-symbol.test diff --git a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp index 517e201b4cd2..c41da0bebcf5 100644 --- a/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp +++ b/lld/lib/ReaderWriter/ELF/ARM/ARMRelocationPass.cpp @@ -566,8 +566,8 @@ protected: // Create specific GOT entry. const auto *ga = (static_cast(this)->*gotFactory)(da); - assert(_gotAtoms.lookup(da) == ga && - "GOT entry should be added to the map"); + assert(_gotpltAtoms.lookup(da) == ga && + "GOT entry should be added to the PLTGOT map"); assert(ga->customSectionName() == ".got.plt" && "GOT entry should be in a special section"); @@ -592,7 +592,7 @@ protected: /// \brief Create the GOT entry for a given IFUNC Atom. const GOTAtom *createIFUNCGOT(const Atom *da) { - assert(!_gotAtoms.lookup(da) && "IFUNC GOT entry already exists"); + assert(!_gotpltAtoms.lookup(da) && "IFUNC GOT entry already exists"); auto g = new (_file._alloc) ARMGOTPLTAtom(_file); g->addReferenceELF_ARM(R_ARM_ABS32, 0, da, 0); g->addReferenceELF_ARM(R_ARM_IRELATIVE, 0, da, 0); @@ -600,7 +600,7 @@ protected: g->_name = "__got_ifunc_"; g->_name += da->name(); #endif - _gotAtoms[da] = g; + _gotpltAtoms[da] = g; return g; } @@ -740,6 +740,11 @@ public: got->setOrdinal(ordinal++); mf->addAtom(*got); } + for (auto &gotKV : _gotpltAtoms) { + auto &got = gotKV.second; + got->setOrdinal(ordinal++); + mf->addAtom(*got); + } for (auto &objectKV : _objectAtoms) { auto &obj = objectKV.second; obj->setOrdinal(ordinal++); @@ -764,6 +769,9 @@ protected: /// \brief Map Atoms to their GOT entries. llvm::MapVector _gotAtoms; + /// \brief Map Atoms to their PLTGOT entries. + llvm::MapVector _gotpltAtoms; + /// \brief Map Atoms to their Object entries. llvm::MapVector _objectAtoms; @@ -861,7 +869,7 @@ public: /// \brief Create the GOT entry for a given atom. const GOTAtom *createPLTGOT(const Atom *da) { - assert(!_gotAtoms.lookup(da) && "PLTGOT entry already exists"); + assert(!_gotpltAtoms.lookup(da) && "PLTGOT entry already exists"); auto g = new (_file._alloc) ARMGOTPLTAtom(_file); g->addReferenceELF_ARM(R_ARM_ABS32, 0, getPLT0(), 0); g->addReferenceELF_ARM(R_ARM_JUMP_SLOT, 0, da, 0); @@ -869,7 +877,7 @@ public: g->_name = "__got_plt0_"; g->_name += da->name(); #endif - _gotAtoms[da] = g; + _gotpltAtoms[da] = g; return g; } diff --git a/lld/test/elf/ARM/two-got-for-symbol.test b/lld/test/elf/ARM/two-got-for-symbol.test new file mode 100644 index 000000000000..ecd15108a3bc --- /dev/null +++ b/lld/test/elf/ARM/two-got-for-symbol.test @@ -0,0 +1,63 @@ +# Check that two GOT entries containing R_ARM_JUMP_SLOT and +# R_ARM_GLOB_DAT may be present for the same symbol in the linked binary. + +# RUN: yaml2obj -format=elf %s > %t-o.o +# RUN: lld -flavor gnu -target arm -m armelf_linux_eabi -shared \ +# RUN: --noinhibit-exec %t-o.o -lfn -L%p/Inputs -o %t +# RUN: llvm-readobj -relocations %t | FileCheck %s + +# CHECK: 0x401000 R_ARM_GLOB_DAT fn 0x0 +# CHECK: 0x401010 R_ARM_JUMP_SLOT fn 0x0 + +--- +FileHeader: + Class: ELFCLASS32 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_ARM + Flags: [ EF_ARM_EABI_VER5 ] +Sections: + - Name: .text + Type: SHT_PROGBITS + Flags: [ SHF_ALLOC, SHF_EXECINSTR ] + AddressAlign: 0x0000000000000004 + Content: 10482DE908B08DE20CD04DE230209FE502208FE02C309FE5033092E710300BE5FEFFFFEB0040A0E110301BE533FF2FE10030A0E1033084E00300A0E108D04BE21088BDE82C00000000000000 + - Name: .rel.text + Type: SHT_REL + Link: .symtab + AddressAlign: 0x0000000000000004 + Info: .text + Relocations: + - Offset: 0x0000000000000020 + Symbol: fn + Type: R_ARM_CALL + - Offset: 0x0000000000000044 + Symbol: _GLOBAL_OFFSET_TABLE_ + Type: R_ARM_BASE_PREL + - Offset: 0x0000000000000048 + Symbol: fn + Type: R_ARM_GOT_BREL + - Name: .data + Type: SHT_PROGBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' + - Name: .bss + Type: SHT_NOBITS + Flags: [ SHF_WRITE, SHF_ALLOC ] + AddressAlign: 0x0000000000000001 + Content: '' +Symbols: + Local: + - Name: '$a' + Section: .text + - Name: '$d' + Section: .text + Value: 0x0000000000000044 + Global: + - Name: f + Type: STT_FUNC + Section: .text + - Name: fn + - Name: _GLOBAL_OFFSET_TABLE_ +...