[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
This commit is contained in:
Denis Protivensky 2015-05-22 11:23:39 +00:00
parent 214122cffc
commit 575f7d4f1c
2 changed files with 77 additions and 6 deletions

View File

@ -566,8 +566,8 @@ protected:
// Create specific GOT entry.
const auto *ga = (static_cast<Derived *>(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<const Atom *, GOTAtom *> _gotAtoms;
/// \brief Map Atoms to their PLTGOT entries.
llvm::MapVector<const Atom *, GOTAtom *> _gotpltAtoms;
/// \brief Map Atoms to their Object entries.
llvm::MapVector<const Atom *, ObjectAtom *> _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;
}

View File

@ -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_
...