aboutsummaryrefslogtreecommitdiffstats
path: root/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp344
1 files changed, 148 insertions, 196 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index d95cffe..0f3ca0f 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -12,27 +12,23 @@
//===----------------------------------------------------------------------===//
#include "RuntimeDyldELF.h"
-#include "JITRegistrar.h"
-#include "ObjectImageCommon.h"
#include "llvm/ADT/IntervalMap.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ADT/StringRef.h"
#include "llvm/ADT/Triple.h"
-#include "llvm/ExecutionEngine/ObjectBuffer.h"
-#include "llvm/ExecutionEngine/ObjectImage.h"
+#include "llvm/MC/MCStreamer.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/ELF.h"
#include "llvm/Support/Endian.h"
#include "llvm/Support/MemoryBuffer.h"
+#include "llvm/Support/TargetRegistry.h"
using namespace llvm;
using namespace llvm::object;
#define DEBUG_TYPE "dyld"
-namespace {
-
static inline std::error_code check(std::error_code Err) {
if (Err) {
report_fatal_error(Err.message());
@@ -40,6 +36,8 @@ static inline std::error_code check(std::error_code Err) {
return Err;
}
+namespace {
+
template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
LLVM_ELF_IMPORT_TYPES_ELFT(ELFT)
@@ -52,16 +50,12 @@ template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
- std::unique_ptr<ObjectFile> UnderlyingFile;
-
public:
- DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile,
- MemoryBufferRef Wrapper, std::error_code &ec);
-
DyldELFObject(MemoryBufferRef Wrapper, std::error_code &ec);
void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
- void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
+
+ void updateSymbolAddress(const SymbolRef &SymRef, uint64_t Addr);
// Methods for type inquiry through isa, cast and dyn_cast
static inline bool classof(const Binary *v) {
@@ -71,42 +65,10 @@ public:
static inline bool classof(const ELFObjectFile<ELFT> *v) {
return v->isDyldType();
}
-};
-
-template <class ELFT> class ELFObjectImage : public ObjectImageCommon {
- bool Registered;
-public:
- ELFObjectImage(std::unique_ptr<ObjectBuffer> Input,
- std::unique_ptr<DyldELFObject<ELFT>> Obj)
- : ObjectImageCommon(std::move(Input), std::move(Obj)), Registered(false) {
- }
-
- virtual ~ELFObjectImage() {
- if (Registered)
- deregisterWithDebugger();
- }
-
- // Subclasses can override these methods to update the image with loaded
- // addresses for sections and common symbols
- void updateSectionAddress(const SectionRef &Sec, uint64_t Addr) override {
- static_cast<DyldELFObject<ELFT>*>(getObjectFile())
- ->updateSectionAddress(Sec, Addr);
- }
+};
- void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr) override {
- static_cast<DyldELFObject<ELFT>*>(getObjectFile())
- ->updateSymbolAddress(Sym, Addr);
- }
- void registerWithDebugger() override {
- JITRegistrar::getGDBRegistrar().registerObject(*Buffer);
- Registered = true;
- }
- void deregisterWithDebugger() override {
- JITRegistrar::getGDBRegistrar().deregisterObject(*Buffer);
- }
-};
// The MemoryBuffer passed into this constructor is just a wrapper around the
// actual memory. Ultimately, the Binary parent class will take ownership of
@@ -118,14 +80,6 @@ DyldELFObject<ELFT>::DyldELFObject(MemoryBufferRef Wrapper, std::error_code &EC)
}
template <class ELFT>
-DyldELFObject<ELFT>::DyldELFObject(std::unique_ptr<ObjectFile> UnderlyingFile,
- MemoryBufferRef Wrapper, std::error_code &EC)
- : ELFObjectFile<ELFT>(Wrapper, EC),
- UnderlyingFile(std::move(UnderlyingFile)) {
- this->isDyldELFObject = true;
-}
-
-template <class ELFT>
void DyldELFObject<ELFT>::updateSectionAddress(const SectionRef &Sec,
uint64_t Addr) {
DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
@@ -149,10 +103,89 @@ void DyldELFObject<ELFT>::updateSymbolAddress(const SymbolRef &SymRef,
sym->st_value = static_cast<addr_type>(Addr);
}
+class LoadedELFObjectInfo : public RuntimeDyld::LoadedObjectInfo {
+public:
+ LoadedELFObjectInfo(RuntimeDyldImpl &RTDyld, unsigned BeginIdx,
+ unsigned EndIdx)
+ : RuntimeDyld::LoadedObjectInfo(RTDyld, BeginIdx, EndIdx) {}
+
+ OwningBinary<ObjectFile>
+ getObjectForDebug(const ObjectFile &Obj) const override;
+};
+
+template <typename ELFT>
+std::unique_ptr<DyldELFObject<ELFT>>
+createRTDyldELFObject(MemoryBufferRef Buffer,
+ const LoadedELFObjectInfo &L,
+ std::error_code &ec) {
+ typedef typename ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
+ typedef typename ELFDataTypeTypedefHelper<ELFT>::value_type addr_type;
+
+ std::unique_ptr<DyldELFObject<ELFT>> Obj =
+ llvm::make_unique<DyldELFObject<ELFT>>(Buffer, ec);
+
+ // Iterate over all sections in the object.
+ for (const auto &Sec : Obj->sections()) {
+ StringRef SectionName;
+ Sec.getName(SectionName);
+ if (SectionName != "") {
+ DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
+ Elf_Shdr *shdr = const_cast<Elf_Shdr *>(
+ reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
+
+ if (uint64_t SecLoadAddr = L.getSectionLoadAddress(SectionName)) {
+ // This assumes that the address passed in matches the target address
+ // bitness. The template-based type cast handles everything else.
+ shdr->sh_addr = static_cast<addr_type>(SecLoadAddr);
+ }
+ }
+ }
+
+ return Obj;
+}
+
+OwningBinary<ObjectFile> createELFDebugObject(const ObjectFile &Obj,
+ const LoadedELFObjectInfo &L) {
+ assert(Obj.isELF() && "Not an ELF object file.");
+
+ std::unique_ptr<MemoryBuffer> Buffer =
+ MemoryBuffer::getMemBufferCopy(Obj.getData(), Obj.getFileName());
+
+ std::error_code ec;
+
+ std::unique_ptr<ObjectFile> DebugObj;
+ if (Obj.getBytesInAddress() == 4 && Obj.isLittleEndian()) {
+ typedef ELFType<support::little, 2, false> ELF32LE;
+ DebugObj = createRTDyldELFObject<ELF32LE>(Buffer->getMemBufferRef(), L, ec);
+ } else if (Obj.getBytesInAddress() == 4 && !Obj.isLittleEndian()) {
+ typedef ELFType<support::big, 2, false> ELF32BE;
+ DebugObj = createRTDyldELFObject<ELF32BE>(Buffer->getMemBufferRef(), L, ec);
+ } else if (Obj.getBytesInAddress() == 8 && !Obj.isLittleEndian()) {
+ typedef ELFType<support::big, 2, true> ELF64BE;
+ DebugObj = createRTDyldELFObject<ELF64BE>(Buffer->getMemBufferRef(), L, ec);
+ } else if (Obj.getBytesInAddress() == 8 && Obj.isLittleEndian()) {
+ typedef ELFType<support::little, 2, true> ELF64LE;
+ DebugObj = createRTDyldELFObject<ELF64LE>(Buffer->getMemBufferRef(), L, ec);
+ } else
+ llvm_unreachable("Unexpected ELF format");
+
+ assert(!ec && "Could not construct copy ELF object file");
+
+ return OwningBinary<ObjectFile>(std::move(DebugObj), std::move(Buffer));
+}
+
+OwningBinary<ObjectFile>
+LoadedELFObjectInfo::getObjectForDebug(const ObjectFile &Obj) const {
+ return createELFDebugObject(Obj, *this);
+}
+
} // namespace
namespace llvm {
+RuntimeDyldELF::RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
+RuntimeDyldELF::~RuntimeDyldELF() {}
+
void RuntimeDyldELF::registerEHFrames() {
if (!MemMgr)
return;
@@ -180,83 +213,14 @@ void RuntimeDyldELF::deregisterEHFrames() {
RegisteredEHFrameSections.clear();
}
-ObjectImage *
-RuntimeDyldELF::createObjectImageFromFile(std::unique_ptr<object::ObjectFile> ObjFile) {
- if (!ObjFile)
- return nullptr;
-
- std::error_code ec;
- MemoryBufferRef Buffer = ObjFile->getMemoryBufferRef();
-
- if (ObjFile->getBytesInAddress() == 4 && ObjFile->isLittleEndian()) {
- auto Obj =
- llvm::make_unique<DyldELFObject<ELFType<support::little, 2, false>>>(
- std::move(ObjFile), Buffer, ec);
- return new ELFObjectImage<ELFType<support::little, 2, false>>(
- nullptr, std::move(Obj));
- } else if (ObjFile->getBytesInAddress() == 4 && !ObjFile->isLittleEndian()) {
- auto Obj =
- llvm::make_unique<DyldELFObject<ELFType<support::big, 2, false>>>(
- std::move(ObjFile), Buffer, ec);
- return new ELFObjectImage<ELFType<support::big, 2, false>>(nullptr, std::move(Obj));
- } else if (ObjFile->getBytesInAddress() == 8 && !ObjFile->isLittleEndian()) {
- auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 2, true>>>(
- std::move(ObjFile), Buffer, ec);
- return new ELFObjectImage<ELFType<support::big, 2, true>>(nullptr,
- std::move(Obj));
- } else if (ObjFile->getBytesInAddress() == 8 && ObjFile->isLittleEndian()) {
- auto Obj =
- llvm::make_unique<DyldELFObject<ELFType<support::little, 2, true>>>(
- std::move(ObjFile), Buffer, ec);
- return new ELFObjectImage<ELFType<support::little, 2, true>>(
- nullptr, std::move(Obj));
- } else
- llvm_unreachable("Unexpected ELF format");
+std::unique_ptr<RuntimeDyld::LoadedObjectInfo>
+RuntimeDyldELF::loadObject(const object::ObjectFile &O) {
+ unsigned SectionStartIdx, SectionEndIdx;
+ std::tie(SectionStartIdx, SectionEndIdx) = loadObjectImpl(O);
+ return llvm::make_unique<LoadedELFObjectInfo>(*this, SectionStartIdx,
+ SectionEndIdx);
}
-std::unique_ptr<ObjectImage>
-RuntimeDyldELF::createObjectImage(std::unique_ptr<ObjectBuffer> Buffer) {
- if (Buffer->getBufferSize() < ELF::EI_NIDENT)
- llvm_unreachable("Unexpected ELF object size");
- std::pair<unsigned char, unsigned char> Ident =
- std::make_pair((uint8_t)Buffer->getBufferStart()[ELF::EI_CLASS],
- (uint8_t)Buffer->getBufferStart()[ELF::EI_DATA]);
- std::error_code ec;
-
- MemoryBufferRef Buf = Buffer->getMemBuffer();
-
- if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
- auto Obj =
- llvm::make_unique<DyldELFObject<ELFType<support::little, 4, false>>>(
- Buf, ec);
- return llvm::make_unique<
- ELFObjectImage<ELFType<support::little, 4, false>>>(std::move(Buffer),
- std::move(Obj));
- }
- if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
- auto Obj =
- llvm::make_unique<DyldELFObject<ELFType<support::big, 4, false>>>(Buf,
- ec);
- return llvm::make_unique<ELFObjectImage<ELFType<support::big, 4, false>>>(
- std::move(Buffer), std::move(Obj));
- }
- if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
- auto Obj = llvm::make_unique<DyldELFObject<ELFType<support::big, 8, true>>>(
- Buf, ec);
- return llvm::make_unique<ELFObjectImage<ELFType<support::big, 8, true>>>(
- std::move(Buffer), std::move(Obj));
- }
- assert(Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB &&
- "Unexpected ELF format");
- auto Obj =
- llvm::make_unique<DyldELFObject<ELFType<support::little, 8, true>>>(Buf,
- ec);
- return llvm::make_unique<ELFObjectImage<ELFType<support::little, 8, true>>>(
- std::move(Buffer), std::move(Obj));
-}
-
-RuntimeDyldELF::~RuntimeDyldELF() {}
-
void RuntimeDyldELF::resolveX86_64Relocation(const SectionEntry &Section,
uint64_t Offset, uint64_t Value,
uint32_t Type, int64_t Addend,
@@ -615,7 +579,7 @@ void RuntimeDyldELF::resolveMIPSRelocation(const SectionEntry &Section,
}
// Return the .TOC. section and offset.
-void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
+void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel) {
// Set a default SectionID in case we do not find a TOC section below.
@@ -628,7 +592,7 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
// The TOC consists of sections .got, .toc, .tocbss, .plt in that
// order. The TOC starts where the first of these sections starts.
- for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
+ for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
si != se; ++si) {
StringRef SectionName;
@@ -650,15 +614,15 @@ void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
// Returns the sections and offset associated with the ODP entry referenced
// by Symbol.
-void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
+void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel) {
// Get the ELF symbol value (st_value) to compare with Relocation offset in
// .opd entries
- for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
+ for (section_iterator si = Obj.section_begin(), se = Obj.section_end();
si != se; ++si) {
section_iterator RelSecI = si->getRelocatedSection();
- if (RelSecI == Obj.end_sections())
+ if (RelSecI == Obj.section_end())
continue;
StringRef RelSectionName;
@@ -700,7 +664,7 @@ void RuntimeDyldELF::findOPDEntrySection(ObjectImage &Obj,
if (Rel.Addend != (int64_t)TargetSymbolOffset)
continue;
- section_iterator tsi(Obj.end_sections());
+ section_iterator tsi(Obj.section_end());
check(TargetSymbol->getSection(tsi));
bool IsCode = tsi->isText();
Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections);
@@ -935,8 +899,9 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
}
relocation_iterator RuntimeDyldELF::processRelocationRef(
- unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
- ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
+ unsigned SectionID, relocation_iterator RelI,
+ const ObjectFile &Obj,
+ ObjSectionToIDMap &ObjSectionToID,
StubMap &Stubs) {
uint64_t RelType;
Check(RelI->getType(RelType));
@@ -946,66 +911,60 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
// Obtain the symbol name which is referenced in the relocation
StringRef TargetName;
- if (Symbol != Obj.end_symbols())
+ if (Symbol != Obj.symbol_end())
Symbol->getName(TargetName);
DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend
<< " TargetName: " << TargetName << "\n");
RelocationValueRef Value;
// First search for the symbol in the local symbol table
- SymbolTableMap::const_iterator lsi = Symbols.end();
SymbolRef::Type SymType = SymbolRef::ST_Unknown;
- if (Symbol != Obj.end_symbols()) {
- lsi = Symbols.find(TargetName.data());
+
+ // Search for the symbol in the global symbol table
+ RTDyldSymbolTable::const_iterator gsi = GlobalSymbolTable.end();
+ if (Symbol != Obj.symbol_end()) {
+ gsi = GlobalSymbolTable.find(TargetName.data());
Symbol->getType(SymType);
}
- if (lsi != Symbols.end()) {
- Value.SectionID = lsi->second.first;
- Value.Offset = lsi->second.second;
- Value.Addend = lsi->second.second + Addend;
+ if (gsi != GlobalSymbolTable.end()) {
+ const auto &SymInfo = gsi->second;
+ Value.SectionID = SymInfo.getSectionID();
+ Value.Offset = SymInfo.getOffset();
+ Value.Addend = SymInfo.getOffset() + Addend;
} else {
- // Search for the symbol in the global symbol table
- SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
- if (Symbol != Obj.end_symbols())
- gsi = GlobalSymbolTable.find(TargetName.data());
- if (gsi != GlobalSymbolTable.end()) {
- Value.SectionID = gsi->second.first;
- Value.Offset = gsi->second.second;
- Value.Addend = gsi->second.second + Addend;
- } else {
- switch (SymType) {
- case SymbolRef::ST_Debug: {
- // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
- // and can be changed by another developers. Maybe best way is add
- // a new symbol type ST_Section to SymbolRef and use it.
- section_iterator si(Obj.end_sections());
- Symbol->getSection(si);
- if (si == Obj.end_sections())
- llvm_unreachable("Symbol section not found, bad object file format!");
- DEBUG(dbgs() << "\t\tThis is section symbol\n");
- bool isCode = si->isText();
- Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID);
- Value.Addend = Addend;
- break;
- }
- case SymbolRef::ST_Data:
- case SymbolRef::ST_Unknown: {
- Value.SymbolName = TargetName.data();
- Value.Addend = Addend;
-
- // Absolute relocations will have a zero symbol ID (STN_UNDEF), which
- // will manifest here as a NULL symbol name.
- // We can set this as a valid (but empty) symbol name, and rely
- // on addRelocationForSymbol to handle this.
- if (!Value.SymbolName)
- Value.SymbolName = "";
- break;
- }
- default:
- llvm_unreachable("Unresolved symbol type!");
- break;
- }
+ switch (SymType) {
+ case SymbolRef::ST_Debug: {
+ // TODO: Now ELF SymbolRef::ST_Debug = STT_SECTION, it's not obviously
+ // and can be changed by another developers. Maybe best way is add
+ // a new symbol type ST_Section to SymbolRef and use it.
+ section_iterator si(Obj.section_end());
+ Symbol->getSection(si);
+ if (si == Obj.section_end())
+ llvm_unreachable("Symbol section not found, bad object file format!");
+ DEBUG(dbgs() << "\t\tThis is section symbol\n");
+ bool isCode = si->isText();
+ Value.SectionID = findOrEmitSection(Obj, (*si), isCode, ObjSectionToID);
+ Value.Addend = Addend;
+ break;
+ }
+ case SymbolRef::ST_Data:
+ case SymbolRef::ST_Unknown: {
+ Value.SymbolName = TargetName.data();
+ Value.Addend = Addend;
+
+ // Absolute relocations will have a zero symbol ID (STN_UNDEF), which
+ // will manifest here as a NULL symbol name.
+ // We can set this as a valid (but empty) symbol name, and rely
+ // on addRelocationForSymbol to handle this.
+ if (!Value.SymbolName)
+ Value.SymbolName = "";
+ break;
+ }
+ default:
+ llvm_unreachable("Unresolved symbol type!");
+ break;
}
}
+
uint64_t Offset;
Check(RelI->getOffset(Offset));
@@ -1135,7 +1094,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
if (RelType == ELF::R_PPC64_REL24) {
// Determine ABI variant in use for this object.
unsigned AbiVariant;
- Obj.getObjectFile()->getPlatformFlags(AbiVariant);
+ Obj.getPlatformFlags(AbiVariant);
AbiVariant &= ELF::EF_PPC64_ABI;
// A PPC branch relocation will need a stub function if the target is
// an external symbol (Symbol::ST_Unknown) or if the target address
@@ -1495,7 +1454,7 @@ uint64_t RuntimeDyldELF::findGOTEntry(uint64_t LoadAddress, uint64_t Offset) {
return 0;
}
-void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg,
+void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
ObjSectionToIDMap &SectionMap) {
// If necessary, allocate the global offset table
if (MemMgr) {
@@ -1533,15 +1492,8 @@ void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg,
}
}
-bool RuntimeDyldELF::isCompatibleFormat(const ObjectBuffer *Buffer) const {
- if (Buffer->getBufferSize() < strlen(ELF::ElfMagic))
- return false;
- return (memcmp(Buffer->getBufferStart(), ELF::ElfMagic,
- strlen(ELF::ElfMagic))) == 0;
-}
-
-bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile *Obj) const {
- return Obj->isELF();
+bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
+ return Obj.isELF();
}
} // namespace llvm