forked from OSchip/llvm-project
RuntimeDyldELF/AArch64: Implement basic GOT support
This patch implements two GOT relocations: R_AARCH64_ADR_GOT_PAGE and R_AARCH64_LD64_GOT_LO12_NC Differential revision: https://reviews.llvm.org/D28571 llvm-svn: 294191
This commit is contained in:
parent
01595ef77d
commit
3e582c8855
|
@ -484,6 +484,14 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Compute Global Offset Table size. If it is not zero we
|
||||||
|
// also update alignment, which is equal to a size of a
|
||||||
|
// single GOT entry.
|
||||||
|
if (unsigned GotSize = computeGOTSize(Obj)) {
|
||||||
|
RWSectionSizes.push_back(GotSize);
|
||||||
|
RWDataAlign = std::max<uint32_t>(RWDataAlign, getGOTEntrySize());
|
||||||
|
}
|
||||||
|
|
||||||
// Compute the size of all common symbols
|
// Compute the size of all common symbols
|
||||||
uint64_t CommonSize = 0;
|
uint64_t CommonSize = 0;
|
||||||
uint32_t CommonAlign = 1;
|
uint32_t CommonAlign = 1;
|
||||||
|
@ -518,6 +526,24 @@ Error RuntimeDyldImpl::computeTotalAllocSize(const ObjectFile &Obj,
|
||||||
return Error::success();
|
return Error::success();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// compute GOT size
|
||||||
|
unsigned RuntimeDyldImpl::computeGOTSize(const ObjectFile &Obj) {
|
||||||
|
size_t GotEntrySize = getGOTEntrySize();
|
||||||
|
if (!GotEntrySize)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
size_t GotSize = 0;
|
||||||
|
for (section_iterator SI = Obj.section_begin(), SE = Obj.section_end();
|
||||||
|
SI != SE; ++SI) {
|
||||||
|
|
||||||
|
for (const RelocationRef &Reloc : SI->relocations())
|
||||||
|
if (relocationNeedsGot(Reloc))
|
||||||
|
GotSize += GotEntrySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GotSize;
|
||||||
|
}
|
||||||
|
|
||||||
// compute stub buffer size for the given section
|
// compute stub buffer size for the given section
|
||||||
unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj,
|
unsigned RuntimeDyldImpl::computeSectionStubBufSize(const ObjectFile &Obj,
|
||||||
const SectionRef &Section) {
|
const SectionRef &Section) {
|
||||||
|
|
|
@ -961,6 +961,61 @@ bool RuntimeDyldELF::resolveAArch64ShortBranch(
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RuntimeDyldELF::resolveAArch64Branch(unsigned SectionID,
|
||||||
|
const RelocationValueRef &Value,
|
||||||
|
relocation_iterator RelI,
|
||||||
|
StubMap &Stubs) {
|
||||||
|
|
||||||
|
DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation.");
|
||||||
|
SectionEntry &Section = Sections[SectionID];
|
||||||
|
|
||||||
|
uint64_t Offset = RelI->getOffset();
|
||||||
|
unsigned RelType = RelI->getType();
|
||||||
|
// Look for an existing stub.
|
||||||
|
StubMap::const_iterator i = Stubs.find(Value);
|
||||||
|
if (i != Stubs.end()) {
|
||||||
|
resolveRelocation(Section, Offset,
|
||||||
|
(uint64_t)Section.getAddressWithOffset(i->second),
|
||||||
|
RelType, 0);
|
||||||
|
DEBUG(dbgs() << " Stub function found\n");
|
||||||
|
} else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) {
|
||||||
|
// Create a new stub function.
|
||||||
|
DEBUG(dbgs() << " Create a new stub function\n");
|
||||||
|
Stubs[Value] = Section.getStubOffset();
|
||||||
|
uint8_t *StubTargetAddr = createStubFunction(
|
||||||
|
Section.getAddressWithOffset(Section.getStubOffset()));
|
||||||
|
|
||||||
|
RelocationEntry REmovz_g3(SectionID, StubTargetAddr - Section.getAddress(),
|
||||||
|
ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend);
|
||||||
|
RelocationEntry REmovk_g2(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 4,
|
||||||
|
ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend);
|
||||||
|
RelocationEntry REmovk_g1(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 8,
|
||||||
|
ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend);
|
||||||
|
RelocationEntry REmovk_g0(SectionID,
|
||||||
|
StubTargetAddr - Section.getAddress() + 12,
|
||||||
|
ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend);
|
||||||
|
|
||||||
|
if (Value.SymbolName) {
|
||||||
|
addRelocationForSymbol(REmovz_g3, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(REmovk_g2, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(REmovk_g1, Value.SymbolName);
|
||||||
|
addRelocationForSymbol(REmovk_g0, Value.SymbolName);
|
||||||
|
} else {
|
||||||
|
addRelocationForSection(REmovz_g3, Value.SectionID);
|
||||||
|
addRelocationForSection(REmovk_g2, Value.SectionID);
|
||||||
|
addRelocationForSection(REmovk_g1, Value.SectionID);
|
||||||
|
addRelocationForSection(REmovk_g0, Value.SectionID);
|
||||||
|
}
|
||||||
|
resolveRelocation(Section, Offset,
|
||||||
|
reinterpret_cast<uint64_t>(Section.getAddressWithOffset(
|
||||||
|
Section.getStubOffset())),
|
||||||
|
RelType, 0);
|
||||||
|
Section.advanceStubOffset(getMaxStubSize());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Expected<relocation_iterator>
|
Expected<relocation_iterator>
|
||||||
RuntimeDyldELF::processRelocationRef(
|
RuntimeDyldELF::processRelocationRef(
|
||||||
unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,
|
unsigned SectionID, relocation_iterator RelI, const ObjectFile &O,
|
||||||
|
@ -1055,55 +1110,22 @@ RuntimeDyldELF::processRelocationRef(
|
||||||
|
|
||||||
DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset
|
DEBUG(dbgs() << "\t\tSectionID: " << SectionID << " Offset: " << Offset
|
||||||
<< "\n");
|
<< "\n");
|
||||||
if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be) &&
|
if ((Arch == Triple::aarch64 || Arch == Triple::aarch64_be)) {
|
||||||
(RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26)) {
|
if (RelType == ELF::R_AARCH64_CALL26 || RelType == ELF::R_AARCH64_JUMP26) {
|
||||||
// This is an AArch64 branch relocation, need to use a stub function.
|
resolveAArch64Branch(SectionID, Value, RelI, Stubs);
|
||||||
DEBUG(dbgs() << "\t\tThis is an AArch64 branch relocation.");
|
} else if (RelType == ELF::R_AARCH64_ADR_GOT_PAGE) {
|
||||||
SectionEntry &Section = Sections[SectionID];
|
// Craete new GOT entry or find existing one. If GOT entry is
|
||||||
|
// to be created, then we also emit ABS64 relocation for it.
|
||||||
|
uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64);
|
||||||
|
resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,
|
||||||
|
ELF::R_AARCH64_ADR_PREL_PG_HI21);
|
||||||
|
|
||||||
// Look for an existing stub.
|
} else if (RelType == ELF::R_AARCH64_LD64_GOT_LO12_NC) {
|
||||||
StubMap::const_iterator i = Stubs.find(Value);
|
uint64_t GOTOffset = findOrAllocGOTEntry(Value, ELF::R_AARCH64_ABS64);
|
||||||
if (i != Stubs.end()) {
|
resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,
|
||||||
resolveRelocation(Section, Offset,
|
ELF::R_AARCH64_LDST64_ABS_LO12_NC);
|
||||||
(uint64_t)Section.getAddressWithOffset(i->second),
|
} else {
|
||||||
RelType, 0);
|
processSimpleRelocation(SectionID, Offset, RelType, Value);
|
||||||
DEBUG(dbgs() << " Stub function found\n");
|
|
||||||
} else if (!resolveAArch64ShortBranch(SectionID, RelI, Value)) {
|
|
||||||
// Create a new stub function.
|
|
||||||
DEBUG(dbgs() << " Create a new stub function\n");
|
|
||||||
Stubs[Value] = Section.getStubOffset();
|
|
||||||
uint8_t *StubTargetAddr = createStubFunction(
|
|
||||||
Section.getAddressWithOffset(Section.getStubOffset()));
|
|
||||||
|
|
||||||
RelocationEntry REmovz_g3(SectionID,
|
|
||||||
StubTargetAddr - Section.getAddress(),
|
|
||||||
ELF::R_AARCH64_MOVW_UABS_G3, Value.Addend);
|
|
||||||
RelocationEntry REmovk_g2(SectionID, StubTargetAddr -
|
|
||||||
Section.getAddress() + 4,
|
|
||||||
ELF::R_AARCH64_MOVW_UABS_G2_NC, Value.Addend);
|
|
||||||
RelocationEntry REmovk_g1(SectionID, StubTargetAddr -
|
|
||||||
Section.getAddress() + 8,
|
|
||||||
ELF::R_AARCH64_MOVW_UABS_G1_NC, Value.Addend);
|
|
||||||
RelocationEntry REmovk_g0(SectionID, StubTargetAddr -
|
|
||||||
Section.getAddress() + 12,
|
|
||||||
ELF::R_AARCH64_MOVW_UABS_G0_NC, Value.Addend);
|
|
||||||
|
|
||||||
if (Value.SymbolName) {
|
|
||||||
addRelocationForSymbol(REmovz_g3, Value.SymbolName);
|
|
||||||
addRelocationForSymbol(REmovk_g2, Value.SymbolName);
|
|
||||||
addRelocationForSymbol(REmovk_g1, Value.SymbolName);
|
|
||||||
addRelocationForSymbol(REmovk_g0, Value.SymbolName);
|
|
||||||
} else {
|
|
||||||
addRelocationForSection(REmovz_g3, Value.SectionID);
|
|
||||||
addRelocationForSection(REmovk_g2, Value.SectionID);
|
|
||||||
addRelocationForSection(REmovk_g1, Value.SectionID);
|
|
||||||
addRelocationForSection(REmovk_g0, Value.SectionID);
|
|
||||||
}
|
|
||||||
resolveRelocation(Section, Offset,
|
|
||||||
reinterpret_cast<uint64_t>(Section.getAddressWithOffset(
|
|
||||||
Section.getStubOffset())),
|
|
||||||
RelType, 0);
|
|
||||||
Section.advanceStubOffset(getMaxStubSize());
|
|
||||||
}
|
}
|
||||||
} else if (Arch == Triple::arm) {
|
} else if (Arch == Triple::arm) {
|
||||||
if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL ||
|
if (RelType == ELF::R_ARM_PC24 || RelType == ELF::R_ARM_CALL ||
|
||||||
|
@ -1252,7 +1274,7 @@ RuntimeDyldELF::processRelocationRef(
|
||||||
if (i != GOTSymbolOffsets.end())
|
if (i != GOTSymbolOffsets.end())
|
||||||
RE.SymOffset = i->second;
|
RE.SymOffset = i->second;
|
||||||
else {
|
else {
|
||||||
RE.SymOffset = allocateGOTEntries(SectionID, 1);
|
RE.SymOffset = allocateGOTEntries(1);
|
||||||
GOTSymbolOffsets[TargetName] = RE.SymOffset;
|
GOTSymbolOffsets[TargetName] = RE.SymOffset;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1509,14 +1531,15 @@ RuntimeDyldELF::processRelocationRef(
|
||||||
Section.advanceStubOffset(getMaxStubSize());
|
Section.advanceStubOffset(getMaxStubSize());
|
||||||
|
|
||||||
// Allocate a GOT Entry
|
// Allocate a GOT Entry
|
||||||
uint64_t GOTOffset = allocateGOTEntries(SectionID, 1);
|
uint64_t GOTOffset = allocateGOTEntries(1);
|
||||||
|
|
||||||
// The load of the GOT address has an addend of -4
|
// The load of the GOT address has an addend of -4
|
||||||
resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4);
|
resolveGOTOffsetRelocation(SectionID, StubOffset + 2, GOTOffset - 4,
|
||||||
|
ELF::R_X86_64_PC32);
|
||||||
|
|
||||||
// Fill in the value of the symbol we're targeting into the GOT
|
// Fill in the value of the symbol we're targeting into the GOT
|
||||||
addRelocationForSymbol(
|
addRelocationForSymbol(
|
||||||
computeGOTOffsetRE(SectionID, GOTOffset, 0, ELF::R_X86_64_64),
|
computeGOTOffsetRE(GOTOffset, 0, ELF::R_X86_64_64),
|
||||||
Value.SymbolName);
|
Value.SymbolName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1531,11 +1554,13 @@ RuntimeDyldELF::processRelocationRef(
|
||||||
} else if (RelType == ELF::R_X86_64_GOTPCREL ||
|
} else if (RelType == ELF::R_X86_64_GOTPCREL ||
|
||||||
RelType == ELF::R_X86_64_GOTPCRELX ||
|
RelType == ELF::R_X86_64_GOTPCRELX ||
|
||||||
RelType == ELF::R_X86_64_REX_GOTPCRELX) {
|
RelType == ELF::R_X86_64_REX_GOTPCRELX) {
|
||||||
uint64_t GOTOffset = allocateGOTEntries(SectionID, 1);
|
uint64_t GOTOffset = allocateGOTEntries(1);
|
||||||
resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend);
|
resolveGOTOffsetRelocation(SectionID, Offset, GOTOffset + Addend,
|
||||||
|
ELF::R_X86_64_PC32);
|
||||||
|
|
||||||
// Fill in the value of the symbol we're targeting into the GOT
|
// Fill in the value of the symbol we're targeting into the GOT
|
||||||
RelocationEntry RE = computeGOTOffsetRE(SectionID, GOTOffset, Value.Offset, ELF::R_X86_64_64);
|
RelocationEntry RE =
|
||||||
|
computeGOTOffsetRE(GOTOffset, Value.Offset, ELF::R_X86_64_64);
|
||||||
if (Value.SymbolName)
|
if (Value.SymbolName)
|
||||||
addRelocationForSymbol(RE, Value.SymbolName);
|
addRelocationForSymbol(RE, Value.SymbolName);
|
||||||
else
|
else
|
||||||
|
@ -1593,9 +1618,7 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
|
||||||
return Result;
|
return Result;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned no)
|
uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned no) {
|
||||||
{
|
|
||||||
(void)SectionID; // The GOT Section is the same for all section in the object file
|
|
||||||
if (GOTSectionID == 0) {
|
if (GOTSectionID == 0) {
|
||||||
GOTSectionID = Sections.size();
|
GOTSectionID = Sections.size();
|
||||||
// Reserve a section id. We'll allocate the section later
|
// Reserve a section id. We'll allocate the section later
|
||||||
|
@ -1607,17 +1630,38 @@ uint64_t RuntimeDyldELF::allocateGOTEntries(unsigned SectionID, unsigned no)
|
||||||
return StartOffset;
|
return StartOffset;
|
||||||
}
|
}
|
||||||
|
|
||||||
void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset, uint64_t GOTOffset)
|
uint64_t RuntimeDyldELF::findOrAllocGOTEntry(const RelocationValueRef &Value,
|
||||||
{
|
unsigned GOTRelType) {
|
||||||
|
auto E = GOTOffsetMap.insert({Value, 0});
|
||||||
|
if (E.second) {
|
||||||
|
uint64_t GOTOffset = allocateGOTEntries(1);
|
||||||
|
|
||||||
|
// Create relocation for newly created GOT entry
|
||||||
|
RelocationEntry RE =
|
||||||
|
computeGOTOffsetRE(GOTOffset, Value.Offset, GOTRelType);
|
||||||
|
if (Value.SymbolName)
|
||||||
|
addRelocationForSymbol(RE, Value.SymbolName);
|
||||||
|
else
|
||||||
|
addRelocationForSection(RE, Value.SectionID);
|
||||||
|
|
||||||
|
E.first->second = GOTOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
return E.first->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void RuntimeDyldELF::resolveGOTOffsetRelocation(unsigned SectionID,
|
||||||
|
uint64_t Offset,
|
||||||
|
uint64_t GOTOffset,
|
||||||
|
uint32_t Type) {
|
||||||
// Fill in the relative address of the GOT Entry into the stub
|
// Fill in the relative address of the GOT Entry into the stub
|
||||||
RelocationEntry GOTRE(SectionID, Offset, ELF::R_X86_64_PC32, GOTOffset);
|
RelocationEntry GOTRE(SectionID, Offset, Type, GOTOffset);
|
||||||
addRelocationForSection(GOTRE, GOTSectionID);
|
addRelocationForSection(GOTRE, GOTSectionID);
|
||||||
}
|
}
|
||||||
|
|
||||||
RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(unsigned SectionID, uint64_t GOTOffset, uint64_t SymbolOffset,
|
RelocationEntry RuntimeDyldELF::computeGOTOffsetRE(uint64_t GOTOffset,
|
||||||
uint32_t Type)
|
uint64_t SymbolOffset,
|
||||||
{
|
uint32_t Type) {
|
||||||
(void)SectionID; // The GOT Section is the same for all section in the object file
|
|
||||||
return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset);
|
return RelocationEntry(GOTSectionID, GOTOffset, Type, SymbolOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1683,6 +1727,19 @@ bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
|
||||||
return Obj.isELF();
|
return Obj.isELF();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool RuntimeDyldELF::relocationNeedsGot(const RelocationRef &R) const {
|
||||||
|
unsigned RelTy = R.getType();
|
||||||
|
if (Arch == Triple::aarch64 || Arch == Triple::aarch64_be)
|
||||||
|
return RelTy == ELF::R_AARCH64_ADR_GOT_PAGE ||
|
||||||
|
RelTy == ELF::R_AARCH64_LD64_GOT_LO12_NC;
|
||||||
|
|
||||||
|
if (Arch == Triple::x86_64)
|
||||||
|
return RelTy == ELF::R_X86_64_GOTPCREL ||
|
||||||
|
RelTy == ELF::R_X86_64_GOTPCRELX ||
|
||||||
|
RelTy == ELF::R_X86_64_REX_GOTPCRELX;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const {
|
bool RuntimeDyldELF::relocationNeedsStub(const RelocationRef &R) const {
|
||||||
if (Arch != Triple::x86_64)
|
if (Arch != Triple::x86_64)
|
||||||
return true; // Conservative answer
|
return true; // Conservative answer
|
||||||
|
|
|
@ -43,6 +43,9 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||||
bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI,
|
bool resolveAArch64ShortBranch(unsigned SectionID, relocation_iterator RelI,
|
||||||
const RelocationValueRef &Value);
|
const RelocationValueRef &Value);
|
||||||
|
|
||||||
|
void resolveAArch64Branch(unsigned SectionID, const RelocationValueRef &Value,
|
||||||
|
relocation_iterator RelI, StubMap &Stubs);
|
||||||
|
|
||||||
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
|
void resolveARMRelocation(const SectionEntry &Section, uint64_t Offset,
|
||||||
uint32_t Value, uint32_t Type, int32_t Addend);
|
uint32_t Value, uint32_t Type, int32_t Addend);
|
||||||
|
|
||||||
|
@ -88,24 +91,26 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
|
||||||
ObjSectionToIDMap &LocalSections,
|
ObjSectionToIDMap &LocalSections,
|
||||||
RelocationValueRef &Rel);
|
RelocationValueRef &Rel);
|
||||||
protected:
|
protected:
|
||||||
size_t getGOTEntrySize();
|
size_t getGOTEntrySize() override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
|
SectionEntry &getSection(unsigned SectionID) { return Sections[SectionID]; }
|
||||||
|
|
||||||
// Allocate no GOT entries for use in the given section.
|
// Allocate no GOT entries for use in the given section.
|
||||||
uint64_t allocateGOTEntries(unsigned SectionID, unsigned no);
|
uint64_t allocateGOTEntries(unsigned no);
|
||||||
|
|
||||||
|
// Find GOT entry corresponding to relocation or create new one.
|
||||||
|
uint64_t findOrAllocGOTEntry(const RelocationValueRef &Value,
|
||||||
|
unsigned GOTRelType);
|
||||||
|
|
||||||
// Resolve the relvative address of GOTOffset in Section ID and place
|
// Resolve the relvative address of GOTOffset in Section ID and place
|
||||||
// it at the given Offset
|
// it at the given Offset
|
||||||
void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset,
|
void resolveGOTOffsetRelocation(unsigned SectionID, uint64_t Offset,
|
||||||
uint64_t GOTOffset);
|
uint64_t GOTOffset, uint32_t Type);
|
||||||
|
|
||||||
// For a GOT entry referenced from SectionID, compute a relocation entry
|
// For a GOT entry referenced from SectionID, compute a relocation entry
|
||||||
// that will place the final resolved value in the GOT slot
|
// that will place the final resolved value in the GOT slot
|
||||||
RelocationEntry computeGOTOffsetRE(unsigned SectionID,
|
RelocationEntry computeGOTOffsetRE(uint64_t GOTOffset, uint64_t SymbolOffset,
|
||||||
uint64_t GOTOffset,
|
|
||||||
uint64_t SymbolOffset,
|
|
||||||
unsigned Type);
|
unsigned Type);
|
||||||
|
|
||||||
// Compute the address in memory where we can find the placeholder
|
// Compute the address in memory where we can find the placeholder
|
||||||
|
@ -146,6 +151,10 @@ private:
|
||||||
SmallVector<SID, 2> UnregisteredEHFrameSections;
|
SmallVector<SID, 2> UnregisteredEHFrameSections;
|
||||||
SmallVector<SID, 2> RegisteredEHFrameSections;
|
SmallVector<SID, 2> RegisteredEHFrameSections;
|
||||||
|
|
||||||
|
// Map between GOT relocation value and corresponding GOT offset
|
||||||
|
std::map<RelocationValueRef, uint64_t> GOTOffsetMap;
|
||||||
|
|
||||||
|
bool relocationNeedsGot(const RelocationRef &R) const override;
|
||||||
bool relocationNeedsStub(const RelocationRef &R) const override;
|
bool relocationNeedsStub(const RelocationRef &R) const override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
|
@ -213,7 +213,7 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @brief Symbol info for RuntimeDyld.
|
/// @brief Symbol info for RuntimeDyld.
|
||||||
class SymbolTableEntry {
|
class SymbolTableEntry {
|
||||||
public:
|
public:
|
||||||
SymbolTableEntry()
|
SymbolTableEntry()
|
||||||
|
@ -426,6 +426,9 @@ protected:
|
||||||
uint64_t &RODataSize, uint32_t &RODataAlign,
|
uint64_t &RODataSize, uint32_t &RODataAlign,
|
||||||
uint64_t &RWDataSize, uint32_t &RWDataAlign);
|
uint64_t &RWDataSize, uint32_t &RWDataAlign);
|
||||||
|
|
||||||
|
// \brief Compute GOT size
|
||||||
|
unsigned computeGOTSize(const ObjectFile &Obj);
|
||||||
|
|
||||||
// \brief Compute the stub buffer size required for a section
|
// \brief Compute the stub buffer size required for a section
|
||||||
unsigned computeSectionStubBufSize(const ObjectFile &Obj,
|
unsigned computeSectionStubBufSize(const ObjectFile &Obj,
|
||||||
const SectionRef &Section);
|
const SectionRef &Section);
|
||||||
|
@ -433,6 +436,14 @@ protected:
|
||||||
// \brief Implementation of the generic part of the loadObject algorithm.
|
// \brief Implementation of the generic part of the loadObject algorithm.
|
||||||
Expected<ObjSectionToIDMap> loadObjectImpl(const object::ObjectFile &Obj);
|
Expected<ObjSectionToIDMap> loadObjectImpl(const object::ObjectFile &Obj);
|
||||||
|
|
||||||
|
// \brief Return size of Global Offset Table (GOT) entry
|
||||||
|
virtual size_t getGOTEntrySize() { return 0; }
|
||||||
|
|
||||||
|
// \brief Return true if the relocation R may require allocating a GOT entry.
|
||||||
|
virtual bool relocationNeedsGot(const RelocationRef &R) const {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
// \brief Return true if the relocation R may require allocating a stub.
|
// \brief Return true if the relocation R may require allocating a stub.
|
||||||
virtual bool relocationNeedsStub(const RelocationRef &R) const {
|
virtual bool relocationNeedsStub(const RelocationRef &R) const {
|
||||||
return true; // Conservative answer
|
return true; // Conservative answer
|
||||||
|
|
|
@ -0,0 +1,46 @@
|
||||||
|
# RUN: llvm-mc -triple=arm64-none-linux-gnu -filetype=obj -o %T/pic-reloc.o %s
|
||||||
|
# RUN: llvm-rtdyld -triple=arm64-none-linux-gnu -verify -check=%s %T/pic-reloc.o \
|
||||||
|
# RUN: -map-section pic-reloc.o,.got=0x20000 -dummy-extern f=0x1234 -dummy-extern g=0x5678
|
||||||
|
|
||||||
|
_s:
|
||||||
|
nop
|
||||||
|
_a1:
|
||||||
|
adrp x8, :got:f
|
||||||
|
_a2:
|
||||||
|
adrp x9, :got:g
|
||||||
|
_a3:
|
||||||
|
adrp x10, :got:_s
|
||||||
|
_l1:
|
||||||
|
ldr x8, [x8, :got_lo12:f]
|
||||||
|
_l2:
|
||||||
|
ldr x9, [x9, :got_lo12:g]
|
||||||
|
_l3:
|
||||||
|
ldr x10, [x10, :got_lo12:_s]
|
||||||
|
|
||||||
|
|
||||||
|
## We'll end up having two sections .text and .got,
|
||||||
|
## each is located on the start of a memory page
|
||||||
|
|
||||||
|
## Test that .got section has three entries pointing to f, g and _s
|
||||||
|
# *{8}section_addr(pic-reloc.o, .got) = f
|
||||||
|
# *{8}(section_addr(pic-reloc.o, .got) + 8) = g
|
||||||
|
# *{8}(section_addr(pic-reloc.o, .got) + 16) = _s
|
||||||
|
|
||||||
|
## Test that first adrp instruction really takes address of
|
||||||
|
## the .got section (_s label is on the start of a page)
|
||||||
|
# rtdyld-check: _s + (((*{4}_a1)[30:29] + ((*{4}_a1)[23:5] << 2)) << 12) = section_addr(pic-reloc.o, .got)
|
||||||
|
|
||||||
|
## Test that second adrp takes address of .got
|
||||||
|
# rtdyld-check: _s + (((*{4}_a2)[30:29] + ((*{4}_a2)[23:5] << 2)) << 12) = section_addr(pic-reloc.o, .got)
|
||||||
|
|
||||||
|
## Test that third adrp takes address of .got
|
||||||
|
# rtdyld-check: _s + (((*{4}_a3)[30:29] + ((*{4}_a3)[23:5] << 2)) << 12) = section_addr(pic-reloc.o, .got)
|
||||||
|
|
||||||
|
## Test that first ldr immediate value is 0 >> 3 = 0 (1st .got entry)
|
||||||
|
# rtdyld-check: (*{4}_l1)[21:10] = 0
|
||||||
|
|
||||||
|
## Test that second ldr immediate value is 8 >> 3 = 1 (2nd .got entry)
|
||||||
|
# rtdyld-check: (*{4}_l2)[21:10] = 1
|
||||||
|
|
||||||
|
## Test that third ldr immediate value is 16 >> 3 = 2 (3rd .got entry, addend is 0)
|
||||||
|
# rtdyld-check: (*{4}_l3)[21:10] = 2
|
Loading…
Reference in New Issue