diff options
author | Andrew Kaylor <andrew.kaylor@intel.com> | 2013-10-05 01:52:09 +0000 |
---|---|---|
committer | Andrew Kaylor <andrew.kaylor@intel.com> | 2013-10-05 01:52:09 +0000 |
commit | 9cffedbbfd009131699c4fcbcb2f820555762812 (patch) | |
tree | 2e6be580397b7be7db0cf1d10ae929c1b82cedf5 /lib/ExecutionEngine/RuntimeDyld | |
parent | c664d76716ba87577b6c2a513ce4fe0712a2d3e2 (diff) | |
download | llvm-9cffedbbfd009131699c4fcbcb2f820555762812.tar.gz llvm-9cffedbbfd009131699c4fcbcb2f820555762812.tar.bz2 llvm-9cffedbbfd009131699c4fcbcb2f820555762812.tar.xz |
Adding multiple GOT handling to RuntimeDyldELF
Patch by Ashok Thirumurthi
git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@192020 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld')
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp | 128 | ||||
-rw-r--r-- | lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h | 12 |
2 files changed, 81 insertions, 59 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp index eb2a1a771d..a438dcd879 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp @@ -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; + } } } - } - 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); + 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); + } } - // Calculate the load address of this entry - return getSectionLoadAddress(GOTSectionID) + (GOTIndex * GOTEntrySize); + assert(GOTIndex != -1 && "Unable to find requested GOT entry."); + 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!"); } } diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h index 14fb5740e5..67dc693b1b 100644 --- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h +++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h @@ -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); |