forked from OSchip/llvm-project
[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:
parent
214122cffc
commit
575f7d4f1c
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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_
|
||||
...
|
Loading…
Reference in New Issue