Adding multiple GOT handling to RuntimeDyldELF

Patch by Ashok Thirumurthi

llvm-svn: 192020
This commit is contained in:
Andrew Kaylor 2013-10-05 01:52:09 +00:00
parent c174ea9ac8
commit 480dcb3ee7
2 changed files with 82 additions and 60 deletions

View File

@ -1250,9 +1250,16 @@ void RuntimeDyldELF::processRelocationRef(unsigned SectionID,
}
void RuntimeDyldELF::updateGOTEntries(StringRef Name, uint64_t Addr) {
for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
if (GOTEntries[i].SymbolName != 0 && GOTEntries[i].SymbolName == Name) {
GOTEntries[i].Offset = Addr;
SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator it;
SmallVectorImpl<std::pair<SID, GOTRelocations> >::iterator end = GOTs.end();
for (it = GOTs.begin(); it != end; ++it) {
GOTRelocations &GOTEntries = it->second;
for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
if (GOTEntries[i].SymbolName != 0 && GOTEntries[i].SymbolName == Name) {
GOTEntries[i].Offset = Addr;
}
}
}
}
@ -1283,69 +1290,80 @@ size_t RuntimeDyldELF::getGOTEntrySize() {
uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress,
uint64_t Offset) {
assert(GOTSectionID != 0
&& "Attempting to lookup GOT entry but the GOT was never allocated.");
if (GOTSectionID == 0) {
return 0;
}
size_t GOTEntrySize = getGOTEntrySize();
const size_t GOTEntrySize = getGOTEntrySize();
SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator it;
SmallVectorImpl<std::pair<SID, GOTRelocations> >::const_iterator end = GOTs.end();
// Find the matching entry in our vector.
int GOTIndex = -1;
uint64_t SymbolOffset = 0;
for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
if (GOTEntries[i].SymbolName == 0) {
if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress &&
GOTEntries[i].Offset == Offset) {
GOTIndex = i;
SymbolOffset = GOTEntries[i].Offset;
break;
}
} else {
// GOT entries for external symbols use the addend as the address when
// the external symbol has been resolved.
if (GOTEntries[i].Offset == LoadAddress) {
GOTIndex = i;
// Don't use the Addend here. The relocation handler will use it.
break;
for (it = GOTs.begin(); it != end; ++it) {
SID GOTSectionID = it->first;
const GOTRelocations &GOTEntries = it->second;
// Find the matching entry in our vector.
uint64_t SymbolOffset = 0;
for (int i = 0, e = GOTEntries.size(); i != e; ++i) {
if (GOTEntries[i].SymbolName == 0) {
if (getSectionLoadAddress(GOTEntries[i].SectionID) == LoadAddress &&
GOTEntries[i].Offset == Offset) {
GOTIndex = i;
SymbolOffset = GOTEntries[i].Offset;
break;
}
} else {
// GOT entries for external symbols use the addend as the address when
// the external symbol has been resolved.
if (GOTEntries[i].Offset == LoadAddress) {
GOTIndex = i;
// Don't use the Addend here. The relocation handler will use it.
break;
}
}
}
if (GOTIndex != -1) {
if (GOTEntrySize == sizeof(uint64_t)) {
uint64_t *LocalGOTAddr = (uint64_t*)getSectionAddress(GOTSectionID);
// Fill in this entry with the address of the symbol being referenced.
LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset;
} else {
uint32_t *LocalGOTAddr = (uint32_t*)getSectionAddress(GOTSectionID);
// Fill in this entry with the address of the symbol being referenced.
LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset);
}
// Calculate the load address of this entry
return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize);
}
}
assert(GOTIndex != -1 && "Unable to find requested GOT entry.");
if (GOTIndex == -1)
return 0;
if (GOTEntrySize == sizeof(uint64_t)) {
uint64_t *LocalGOTAddr = (uint64_t*)getSectionAddress(GOTSectionID);
// Fill in this entry with the address of the symbol being referenced.
LocalGOTAddr[GOTIndex] = LoadAddress + SymbolOffset;
} else {
uint32_t *LocalGOTAddr = (uint32_t*)getSectionAddress(GOTSectionID);
// Fill in this entry with the address of the symbol being referenced.
LocalGOTAddr[GOTIndex] = (uint32_t)(LoadAddress + SymbolOffset);
}
// Calculate the load address of this entry
return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize);
return 0;
}
void RuntimeDyldELF::finalizeLoad() {
// Allocate the GOT if necessary
size_t numGOTEntries = GOTEntries.size();
if (numGOTEntries != 0) {
// Allocate memory for the section
unsigned SectionID = Sections.size();
size_t TotalSize = numGOTEntries * getGOTEntrySize();
uint8_t *Addr = MemMgr->allocateDataSection(
TotalSize, getGOTEntrySize(), SectionID, ".got", false);
if (!Addr)
report_fatal_error("Unable to allocate memory for GOT!");
Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0));
// For now, initialize all GOT entries to zero. We'll fill them in as
// needed when GOT-based relocations are applied.
memset(Addr, 0, TotalSize);
GOTSectionID = SectionID;
if (MemMgr) {
// Allocate the GOT if necessary
size_t numGOTEntries = GOTEntries.size();
if (numGOTEntries != 0) {
// Allocate memory for the section
unsigned SectionID = Sections.size();
size_t TotalSize = numGOTEntries * getGOTEntrySize();
uint8_t *Addr = MemMgr->allocateDataSection(TotalSize, getGOTEntrySize(),
SectionID, ".got", false);
if (!Addr)
report_fatal_error("Unable to allocate memory for GOT!");
GOTs.push_back(std::make_pair(SectionID, GOTEntries));
Sections.push_back(SectionEntry(".got", Addr, TotalSize, 0));
// For now, initialize all GOT entries to zero. We'll fill them in as
// needed when GOT-based relocations are applied.
memset(Addr, 0, TotalSize);
}
}
else {
report_fatal_error("Unable to allocate memory for GOT!");
}
}

View File

@ -15,6 +15,7 @@
#define LLVM_RUNTIME_DYLD_ELF_H
#include "RuntimeDyldImpl.h"
#include "llvm/ADT/DenseMap.h"
using namespace llvm;
@ -91,12 +92,15 @@ class RuntimeDyldELF : public RuntimeDyldImpl {
virtual void updateGOTEntries(StringRef Name, uint64_t Addr);
SmallVector<RelocationValueRef, 2> GOTEntries;
unsigned GOTSectionID;
// Relocation entries for symbols whose position-independant offset is
// updated in a global offset table.
typedef unsigned SID; // Type for SectionIDs
typedef SmallVector<RelocationValueRef, 2> GOTRelocations;
GOTRelocations GOTEntries; // List of entries requiring finalization.
SmallVector<std::pair<SID, GOTRelocations>, 8> GOTs; // Allocated tables.
public:
RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm),
GOTSectionID(0)
RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm)
{}
virtual void resolveRelocation(const RelocationEntry &RE, uint64_t Value);