//===----------------------------------------------------------------------===//
#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/MC/MCStreamer.h"
+#include "llvm/ExecutionEngine/ObjectBuffer.h"
+#include "llvm/ExecutionEngine/ObjectImage.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());
return Err;
}
-namespace {
-
template <class ELFT> class DyldELFObject : public ELFObjectFile<ELFT> {
LLVM_ELF_IMPORT_TYPES_ELFT(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 &SymRef, uint64_t Addr);
+ void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
// Methods for type inquiry through isa, cast and dyn_cast
static inline bool classof(const Binary *v) {
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
this->isDyldELFObject = true;
}
+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) {
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;
RegisteredEHFrameSections.clear();
}
-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);
+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<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,
}
// Return the .TOC. section and offset.
-void RuntimeDyldELF::findPPC64TOCSection(const ObjectFile &Obj,
+void RuntimeDyldELF::findPPC64TOCSection(ObjectImage &Obj,
ObjSectionToIDMap &LocalSections,
RelocationValueRef &Rel) {
// Set a default SectionID in case we do not find a TOC section below.
// 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.section_begin(), se = Obj.section_end();
+ for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
si != se; ++si) {
StringRef SectionName;
// Returns the sections and offset associated with the ODP entry referenced
// by Symbol.
-void RuntimeDyldELF::findOPDEntrySection(const ObjectFile &Obj,
+void RuntimeDyldELF::findOPDEntrySection(ObjectImage &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.section_begin(), se = Obj.section_end();
+ for (section_iterator si = Obj.begin_sections(), se = Obj.end_sections();
si != se; ++si) {
section_iterator RelSecI = si->getRelocatedSection();
- if (RelSecI == Obj.section_end())
+ if (RelSecI == Obj.end_sections())
continue;
StringRef RelSectionName;
if (Rel.Addend != (int64_t)TargetSymbolOffset)
continue;
- section_iterator tsi(Obj.section_end());
+ section_iterator tsi(Obj.end_sections());
check(TargetSymbol->getSection(tsi));
bool IsCode = tsi->isText();
Rel.SectionID = findOrEmitSection(Obj, (*tsi), IsCode, LocalSections);
}
relocation_iterator RuntimeDyldELF::processRelocationRef(
- unsigned SectionID, relocation_iterator RelI,
- const ObjectFile &Obj,
+ unsigned SectionID, relocation_iterator RelI, ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID, const SymbolTableMap &Symbols,
StubMap &Stubs) {
uint64_t RelType;
// Obtain the symbol name which is referenced in the relocation
StringRef TargetName;
- if (Symbol != Obj.symbol_end())
+ if (Symbol != Obj.end_symbols())
Symbol->getName(TargetName);
DEBUG(dbgs() << "\t\tRelType: " << RelType << " Addend: " << Addend
<< " TargetName: " << TargetName << "\n");
// 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.symbol_end()) {
+ if (Symbol != Obj.end_symbols()) {
lsi = Symbols.find(TargetName.data());
Symbol->getType(SymType);
}
} else {
// Search for the symbol in the global symbol table
SymbolTableMap::const_iterator gsi = GlobalSymbolTable.end();
- if (Symbol != Obj.symbol_end())
+ if (Symbol != Obj.end_symbols())
gsi = GlobalSymbolTable.find(TargetName.data());
if (gsi != GlobalSymbolTable.end()) {
Value.SectionID = gsi->second.first;
// 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());
+ section_iterator si(Obj.end_sections());
Symbol->getSection(si);
- if (si == Obj.section_end())
+ 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();
if (RelType == ELF::R_PPC64_REL24) {
// Determine ABI variant in use for this object.
unsigned AbiVariant;
- Obj.getPlatformFlags(AbiVariant);
+ Obj.getObjectFile()->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
return 0;
}
-void RuntimeDyldELF::finalizeLoad(const ObjectFile &Obj,
+void RuntimeDyldELF::finalizeLoad(ObjectImage &ObjImg,
ObjSectionToIDMap &SectionMap) {
// If necessary, allocate the global offset table
if (MemMgr) {
}
}
-bool RuntimeDyldELF::isCompatibleFile(const object::ObjectFile &Obj) const {
- return Obj.isELF();
+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();
}
} // namespace llvm