summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/llvm/Object/ELF.h9
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt3
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp37
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp169
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h12
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h21
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp4
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h4
-rw-r--r--lib/Object/ELFObjectFile.cpp10
9 files changed, 235 insertions, 34 deletions
diff --git a/include/llvm/Object/ELF.h b/include/llvm/Object/ELF.h
index 0828985f2e..e493f5bd92 100644
--- a/include/llvm/Object/ELF.h
+++ b/include/llvm/Object/ELF.h
@@ -33,6 +33,15 @@
namespace llvm {
namespace object {
+// Subclasses of ELFObjectFile may need this for template instantiation
+inline std::pair<unsigned char, unsigned char>
+getElfArchType(MemoryBuffer *Object) {
+ if (Object->getBufferSize() < ELF::EI_NIDENT)
+ return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
+ return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
+ , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
+}
+
// Templates to choose Elf_Addr and Elf_Off depending on is64Bits.
template<support::endianness target_endianness>
struct ELFDataTypeTypedefHelperCommon {
diff --git a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
index 002e63cd3b..cbf7cf14d4 100644
--- a/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
+++ b/lib/ExecutionEngine/RuntimeDyld/CMakeLists.txt
@@ -1,5 +1,6 @@
add_llvm_library(LLVMRuntimeDyld
+ GDBRegistrar.cpp
RuntimeDyld.cpp
- RuntimeDyldMachO.cpp
RuntimeDyldELF.cpp
+ RuntimeDyldMachO.cpp
)
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 63cec1aca3..1b1840ae06 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -59,11 +59,17 @@ void RuntimeDyldImpl::mapSectionAddress(void *LocalAddress,
llvm_unreachable("Attempting to remap address of unknown section!");
}
+// Subclasses can implement this method to create specialized image instances
+// The caller owns the the pointer that is returned.
+ObjectImage *RuntimeDyldImpl::createObjectImage(const MemoryBuffer *InputBuffer) {
+ ObjectFile *ObjFile = ObjectFile::createObjectFile(const_cast<MemoryBuffer*>
+ (InputBuffer));
+ ObjectImage *Obj = new ObjectImage(ObjFile);
+ return Obj;
+}
+
bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
- // FIXME: ObjectFile don't modify MemoryBuffer.
- // It should use const MemoryBuffer as parameter.
- OwningPtr<ObjectFile> obj(ObjectFile::createObjectFile(
- const_cast<MemoryBuffer*>(InputBuffer)));
+ OwningPtr<ObjectImage> obj(createObjectImage(InputBuffer));
if (!obj)
report_fatal_error("Unable to create object image from memory buffer!");
@@ -110,7 +116,8 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
(uintptr_t)FileOffset;
uintptr_t SectOffset = (uintptr_t)(SymPtr - (const uint8_t*)sData.begin());
unsigned SectionID =
- findOrEmitSection(*si,
+ findOrEmitSection(*obj,
+ *si,
SymType == object::SymbolRef::ST_Function,
LocalSections);
bool isGlobal = flags & SymbolRef::SF_Global;
@@ -128,7 +135,7 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
// Allocate common symbols
if (CommonSize != 0)
- emitCommonSymbols(CommonSymbols, CommonSize, LocalSymbols);
+ emitCommonSymbols(*obj, CommonSymbols, CommonSize, LocalSymbols);
// Parse and proccess relocations
DEBUG(dbgs() << "Parse relocations:\n");
@@ -145,7 +152,7 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
// If it's first relocation in this section, find its SectionID
if (isFirstRelocation) {
- SectionID = findOrEmitSection(*si, true, LocalSections);
+ SectionID = findOrEmitSection(*obj, *si, true, LocalSections);
DEBUG(dbgs() << "\tSectionID: " << SectionID << "\n");
isFirstRelocation = false;
}
@@ -164,10 +171,14 @@ bool RuntimeDyldImpl::loadObject(const MemoryBuffer *InputBuffer) {
processRelocationRef(RI, *obj, LocalSections, LocalSymbols, Stubs);
}
}
+
+ handleObjectLoaded(obj.take());
+
return false;
}
-unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map,
+unsigned RuntimeDyldImpl::emitCommonSymbols(ObjectImage &Obj,
+ const CommonSymbolMap &Map,
uint64_t TotalSize,
LocalSymbolMap &LocalSymbols) {
// Allocate memory for the section
@@ -191,6 +202,7 @@ unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map,
uint64_t Size = it->second;
StringRef Name;
it->first.getName(Name);
+ Obj.updateSymbolAddress(it->first, (uint64_t)Addr);
LocalSymbols[Name.data()] = SymbolLoc(SectionID, Offset);
Offset += Size;
Addr += Size;
@@ -199,7 +211,8 @@ unsigned RuntimeDyldImpl::emitCommonSymbols(const CommonSymbolMap &Map,
return SectionID;
}
-unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
+unsigned RuntimeDyldImpl::emitSection(ObjectImage &Obj,
+ const SectionRef &Section,
bool IsCode) {
unsigned StubBufSize = 0,
@@ -257,6 +270,7 @@ unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
<< " StubBufSize: " << StubBufSize
<< " Allocate: " << Allocate
<< "\n");
+ Obj.updateSectionAddress(Section, (uint64_t)Addr);
}
else {
// Even if we didn't load the section, we need to record an entry for it
@@ -277,7 +291,8 @@ unsigned RuntimeDyldImpl::emitSection(const SectionRef &Section,
return SectionID;
}
-unsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section,
+unsigned RuntimeDyldImpl::findOrEmitSection(ObjectImage &Obj,
+ const SectionRef &Section,
bool IsCode,
ObjSectionToIDMap &LocalSections) {
@@ -286,7 +301,7 @@ unsigned RuntimeDyldImpl::findOrEmitSection(const SectionRef &Section,
if (i != LocalSections.end())
SectionID = i->second;
else {
- SectionID = emitSection(Section, IsCode);
+ SectionID = emitSection(Obj, Section, IsCode);
LocalSections[Section] = SectionID;
}
return SectionID;
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index 57fefee5de..e2ebc342ad 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -20,11 +20,176 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/ELF.h"
#include "llvm/ADT/Triple.h"
+#include "llvm/Object/ELF.h"
+#include "JITRegistrar.h"
using namespace llvm;
using namespace llvm::object;
+namespace {
+
+template<support::endianness target_endianness, bool is64Bits>
+class DyldELFObject : public ELFObjectFile<target_endianness, is64Bits> {
+ LLVM_ELF_IMPORT_TYPES(target_endianness, is64Bits)
+
+ typedef Elf_Shdr_Impl<target_endianness, is64Bits> Elf_Shdr;
+ typedef Elf_Sym_Impl<target_endianness, is64Bits> Elf_Sym;
+ typedef Elf_Rel_Impl<target_endianness, is64Bits, false> Elf_Rel;
+ typedef Elf_Rel_Impl<target_endianness, is64Bits, true> Elf_Rela;
+
+ typedef typename ELFObjectFile<target_endianness, is64Bits>::
+ Elf_Ehdr Elf_Ehdr;
+
+ typedef typename ELFDataTypeTypedefHelper<
+ target_endianness, is64Bits>::value_type addr_type;
+
+protected:
+ // This duplicates the 'Data' member in the 'Binary' base class
+ // but it is necessary to workaround a bug in gcc 4.2
+ MemoryBuffer *InputData;
+
+public:
+ DyldELFObject(MemoryBuffer *Object, error_code &ec);
+
+ void updateSectionAddress(const SectionRef &Sec, uint64_t Addr);
+ void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr);
+
+ const MemoryBuffer& getBuffer() const { return *InputData; }
+
+ // Methods for type inquiry through isa, cast, and dyn_cast
+ static inline bool classof(const Binary *v) {
+ return (isa<ELFObjectFile<target_endianness, is64Bits> >(v)
+ && classof(cast<ELFObjectFile<target_endianness, is64Bits> >(v)));
+ }
+ static inline bool classof(
+ const ELFObjectFile<target_endianness, is64Bits> *v) {
+ return v->isDyldType();
+ }
+ static inline bool classof(const DyldELFObject *v) {
+ return true;
+ }
+};
+
+template<support::endianness target_endianness, bool is64Bits>
+class ELFObjectImage : public ObjectImage {
+ protected:
+ DyldELFObject<target_endianness, is64Bits> *DyldObj;
+ bool Registered;
+
+ public:
+ ELFObjectImage(DyldELFObject<target_endianness, is64Bits> *Obj)
+ : ObjectImage(Obj),
+ DyldObj(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
+ virtual void updateSectionAddress(const SectionRef &Sec, uint64_t Addr)
+ {
+ DyldObj->updateSectionAddress(Sec, Addr);
+ }
+
+ virtual void updateSymbolAddress(const SymbolRef &Sym, uint64_t Addr)
+ {
+ DyldObj->updateSymbolAddress(Sym, Addr);
+ }
+
+ virtual void registerWithDebugger()
+ {
+ JITRegistrar::getGDBRegistrar().registerObject(DyldObj->getBuffer());
+ Registered = true;
+ }
+ virtual void deregisterWithDebugger()
+ {
+ JITRegistrar::getGDBRegistrar().deregisterObject(DyldObj->getBuffer());
+ }
+};
+
+template<support::endianness target_endianness, bool is64Bits>
+DyldELFObject<target_endianness, is64Bits>::DyldELFObject(MemoryBuffer *Object,
+ error_code &ec)
+ : ELFObjectFile<target_endianness, is64Bits>(Object, ec),
+ InputData(Object) {
+ this->isDyldELFObject = true;
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+void DyldELFObject<target_endianness, is64Bits>::updateSectionAddress(
+ const SectionRef &Sec,
+ uint64_t Addr) {
+ DataRefImpl ShdrRef = Sec.getRawDataRefImpl();
+ Elf_Shdr *shdr = const_cast<Elf_Shdr*>(
+ reinterpret_cast<const Elf_Shdr *>(ShdrRef.p));
+
+ // This assumes the address passed in matches the target address bitness
+ // The template-based type cast handles everything else.
+ shdr->sh_addr = static_cast<addr_type>(Addr);
+}
+
+template<support::endianness target_endianness, bool is64Bits>
+void DyldELFObject<target_endianness, is64Bits>::updateSymbolAddress(
+ const SymbolRef &SymRef,
+ uint64_t Addr) {
+
+ Elf_Sym *sym = const_cast<Elf_Sym*>(
+ ELFObjectFile<target_endianness, is64Bits>::
+ getSymbol(SymRef.getRawDataRefImpl()));
+
+ // This assumes the address passed in matches the target address bitness
+ // The template-based type cast handles everything else.
+ sym->st_value = static_cast<addr_type>(Addr);
+}
+
+} // namespace
+
+
namespace llvm {
+ObjectImage *RuntimeDyldELF::createObjectImage(
+ const MemoryBuffer *ConstInputBuffer) {
+ MemoryBuffer *InputBuffer = const_cast<MemoryBuffer*>(ConstInputBuffer);
+ std::pair<unsigned char, unsigned char> Ident = getElfArchType(InputBuffer);
+ error_code ec;
+
+ if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2LSB) {
+ DyldELFObject<support::little, false> *Obj =
+ new DyldELFObject<support::little, false>(InputBuffer, ec);
+ return new ELFObjectImage<support::little, false>(Obj);
+ }
+ else if (Ident.first == ELF::ELFCLASS32 && Ident.second == ELF::ELFDATA2MSB) {
+ DyldELFObject<support::big, false> *Obj =
+ new DyldELFObject<support::big, false>(InputBuffer, ec);
+ return new ELFObjectImage<support::big, false>(Obj);
+ }
+ else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2MSB) {
+ DyldELFObject<support::big, true> *Obj =
+ new DyldELFObject<support::big, true>(InputBuffer, ec);
+ return new ELFObjectImage<support::big, true>(Obj);
+ }
+ else if (Ident.first == ELF::ELFCLASS64 && Ident.second == ELF::ELFDATA2LSB) {
+ DyldELFObject<support::little, true> *Obj =
+ new DyldELFObject<support::little, true>(InputBuffer, ec);
+ return new ELFObjectImage<support::little, true>(Obj);
+ }
+ else
+ llvm_unreachable("Unexpected ELF format");
+}
+
+void RuntimeDyldELF::handleObjectLoaded(ObjectImage *Obj)
+{
+ Obj->registerWithDebugger();
+ // Save the loaded object. It will deregister itself when deleted
+ LoadedObject = Obj;
+}
+
+RuntimeDyldELF::~RuntimeDyldELF() {
+ if (LoadedObject)
+ delete LoadedObject;
+}
void RuntimeDyldELF::resolveX86_64Relocation(uint8_t *LocalAddress,
uint64_t FinalAddress,
@@ -167,7 +332,7 @@ void RuntimeDyldELF::resolveRelocation(uint8_t *LocalAddress,
}
void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
- const ObjectFile &Obj,
+ ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID,
LocalSymbolMap &Symbols,
StubMap &Stubs) {
@@ -206,7 +371,7 @@ void RuntimeDyldELF::processRelocationRef(const ObjRelocationInfo &Rel,
if (si == Obj.end_sections())
llvm_unreachable("Symbol section not found, bad object file format!");
DEBUG(dbgs() << "\t\tThis is section symbol\n");
- Value.SectionID = findOrEmitSection((*si), true, ObjSectionToID);
+ Value.SectionID = findOrEmitSection(Obj, (*si), true, ObjSectionToID);
Value.Addend = Addend;
break;
}
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
index 36566da57a..e7f6fab16f 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.h
@@ -22,6 +22,8 @@ using namespace llvm;
namespace llvm {
class RuntimeDyldELF : public RuntimeDyldImpl {
protected:
+ ObjectImage *LoadedObject;
+
void resolveX86_64Relocation(uint8_t *LocalAddress,
uint64_t FinalAddress,
uint64_t Value,
@@ -47,12 +49,18 @@ protected:
int64_t Addend);
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
- const ObjectFile &Obj,
+ ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID,
LocalSymbolMap &Symbols, StubMap &Stubs);
+ virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer);
+ virtual void handleObjectLoaded(ObjectImage *Obj);
+
public:
- RuntimeDyldELF(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
+ RuntimeDyldELF(RTDyldMemoryManager *mm)
+ : RuntimeDyldImpl(mm), LoadedObject(0) {}
+
+ virtual ~RuntimeDyldELF();
bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
};
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
index bf678af6ec..2dea13f15c 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldImpl.h
@@ -29,6 +29,7 @@
#include "llvm/ADT/Triple.h"
#include <map>
#include "llvm/Support/Format.h"
+#include "ObjectImage.h"
using namespace llvm;
using namespace llvm::object;
@@ -154,7 +155,8 @@ protected:
/// \brief Emits a section containing common symbols.
/// \return SectionID.
- unsigned emitCommonSymbols(const CommonSymbolMap &Map,
+ unsigned emitCommonSymbols(ObjectImage &Obj,
+ const CommonSymbolMap &Map,
uint64_t TotalSize,
LocalSymbolMap &Symbols);
@@ -162,14 +164,18 @@ protected:
/// \param IsCode if it's true then allocateCodeSection() will be
/// used for emmits, else allocateDataSection() will be used.
/// \return SectionID.
- unsigned emitSection(const SectionRef &Section, bool IsCode);
+ unsigned emitSection(ObjectImage &Obj,
+ const SectionRef &Section,
+ bool IsCode);
/// \brief Find Section in LocalSections. If the secton is not found - emit
/// it and store in LocalSections.
/// \param IsCode if it's true then allocateCodeSection() will be
/// used for emmits, else allocateDataSection() will be used.
/// \return SectionID.
- unsigned findOrEmitSection(const SectionRef &Section, bool IsCode,
+ unsigned findOrEmitSection(ObjectImage &Obj,
+ const SectionRef &Section,
+ bool IsCode,
ObjSectionToIDMap &LocalSections);
/// \brief If Value.SymbolName is NULL then store relocation to the
@@ -200,11 +206,18 @@ protected:
/// \brief Parses the object file relocation and store it to Relocations
/// or SymbolRelocations. Its depend from object file type.
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
- const ObjectFile &Obj,
+ ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID,
LocalSymbolMap &Symbols, StubMap &Stubs) = 0;
void resolveSymbols();
+ virtual ObjectImage *createObjectImage(const MemoryBuffer *InputBuffer);
+ virtual void handleObjectLoaded(ObjectImage *Obj)
+ {
+ // Subclasses may choose to retain this image if they have a use for it
+ delete Obj;
+ }
+
public:
RuntimeDyldImpl(RTDyldMemoryManager *mm) : MemMgr(mm), HasError(false) {}
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
index 1318b44542..b7f515d6ce 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.cpp
@@ -205,7 +205,7 @@ resolveARMRelocation(uint8_t *LocalAddress,
}
void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
- const ObjectFile &Obj,
+ ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID,
LocalSymbolMap &Symbols,
StubMap &Stubs) {
@@ -246,7 +246,7 @@ void RuntimeDyldMachO::processRelocationRef(const ObjRelocationInfo &Rel,
break;
}
assert(si != se && "No section containing relocation!");
- Value.SectionID = findOrEmitSection(*si, true, ObjSectionToID);
+ Value.SectionID = findOrEmitSection(Obj, *si, true, ObjSectionToID);
Value.Addend = *(const intptr_t *)Target;
if (Value.Addend) {
// The MachO addend is offset from the current section, we need set it
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
index 898b85190e..418d130f63 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldMachO.h
@@ -49,7 +49,7 @@ protected:
int64_t Addend);
virtual void processRelocationRef(const ObjRelocationInfo &Rel,
- const ObjectFile &Obj,
+ ObjectImage &Obj,
ObjSectionToIDMap &ObjSectionToID,
LocalSymbolMap &Symbols, StubMap &Stubs);
@@ -59,7 +59,7 @@ public:
uint64_t Value,
uint32_t Type,
int64_t Addend);
-
+
RuntimeDyldMachO(RTDyldMemoryManager *mm) : RuntimeDyldImpl(mm) {}
bool isCompatibleFormat(const MemoryBuffer *InputBuffer) const;
diff --git a/lib/Object/ELFObjectFile.cpp b/lib/Object/ELFObjectFile.cpp
index ab5f8108af..663b84ec8b 100644
--- a/lib/Object/ELFObjectFile.cpp
+++ b/lib/Object/ELFObjectFile.cpp
@@ -17,16 +17,6 @@ namespace llvm {
using namespace object;
-namespace {
- std::pair<unsigned char, unsigned char>
- getElfArchType(MemoryBuffer *Object) {
- if (Object->getBufferSize() < ELF::EI_NIDENT)
- return std::make_pair((uint8_t)ELF::ELFCLASSNONE,(uint8_t)ELF::ELFDATANONE);
- return std::make_pair( (uint8_t)Object->getBufferStart()[ELF::EI_CLASS]
- , (uint8_t)Object->getBufferStart()[ELF::EI_DATA]);
- }
-}
-
// Creates an in-memory object-file by default: createELFObjectFile(Buffer)
ObjectFile *ObjectFile::createELFObjectFile(MemoryBuffer *Object) {
std::pair<unsigned char, unsigned char> Ident = getElfArchType(Object);