summaryrefslogtreecommitdiffstats
path: root/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2014-11-26 16:54:40 +0000
committerLang Hames <lhames@gmail.com>2014-11-26 16:54:40 +0000
commitb5c7b1ff833d387db18d075e4c95fe5546ca138a (patch)
treeecaf5aebb7fa099e857a7bf408b521fd010e323e /llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
parent450425c980137ee1e57dd77f149aecaea8300544 (diff)
downloadbcm5719-llvm-b5c7b1ff833d387db18d075e4c95fe5546ca138a.tar.gz
bcm5719-llvm-b5c7b1ff833d387db18d075e4c95fe5546ca138a.zip
[MCJIT] Reapply r222828 and r222810-r222812 with fix for MSVC move-op issues.
llvm-svn: 222840
Diffstat (limited to 'llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp')
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp260
1 files changed, 109 insertions, 151 deletions
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index d95cffef03f..d213cc93793 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/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,7 +899,8 @@ void RuntimeDyldELF::resolveRelocation(const SectionEntry &Section,
}
relocation_iterator RuntimeDyldELF::processRelocationRef(
- unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
+ unsigned SectionID, relocation_iterator RelI,
+ const ObjectFile &Obj,
ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
StubMap &Stubs) {
uint64_t RelType;
@@ -946,7 +911,7 @@ 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");
@@ -954,7 +919,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
// 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()) {
+ if (Symbol != Obj.symbol_end()) {
lsi = Symbols.find(TargetName.data());
Symbol->getType(SymType);
}
@@ -965,7 +930,7 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
} else {
// Search for the symbol in the global symbol table
SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
- if (Symbol != Obj.end_symbols())
+ if (Symbol != Obj.symbol_end())
gsi = GlobalSymbolTable.find(TargetName.data());
if (gsi != GlobalSymbolTable.end()) {
Value.SectionID = gsi->second.first;
@@ -977,9 +942,9 @@ relocation_iterator RuntimeDyldELF::processRelocationRef(
// 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());
+ section_iterator si(Obj.section_end());
Symbol->getSection(si);
- if (si == Obj.end_sections())
+ 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();
@@ -1135,7 +1100,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 +1460,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 +1498,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
OpenPOWER on IntegriCloud