ObjectLinkingLayer.h [plain text]
#ifndef LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
#define LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H
#include "JITSymbol.h"
#include "llvm/ADT/STLExtras.h"
#include "llvm/ExecutionEngine/ExecutionEngine.h"
#include "llvm/ExecutionEngine/SectionMemoryManager.h"
#include <list>
#include <memory>
namespace llvm {
namespace orc {
class ObjectLinkingLayerBase {
protected:
class LinkedObjectSet {
LinkedObjectSet(const LinkedObjectSet&) = delete;
void operator=(const LinkedObjectSet&) = delete;
public:
LinkedObjectSet() = default;
virtual ~LinkedObjectSet() {}
virtual void finalize() = 0;
virtual JITSymbol::GetAddressFtor
getSymbolMaterializer(std::string Name) = 0;
virtual void mapSectionAddress(const void *LocalAddress,
TargetAddress TargetAddr) const = 0;
JITSymbol getSymbol(StringRef Name, bool ExportedSymbolsOnly) {
auto SymEntry = SymbolTable.find(Name);
if (SymEntry == SymbolTable.end())
return nullptr;
if (!SymEntry->second.isExported() && ExportedSymbolsOnly)
return nullptr;
if (!Finalized)
return JITSymbol(getSymbolMaterializer(Name),
SymEntry->second.getFlags());
return JITSymbol(SymEntry->second.getAddress(),
SymEntry->second.getFlags());
}
protected:
StringMap<RuntimeDyld::SymbolInfo> SymbolTable;
bool Finalized = false;
};
typedef std::list<std::unique_ptr<LinkedObjectSet>> LinkedObjectSetListT;
public:
typedef LinkedObjectSetListT::iterator ObjSetHandleT;
};
class DoNothingOnNotifyLoaded {
public:
template <typename ObjSetT, typename LoadResult>
void operator()(ObjectLinkingLayerBase::ObjSetHandleT, const ObjSetT &,
const LoadResult &) {}
};
template <typename NotifyLoadedFtor = DoNothingOnNotifyLoaded>
class ObjectLinkingLayer : public ObjectLinkingLayerBase {
public:
typedef std::function<void(ObjSetHandleT)> NotifyFinalizedFtor;
private:
template <typename ObjSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT, typename FinalizerFtor>
class ConcreteLinkedObjectSet : public LinkedObjectSet {
public:
ConcreteLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver,
FinalizerFtor Finalizer,
bool ProcessAllSections)
: MemMgr(std::move(MemMgr)),
PFC(llvm::make_unique<PreFinalizeContents>(std::move(Objects),
std::move(Resolver),
std::move(Finalizer),
ProcessAllSections)) {
buildInitialSymbolTable(PFC->Objects);
}
void setHandle(ObjSetHandleT H) {
PFC->Handle = H;
}
void finalize() override {
assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
RuntimeDyld RTDyld(*MemMgr, *PFC->Resolver);
RTDyld.setProcessAllSections(PFC->ProcessAllSections);
PFC->RTDyld = &RTDyld;
PFC->Finalizer(PFC->Handle, RTDyld, std::move(PFC->Objects),
[&]() {
this->updateSymbolTable(RTDyld);
this->Finalized = true;
});
PFC = nullptr;
}
JITSymbol::GetAddressFtor getSymbolMaterializer(std::string Name) override {
return
[this, Name]() {
if (!this->Finalized)
this->finalize();
return this->getSymbol(Name, false).getAddress();
};
}
void mapSectionAddress(const void *LocalAddress,
TargetAddress TargetAddr) const override {
assert(PFC && "mapSectionAddress called on finalized LinkedObjectSet");
assert(PFC->RTDyld && "mapSectionAddress called on raw LinkedObjectSet");
PFC->RTDyld->mapSectionAddress(LocalAddress, TargetAddr);
}
private:
void buildInitialSymbolTable(const ObjSetT &Objects) {
for (const auto &Obj : Objects)
for (auto &Symbol : getObject(*Obj).symbols()) {
if (Symbol.getFlags() & object::SymbolRef::SF_Undefined)
continue;
ErrorOr<StringRef> SymbolName = Symbol.getName();
if (!SymbolName)
continue;
auto Flags = JITSymbol::flagsFromObjectSymbol(Symbol);
SymbolTable.insert(
std::make_pair(*SymbolName, RuntimeDyld::SymbolInfo(0, Flags)));
}
}
void updateSymbolTable(const RuntimeDyld &RTDyld) {
for (auto &SymEntry : SymbolTable)
SymEntry.second = RTDyld.getSymbol(SymEntry.first());
}
struct PreFinalizeContents {
PreFinalizeContents(ObjSetT Objects, SymbolResolverPtrT Resolver,
FinalizerFtor Finalizer, bool ProcessAllSections)
: Objects(std::move(Objects)), Resolver(std::move(Resolver)),
Finalizer(std::move(Finalizer)),
ProcessAllSections(ProcessAllSections) {}
ObjSetT Objects;
SymbolResolverPtrT Resolver;
FinalizerFtor Finalizer;
bool ProcessAllSections;
ObjSetHandleT Handle;
RuntimeDyld *RTDyld;
};
MemoryManagerPtrT MemMgr;
std::unique_ptr<PreFinalizeContents> PFC;
};
template <typename ObjSetT, typename MemoryManagerPtrT,
typename SymbolResolverPtrT, typename FinalizerFtor>
std::unique_ptr<
ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
SymbolResolverPtrT, FinalizerFtor>>
createLinkedObjectSet(ObjSetT Objects, MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver,
FinalizerFtor Finalizer,
bool ProcessAllSections) {
typedef ConcreteLinkedObjectSet<ObjSetT, MemoryManagerPtrT,
SymbolResolverPtrT, FinalizerFtor> LOS;
return llvm::make_unique<LOS>(std::move(Objects), std::move(MemMgr),
std::move(Resolver), std::move(Finalizer),
ProcessAllSections);
}
public:
typedef std::vector<std::unique_ptr<RuntimeDyld::LoadedObjectInfo>>
LoadedObjInfoList;
ObjectLinkingLayer(
NotifyLoadedFtor NotifyLoaded = NotifyLoadedFtor(),
NotifyFinalizedFtor NotifyFinalized = NotifyFinalizedFtor())
: NotifyLoaded(std::move(NotifyLoaded)),
NotifyFinalized(std::move(NotifyFinalized)),
ProcessAllSections(false) {}
void setProcessAllSections(bool ProcessAllSections) {
this->ProcessAllSections = ProcessAllSections;
}
template <typename ObjSetT,
typename MemoryManagerPtrT,
typename SymbolResolverPtrT>
ObjSetHandleT addObjectSet(ObjSetT Objects,
MemoryManagerPtrT MemMgr,
SymbolResolverPtrT Resolver) {
auto Finalizer = [&](ObjSetHandleT H, RuntimeDyld &RTDyld,
const ObjSetT &Objs,
std::function<void()> LOSHandleLoad) {
LoadedObjInfoList LoadedObjInfos;
for (auto &Obj : Objs)
LoadedObjInfos.push_back(RTDyld.loadObject(this->getObject(*Obj)));
LOSHandleLoad();
this->NotifyLoaded(H, Objs, LoadedObjInfos);
RTDyld.finalizeWithMemoryManagerLocking();
if (this->NotifyFinalized)
this->NotifyFinalized(H);
};
auto LOS =
createLinkedObjectSet(std::move(Objects), std::move(MemMgr),
std::move(Resolver), std::move(Finalizer),
ProcessAllSections);
auto *LOSPtr = LOS.get();
ObjSetHandleT Handle = LinkedObjSetList.insert(LinkedObjSetList.end(),
std::move(LOS));
LOSPtr->setHandle(Handle);
return Handle;
}
void removeObjectSet(ObjSetHandleT H) {
LinkedObjSetList.erase(H);
}
JITSymbol findSymbol(StringRef Name, bool ExportedSymbolsOnly) {
for (auto I = LinkedObjSetList.begin(), E = LinkedObjSetList.end(); I != E;
++I)
if (auto Symbol = findSymbolIn(I, Name, ExportedSymbolsOnly))
return Symbol;
return nullptr;
}
JITSymbol findSymbolIn(ObjSetHandleT H, StringRef Name,
bool ExportedSymbolsOnly) {
return (*H)->getSymbol(Name, ExportedSymbolsOnly);
}
void mapSectionAddress(ObjSetHandleT H, const void *LocalAddress,
TargetAddress TargetAddr) {
(*H)->mapSectionAddress(LocalAddress, TargetAddr);
}
void emitAndFinalize(ObjSetHandleT H) {
(*H)->finalize();
}
private:
static const object::ObjectFile& getObject(const object::ObjectFile &Obj) {
return Obj;
}
template <typename ObjT>
static const object::ObjectFile&
getObject(const object::OwningBinary<ObjT> &Obj) {
return *Obj.getBinary();
}
LinkedObjectSetListT LinkedObjSetList;
NotifyLoadedFtor NotifyLoaded;
NotifyFinalizedFtor NotifyFinalized;
bool ProcessAllSections;
};
} }
#endif // LLVM_EXECUTIONENGINE_ORC_OBJECTLINKINGLAYER_H