1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-19 02:52:53 +02:00

[ORC] Redesign the JITSymbolResolver interface to support bulk queries.

Bulk queries reduce IPC/RPC overhead for cross-process JITing and expose
opportunities for parallel compilation.

The two new query methods are lookupFlags, which finds the flags for each of a
set of symbols; and lookup, which finds the address and flags for each of a
set of symbols. (See doxygen comments for more details.)

The existing JITSymbolResolver class is renamed LegacyJITSymbolResolver, and
modified to extend the new JITSymbolResolver class using the following scheme:

- lookupFlags is implemented by calling findSymbolInLogicalDylib for each of the
symbols, then returning the result of calling getFlags() on each of these
symbols. (Importantly: lookupFlags does NOT call getAddress on the returned
symbols, so lookupFlags will never trigger materialization, and lookupFlags will
never call findSymbol, so only symbols that are part of the logical dylib will
return results.)

- lookup is implemented by calling findSymbolInLogicalDylib for each symbol and
falling back to findSymbol if findSymbolInLogicalDylib returns a null result.
Assuming a symbol is found its getAddress method is called to materialize it and
the result (if getAddress succeeds) is stored in the result map, or the error
(if getAddress fails) is returned immediately from lookup. If any symbol is not
found then lookup returns immediately with an error.

This change will break any out-of-tree derivatives of JITSymbolResolver. This
can be fixed by updating those classes to derive from LegacyJITSymbolResolver
instead.

llvm-svn: 322913
This commit is contained in:
Lang Hames 2018-01-19 01:12:40 +00:00
parent 1c2f80aef6
commit 6784638299
17 changed files with 319 additions and 201 deletions

View File

@ -137,17 +137,15 @@ protected:
virtual char *getMemoryForGV(const GlobalVariable *GV);
static ExecutionEngine *(*MCJITCtor)(
std::unique_ptr<Module> M,
std::string *ErrorStr,
std::shared_ptr<MCJITMemoryManager> MM,
std::shared_ptr<JITSymbolResolver> SR,
std::unique_ptr<TargetMachine> TM);
std::unique_ptr<Module> M, std::string *ErrorStr,
std::shared_ptr<MCJITMemoryManager> MM,
std::shared_ptr<LegacyJITSymbolResolver> SR,
std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*OrcMCJITReplacementCtor)(
std::string *ErrorStr,
std::shared_ptr<MCJITMemoryManager> MM,
std::shared_ptr<JITSymbolResolver> SR,
std::unique_ptr<TargetMachine> TM);
std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MM,
std::shared_ptr<LegacyJITSymbolResolver> SR,
std::unique_ptr<TargetMachine> TM);
static ExecutionEngine *(*InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr);
@ -532,7 +530,7 @@ private:
std::string *ErrorStr;
CodeGenOpt::Level OptLevel;
std::shared_ptr<MCJITMemoryManager> MemMgr;
std::shared_ptr<JITSymbolResolver> Resolver;
std::shared_ptr<LegacyJITSymbolResolver> Resolver;
TargetOptions Options;
Optional<Reloc::Model> RelocModel;
Optional<CodeModel::Model> CMModel;
@ -571,8 +569,7 @@ public:
EngineBuilder&
setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM);
EngineBuilder&
setSymbolResolver(std::unique_ptr<JITSymbolResolver> SR);
EngineBuilder &setSymbolResolver(std::unique_ptr<LegacyJITSymbolResolver> SR);
/// setErrorStr - Set the error string to write to on error. This option
/// defaults to NULL.

View File

@ -19,8 +19,11 @@
#include <cstddef>
#include <cstdint>
#include <functional>
#include <map>
#include <set>
#include <string>
#include "llvm/ADT/StringRef.h"
#include "llvm/Support/Error.h"
namespace llvm {
@ -269,11 +272,50 @@ private:
JITSymbolFlags Flags;
};
/// \brief Symbol resolution.
/// @brief Symbol resolution interface.
///
/// Allows symbol flags and addresses to be looked up by name.
/// Symbol queries are done in bulk (i.e. you request resolution of a set of
/// symbols, rather than a single one) to reduce IPC overhead in the case of
/// remote JITing, and expose opportunities for parallel compilation.
class JITSymbolResolver {
public:
using SymbolNameSet = std::set<StringRef>;
using LookupResult = std::map<StringRef, JITEvaluatedSymbol>;
using LookupFlagsResult = std::map<StringRef, JITSymbolFlags>;
virtual ~JITSymbolResolver() = default;
/// @brief Returns the fully resolved address and flags for each of the given
/// symbols.
///
/// This method will return an error if any of the given symbols can not be
/// resolved, or if the resolution process itself triggers an error.
virtual Expected<LookupResult> lookup(const SymbolNameSet &Symbols) = 0;
/// @brief Returns the symbol flags for each of the given symbols.
///
/// This method does NOT return an error if any of the given symbols is
/// missing. Instead, that symbol will be left out of the result map.
virtual Expected<LookupFlagsResult>
lookupFlags(const SymbolNameSet &Symbols) = 0;
private:
virtual void anchor();
};
/// \brief Legacy symbol resolution interface.
class LegacyJITSymbolResolver : public JITSymbolResolver {
public:
/// @brief Performs lookup by, for each symbol, first calling
/// findSymbolInLogicalDylib and if that fails calling
/// findSymbol.
Expected<LookupResult> lookup(const SymbolNameSet &Symbols) final;
/// @brief Performs flags lookup by calling findSymbolInLogicalDylib and
/// returning the flags value for that symbol.
Expected<LookupFlagsResult> lookupFlags(const SymbolNameSet &Symbols) final;
/// This method returns the address of the specified symbol if it exists
/// within the logical dynamic library represented by this JITSymbolResolver.
/// Unlike findSymbol, queries through this interface should return addresses

View File

@ -183,7 +183,7 @@ private:
return Error::success();
}
std::shared_ptr<JITSymbolResolver> ExternalSymbolResolver;
std::shared_ptr<LegacyJITSymbolResolver> ExternalSymbolResolver;
std::unique_ptr<IndirectStubsMgrT> StubsMgr;
StaticGlobalRenamer StaticRenamer;
SourceModulesList SourceModules;
@ -223,7 +223,7 @@ public:
/// @brief Add a module to the compile-on-demand layer.
Expected<ModuleHandleT>
addModule(std::shared_ptr<Module> M,
std::shared_ptr<JITSymbolResolver> Resolver) {
std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
LogicalDylibs.push_back(LogicalDylib());
auto &LD = LogicalDylibs.back();

View File

@ -23,7 +23,7 @@ namespace llvm {
namespace orc {
template <typename DylibLookupFtorT, typename ExternalLookupFtorT>
class LambdaResolver : public JITSymbolResolver {
class LambdaResolver : public LegacyJITSymbolResolver {
public:
LambdaResolver(DylibLookupFtorT DylibLookupFtor,
ExternalLookupFtorT ExternalLookupFtor)

View File

@ -22,7 +22,7 @@ namespace orc {
/// SymbolResolver impliementation that rejects all resolution requests.
/// Useful for clients that have no cross-object fixups.
class NullResolver : public JITSymbolResolver {
class NullResolver : public LegacyJITSymbolResolver {
public:
JITSymbol findSymbol(const std::string &Name) final;

View File

@ -328,7 +328,8 @@ public:
/// @return A handle that can be used to refer to the loaded object (for
/// symbol searching, finalization, freeing memory, etc.).
Expected<ObjHandleT>
addObject(ObjectPtr Object, std::shared_ptr<JITSymbolResolver> Resolver) {
addObject(ObjectPtr Object,
std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
StringRef ObjBuffer = Object->getBinary()->getData();
if (auto HandleOrErr =
this->Remote.template callB<AddObject>(ObjBuffer)) {
@ -386,7 +387,8 @@ private:
}
std::map<remote::ResourceIdMgr::ResourceId,
std::shared_ptr<JITSymbolResolver>> Resolvers;
std::shared_ptr<LegacyJITSymbolResolver>>
Resolvers;
};
/// RemoteObjectServerLayer acts as a server and handling RPC calls for the

View File

@ -56,7 +56,7 @@ public:
// FIXME: As the RuntimeDyld fills out, additional routines will be needed
// for the varying types of objects to be allocated.
class RTDyldMemoryManager : public MCJITMemoryManager,
public JITSymbolResolver {
public LegacyJITSymbolResolver {
public:
RTDyldMemoryManager() = default;
RTDyldMemoryManager(const RTDyldMemoryManager&) = delete;

View File

@ -49,14 +49,13 @@ STATISTIC(NumGlobals , "Number of global vars initialized");
ExecutionEngine *(*ExecutionEngine::MCJITCtor)(
std::unique_ptr<Module> M, std::string *ErrorStr,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) = nullptr;
ExecutionEngine *(*ExecutionEngine::OrcMCJITReplacementCtor)(
std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) = nullptr;
std::string *ErrorStr, std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) = nullptr;
ExecutionEngine *(*ExecutionEngine::InterpCtor)(std::unique_ptr<Module> M,
std::string *ErrorStr) =nullptr;
@ -502,9 +501,9 @@ EngineBuilder::setMemoryManager(std::unique_ptr<MCJITMemoryManager> MM) {
return *this;
}
EngineBuilder&
EngineBuilder::setSymbolResolver(std::unique_ptr<JITSymbolResolver> SR) {
Resolver = std::shared_ptr<JITSymbolResolver>(std::move(SR));
EngineBuilder &
EngineBuilder::setSymbolResolver(std::unique_ptr<LegacyJITSymbolResolver> SR) {
Resolver = std::shared_ptr<LegacyJITSymbolResolver>(std::move(SR));
return *this;
}

View File

@ -39,11 +39,10 @@ static struct RegisterJIT {
extern "C" void LLVMLinkInMCJIT() {
}
ExecutionEngine*
MCJIT::createJIT(std::unique_ptr<Module> M,
std::string *ErrorStr,
ExecutionEngine *
MCJIT::createJIT(std::unique_ptr<Module> M, std::string *ErrorStr,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) {
// Try to register the program as a source of symbols to resolve against.
//
@ -64,7 +63,7 @@ MCJIT::createJIT(std::unique_ptr<Module> M,
MCJIT::MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> TM,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver)
std::shared_ptr<LegacyJITSymbolResolver> Resolver)
: ExecutionEngine(TM->createDataLayout(), std::move(M)), TM(std::move(TM)),
Ctx(nullptr), MemMgr(std::move(MemMgr)),
Resolver(*this, std::move(Resolver)), Dyld(*this->MemMgr, this->Resolver),

View File

@ -26,11 +26,11 @@ class MCJIT;
// functions across modules that it owns. It aggregates the memory manager
// that is passed in to the MCJIT constructor and defers most functionality
// to that object.
class LinkingSymbolResolver : public JITSymbolResolver {
class LinkingSymbolResolver : public LegacyJITSymbolResolver {
public:
LinkingSymbolResolver(MCJIT &Parent,
std::shared_ptr<JITSymbolResolver> Resolver)
: ParentEngine(Parent), ClientResolver(std::move(Resolver)) {}
std::shared_ptr<LegacyJITSymbolResolver> Resolver)
: ParentEngine(Parent), ClientResolver(std::move(Resolver)) {}
JITSymbol findSymbol(const std::string &Name) override;
@ -41,7 +41,7 @@ public:
private:
MCJIT &ParentEngine;
std::shared_ptr<JITSymbolResolver> ClientResolver;
std::shared_ptr<LegacyJITSymbolResolver> ClientResolver;
};
// About Module states: added->loaded->finalized.
@ -67,7 +67,7 @@ private:
class MCJIT : public ExecutionEngine {
MCJIT(std::unique_ptr<Module> M, std::unique_ptr<TargetMachine> tm,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver);
std::shared_ptr<LegacyJITSymbolResolver> Resolver);
typedef llvm::SmallPtrSet<Module *, 4> ModulePtrSet;
@ -300,11 +300,10 @@ public:
MCJITCtor = createJIT;
}
static ExecutionEngine*
createJIT(std::unique_ptr<Module> M,
std::string *ErrorStr,
static ExecutionEngine *
createJIT(std::unique_ptr<Module> M, std::string *ErrorStr,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM);
// @}

View File

@ -196,7 +196,7 @@ public:
return mapError(IndirectStubsMgr->updatePointer(Name, Addr));
}
std::shared_ptr<JITSymbolResolver>
std::shared_ptr<LegacyJITSymbolResolver>
createResolver(LLVMOrcSymbolResolverFn ExternalResolver,
void *ExternalResolverCtx) {
return orc::createLambdaResolver(

View File

@ -138,7 +138,7 @@ class OrcMCJITReplacement : public ExecutionEngine {
std::shared_ptr<MCJITMemoryManager> ClientMM;
};
class LinkingResolver : public JITSymbolResolver {
class LinkingResolver : public LegacyJITSymbolResolver {
public:
LinkingResolver(OrcMCJITReplacement &M) : M(M) {}
@ -160,20 +160,19 @@ private:
static ExecutionEngine *
createOrcMCJITReplacement(std::string *ErrorMsg,
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> Resolver,
std::shared_ptr<LegacyJITSymbolResolver> Resolver,
std::unique_ptr<TargetMachine> TM) {
return new OrcMCJITReplacement(std::move(MemMgr), std::move(Resolver),
std::move(TM));
}
public:
OrcMCJITReplacement(
std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<JITSymbolResolver> ClientResolver,
std::unique_ptr<TargetMachine> TM)
OrcMCJITReplacement(std::shared_ptr<MCJITMemoryManager> MemMgr,
std::shared_ptr<LegacyJITSymbolResolver> ClientResolver,
std::unique_ptr<TargetMachine> TM)
: ExecutionEngine(TM->createDataLayout()), TM(std::move(TM)),
MemMgr(std::make_shared<MCJITReplacementMemMgr>(*this,
std::move(MemMgr))),
MemMgr(
std::make_shared<MCJITReplacementMemMgr>(*this, std::move(MemMgr))),
Resolver(std::make_shared<LinkingResolver>(*this)),
ClientResolver(std::move(ClientResolver)), NotifyObjectLoaded(*this),
NotifyFinalized(*this),
@ -378,7 +377,7 @@ private:
std::unique_ptr<TargetMachine> TM;
std::shared_ptr<MCJITReplacementMemMgr> MemMgr;
std::shared_ptr<LinkingResolver> Resolver;
std::shared_ptr<JITSymbolResolver> ClientResolver;
std::shared_ptr<LegacyJITSymbolResolver> ClientResolver;
Mangler Mang;
// IMPORTANT: ShouldDelete *must* come before LocalModules: The shared_ptr

View File

@ -47,3 +47,53 @@ ARMJITSymbolFlags llvm::ARMJITSymbolFlags::fromObjectSymbol(
Flags |= ARMJITSymbolFlags::Thumb;
return Flags;
}
/// @brief Performs lookup by, for each symbol, first calling
/// findSymbolInLogicalDylib and if that fails calling
/// findSymbol.
Expected<JITSymbolResolver::LookupResult>
LegacyJITSymbolResolver::lookup(const SymbolNameSet &Symbols) {
JITSymbolResolver::LookupResult Result;
for (auto &Symbol : Symbols) {
std::string SymName = Symbol.str();
if (auto Sym = findSymbolInLogicalDylib(SymName)) {
if (auto AddrOrErr = Sym.getAddress())
Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
else
return AddrOrErr.takeError();
} else if (auto Err = Sym.takeError())
return std::move(Err);
else {
// findSymbolInLogicalDylib failed. Lets try findSymbol.
if (auto Sym = findSymbol(SymName)) {
if (auto AddrOrErr = Sym.getAddress())
Result[Symbol] = JITEvaluatedSymbol(*AddrOrErr, Sym.getFlags());
else
return AddrOrErr.takeError();
} else if (auto Err = Sym.takeError())
return std::move(Err);
else
return make_error<StringError>("Symbol not found: " + Symbol,
inconvertibleErrorCode());
}
}
return std::move(Result);
}
/// @brief Performs flags lookup by calling findSymbolInLogicalDylib and
/// returning the flags value for that symbol.
Expected<JITSymbolResolver::LookupFlagsResult>
LegacyJITSymbolResolver::lookupFlags(const SymbolNameSet &Symbols) {
JITSymbolResolver::LookupFlagsResult Result;
for (auto &Symbol : Symbols) {
std::string SymName = Symbol.str();
if (auto Sym = findSymbolInLogicalDylib(SymName))
Result[Symbol] = Sym.getFlags();
else if (auto Err = Sym.takeError())
return std::move(Err);
}
return std::move(Result);
}

View File

@ -202,7 +202,33 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
ObjSectionToIDMap LocalSections;
// Common symbols requiring allocation, with their sizes and alignments
CommonSymbolList CommonSymbols;
CommonSymbolList CommonSymbolsToAllocate;
uint64_t CommonSize = 0;
uint32_t CommonAlign = 0;
// First, collect all weak and common symbols. We need to know if stronger
// definitions occur elsewhere.
JITSymbolResolver::LookupFlagsResult SymbolFlags;
{
JITSymbolResolver::SymbolNameSet Symbols;
for (auto &Sym : Obj.symbols()) {
uint32_t Flags = Sym.getFlags();
if ((Flags & SymbolRef::SF_Common) || (Flags & SymbolRef::SF_Weak)) {
// Get symbol name.
StringRef Name;
if (auto NameOrErr = Sym.getName())
Symbols.insert(*NameOrErr);
else
return NameOrErr.takeError();
}
}
if (auto FlagsResultOrErr = Resolver.lookupFlags(Symbols))
SymbolFlags = std::move(*FlagsResultOrErr);
else
return FlagsResultOrErr.takeError();
}
// Parse symbols
DEBUG(dbgs() << "Parse symbols:\n");
@ -214,102 +240,108 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
if (Flags & SymbolRef::SF_Undefined)
continue;
if (Flags & SymbolRef::SF_Common)
CommonSymbols.push_back(*I);
else {
// Get the symbol type.
object::SymbolRef::Type SymType;
if (auto SymTypeOrErr = I->getType())
SymType = *SymTypeOrErr;
else
return SymTypeOrErr.takeError();
// Get the symbol type.
object::SymbolRef::Type SymType;
if (auto SymTypeOrErr = I->getType())
SymType = *SymTypeOrErr;
// Get symbol name.
StringRef Name;
if (auto NameOrErr = I->getName())
Name = *NameOrErr;
else
return NameOrErr.takeError();
// Compute JIT symbol flags.
JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I);
// If this is a weak definition, check to see if there's a strong one.
// If there is, skip this symbol (we won't be providing it: the strong
// definition will). If there's no strong definition, make this definition
// strong.
if (JITSymFlags.isWeak() || JITSymFlags.isCommon()) {
// First check whether there's already a definition in this instance.
// FIXME: Override existing weak definitions with strong ones.
if (GlobalSymbolTable.count(Name))
continue;
// Then check whether we found flags for an existing symbol during the
// flags lookup earlier.
auto FlagsI = SymbolFlags.find(Name);
if (FlagsI == SymbolFlags.end() ||
(JITSymFlags.isWeak() && !FlagsI->second.isStrong()) ||
(JITSymFlags.isCommon() && FlagsI->second.isCommon())) {
if (JITSymFlags.isWeak())
JITSymFlags &= ~JITSymbolFlags::Weak;
if (JITSymFlags.isCommon()) {
JITSymFlags &= ~JITSymbolFlags::Common;
uint32_t Align = I->getAlignment();
uint64_t Size = I->getCommonSize();
if (!CommonAlign)
CommonAlign = Align;
CommonSize += alignTo(CommonSize, Align) + Size;
CommonSymbolsToAllocate.push_back(*I);
}
} else
continue;
}
if (Flags & SymbolRef::SF_Absolute &&
SymType != object::SymbolRef::ST_File) {
uint64_t Addr = 0;
if (auto AddrOrErr = I->getAddress())
Addr = *AddrOrErr;
else
return SymTypeOrErr.takeError();
return AddrOrErr.takeError();
// Get symbol name.
StringRef Name;
if (auto NameOrErr = I->getName())
Name = *NameOrErr;
unsigned SectionID = AbsoluteSymbolSection;
DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name
<< " SID: " << SectionID
<< " Offset: " << format("%p", (uintptr_t)Addr)
<< " flags: " << Flags << "\n");
GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, JITSymFlags);
} else if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data ||
SymType == object::SymbolRef::ST_Unknown ||
SymType == object::SymbolRef::ST_Other) {
section_iterator SI = Obj.section_end();
if (auto SIOrErr = I->getSection())
SI = *SIOrErr;
else
return NameOrErr.takeError();
return SIOrErr.takeError();
// Compute JIT symbol flags.
JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I);
if (SI == Obj.section_end())
continue;
// If this is a weak definition, check to see if there's a strong one.
// If there is, skip this symbol (we won't be providing it: the strong
// definition will). If there's no strong definition, make this definition
// strong.
if (JITSymFlags.isWeak()) {
// First check whether there's already a definition in this instance.
// FIXME: Override existing weak definitions with strong ones.
if (GlobalSymbolTable.count(Name))
continue;
// Then check the symbol resolver to see if there's a definition
// elsewhere in this logical dylib.
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) {
if (Sym.getFlags().isStrong())
continue;
} else if (auto Err = Sym.takeError())
return std::move(Err);
// else
JITSymFlags &= ~JITSymbolFlags::Weak;
}
// Get symbol offset.
uint64_t SectOffset;
if (auto Err = getOffset(*I, *SI, SectOffset))
return std::move(Err);
if (Flags & SymbolRef::SF_Absolute &&
SymType != object::SymbolRef::ST_File) {
uint64_t Addr = 0;
if (auto AddrOrErr = I->getAddress())
Addr = *AddrOrErr;
else
return AddrOrErr.takeError();
bool IsCode = SI->isText();
unsigned SectionID;
if (auto SectionIDOrErr =
findOrEmitSection(Obj, *SI, IsCode, LocalSections))
SectionID = *SectionIDOrErr;
else
return SectionIDOrErr.takeError();
unsigned SectionID = AbsoluteSymbolSection;
DEBUG(dbgs() << "\tType: " << SymType << " (absolute) Name: " << Name
<< " SID: " << SectionID << " Offset: "
<< format("%p", (uintptr_t)Addr)
<< " flags: " << Flags << "\n");
GlobalSymbolTable[Name] =
SymbolTableEntry(SectionID, Addr, JITSymFlags);
} else if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data ||
SymType == object::SymbolRef::ST_Unknown ||
SymType == object::SymbolRef::ST_Other) {
section_iterator SI = Obj.section_end();
if (auto SIOrErr = I->getSection())
SI = *SIOrErr;
else
return SIOrErr.takeError();
if (SI == Obj.section_end())
continue;
// Get symbol offset.
uint64_t SectOffset;
if (auto Err = getOffset(*I, *SI, SectOffset))
return std::move(Err);
bool IsCode = SI->isText();
unsigned SectionID;
if (auto SectionIDOrErr = findOrEmitSection(Obj, *SI, IsCode,
LocalSections))
SectionID = *SectionIDOrErr;
else
return SectionIDOrErr.takeError();
DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name
<< " SID: " << SectionID << " Offset: "
<< format("%p", (uintptr_t)SectOffset)
<< " flags: " << Flags << "\n");
GlobalSymbolTable[Name] =
DEBUG(dbgs() << "\tType: " << SymType << " Name: " << Name
<< " SID: " << SectionID
<< " Offset: " << format("%p", (uintptr_t)SectOffset)
<< " flags: " << Flags << "\n");
GlobalSymbolTable[Name] =
SymbolTableEntry(SectionID, SectOffset, JITSymFlags);
}
}
}
// Allocate common symbols
if (auto Err = emitCommonSymbols(Obj, CommonSymbols))
if (auto Err = emitCommonSymbols(Obj, CommonSymbolsToAllocate, CommonSize,
CommonAlign))
return std::move(Err);
// Parse and process relocations
@ -621,45 +653,12 @@ JITSymbolFlags RuntimeDyldImpl::getJITSymbolFlags(const BasicSymbolRef &SR) {
}
Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
CommonSymbolList &CommonSymbols) {
if (CommonSymbols.empty())
CommonSymbolList &SymbolsToAllocate,
uint64_t CommonSize,
uint32_t CommonAlign) {
if (SymbolsToAllocate.empty())
return Error::success();
uint64_t CommonSize = 0;
uint32_t CommonAlign = CommonSymbols.begin()->getAlignment();
CommonSymbolList SymbolsToAllocate;
DEBUG(dbgs() << "Processing common symbols...\n");
for (const auto &Sym : CommonSymbols) {
StringRef Name;
if (auto NameOrErr = Sym.getName())
Name = *NameOrErr;
else
return NameOrErr.takeError();
// Skip common symbols already elsewhere.
if (GlobalSymbolTable.count(Name)) {
DEBUG(dbgs() << "\tSkipping already emitted common symbol '" << Name
<< "'\n");
continue;
}
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name)) {
if (!Sym.getFlags().isCommon()) {
DEBUG(dbgs() << "\tSkipping common symbol '" << Name
<< "' in favor of stronger definition.\n");
continue;
}
}
uint32_t Align = Sym.getAlignment();
uint64_t Size = Sym.getCommonSize();
CommonSize = alignTo(CommonSize, Align) + Size;
SymbolsToAllocate.push_back(Sym);
}
// Allocate memory for the section
unsigned SectionID = Sections.size();
uint8_t *Addr = MemMgr.allocateDataSection(CommonSize, CommonAlign, SectionID,
@ -997,7 +996,40 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
}
Error RuntimeDyldImpl::resolveExternalSymbols() {
JITSymbolResolver::LookupResult ExternalSymbolMap;
// Resolution can trigger emission of more symbols, so iterate until
// we've resolved *everything*.
{
JITSymbolResolver::SymbolNameSet ResolvedSymbols;
while (true) {
JITSymbolResolver::SymbolNameSet NewSymbols;
for (auto &RelocKV : ExternalSymbolRelocations) {
StringRef Name = RelocKV.first();
if (!Name.empty() && !GlobalSymbolTable.count(Name) &&
!ResolvedSymbols.count(Name))
NewSymbols.insert(Name);
}
if (NewSymbols.empty())
break;
auto NewResolverResults = Resolver.lookup(NewSymbols);
if (!NewResolverResults)
return NewResolverResults.takeError();
for (auto &RRKV : *NewResolverResults) {
assert(!ResolvedSymbols.count(RRKV.first) && "Redundant resolution?");
ExternalSymbolMap.insert(RRKV);
ResolvedSymbols.insert(RRKV.first);
}
}
}
while (!ExternalSymbolRelocations.empty()) {
StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
StringRef Name = i->first();
@ -1012,29 +1044,10 @@ Error RuntimeDyldImpl::resolveExternalSymbols() {
JITSymbolFlags Flags;
RTDyldSymbolTable::const_iterator Loc = GlobalSymbolTable.find(Name);
if (Loc == GlobalSymbolTable.end()) {
// This is an external symbol, try to get its address from the symbol
// resolver.
// First search for the symbol in this logical dylib.
if (auto Sym = Resolver.findSymbolInLogicalDylib(Name.data())) {
if (auto AddrOrErr = Sym.getAddress()) {
Addr = *AddrOrErr;
Flags = Sym.getFlags();
} else
return AddrOrErr.takeError();
} else if (auto Err = Sym.takeError())
return Err;
// If that fails, try searching for an external symbol.
if (!Addr) {
if (auto Sym = Resolver.findSymbol(Name.data())) {
if (auto AddrOrErr = Sym.getAddress()) {
Addr = *AddrOrErr;
Flags = Sym.getFlags();
} else
return AddrOrErr.takeError();
} else if (auto Err = Sym.takeError())
return Err;
}
auto RRI = ExternalSymbolMap.find(Name);
assert(RRI != ExternalSymbolMap.end() && "No result for symbol");
Addr = RRI->second.getAddress();
Flags = RRI->second.getFlags();
// The call to getSymbolAddress may have caused additional modules to
// be loaded, which may have added new entries to the
// ExternalSymbolRelocations map. Consquently, we need to update our
@ -1095,6 +1108,7 @@ uint64_t RuntimeDyld::LoadedObjectInfo::getSectionLoadAddress(
void RuntimeDyld::MemoryManager::anchor() {}
void JITSymbolResolver::anchor() {}
void LegacyJITSymbolResolver::anchor() {}
RuntimeDyld::RuntimeDyld(RuntimeDyld::MemoryManager &MemMgr,
JITSymbolResolver &Resolver)

View File

@ -731,7 +731,14 @@ bool RuntimeDyldCheckerImpl::checkAllRulesInBuffer(StringRef RulePrefix,
bool RuntimeDyldCheckerImpl::isSymbolValid(StringRef Symbol) const {
if (getRTDyld().getSymbol(Symbol))
return true;
return !!getRTDyld().Resolver.findSymbol(Symbol);
JITSymbolResolver::SymbolNameSet Symbols({Symbol});
auto Result = getRTDyld().Resolver.lookup(Symbols);
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
return false;
}
assert(Result->count(Symbol) && "Missing symbol result");
return true;
}
uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
@ -742,7 +749,16 @@ uint64_t RuntimeDyldCheckerImpl::getSymbolLocalAddr(StringRef Symbol) const {
uint64_t RuntimeDyldCheckerImpl::getSymbolRemoteAddr(StringRef Symbol) const {
if (auto InternalSymbol = getRTDyld().getSymbol(Symbol))
return InternalSymbol.getAddress();
return cantFail(getRTDyld().Resolver.findSymbol(Symbol).getAddress());
JITSymbolResolver::SymbolNameSet Symbols({Symbol});
auto Result = getRTDyld().Resolver.lookup(Symbols);
if (!Result) {
logAllUnhandledErrors(Result.takeError(), errs(), "RTDyldChecker: ");
return 0;
}
auto I = Result->find(Symbol);
assert(I != Result->end() && "Missing symbol result");
return I->second.getAddress();
}
uint64_t RuntimeDyldCheckerImpl::readMemoryAtAddr(uint64_t SrcAddr,

View File

@ -385,7 +385,8 @@ protected:
/// new section for them and update the symbol mappings in the object and
/// symbol table.
Error emitCommonSymbols(const ObjectFile &Obj,
CommonSymbolList &CommonSymbols);
CommonSymbolList &CommonSymbols, uint64_t CommonSize,
uint32_t CommonAlign);
/// \brief Emits section data from the object file to the MemoryManager.
/// \param IsCode if it's true then allocateCodeSection() will be

View File

@ -84,7 +84,7 @@ public:
this->MemMgr = std::move(MemMgr);
}
void setResolver(std::shared_ptr<JITSymbolResolver> Resolver) {
void setResolver(std::shared_ptr<LegacyJITSymbolResolver> Resolver) {
this->Resolver = std::move(Resolver);
}
@ -145,7 +145,7 @@ public:
private:
std::unique_ptr<RuntimeDyld::MemoryManager> MemMgr;
std::shared_ptr<JITSymbolResolver> Resolver;
std::shared_ptr<LegacyJITSymbolResolver> Resolver;
};
}