summaryrefslogtreecommitdiff
path: root/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
committerDimitry Andric <dim@FreeBSD.org>2019-01-19 10:01:25 +0000
commitd8e91e46262bc44006913e6796843909f1ac7bcd (patch)
tree7d0c143d9b38190e0fa0180805389da22cd834c5 /lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
parentb7eb8e35e481a74962664b63dfb09483b200209a (diff)
Notes
Diffstat (limited to 'lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp')
-rw-r--r--lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp251
1 files changed, 181 insertions, 70 deletions
diff --git a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 1189be599edd..53cb782c55c4 100644
--- a/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -19,10 +19,13 @@
#include "RuntimeDyldMachO.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
+#include "llvm/Support/MSVCErrorWorkarounds.h"
#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include "llvm/Support/MutexGuard.h"
+#include <future>
+
using namespace llvm;
using namespace llvm::object;
@@ -131,6 +134,14 @@ void RuntimeDyldImpl::resolveRelocations() {
ErrorStr = toString(std::move(Err));
}
+ resolveLocalRelocations();
+
+ // Print out sections after relocation.
+ LLVM_DEBUG(for (int i = 0, e = Sections.size(); i != e; ++i)
+ dumpSectionMemory(Sections[i], "after relocations"););
+}
+
+void RuntimeDyldImpl::resolveLocalRelocations() {
// Iterate over all outstanding relocations
for (auto it = Relocations.begin(), e = Relocations.end(); it != e; ++it) {
// The Section here (Sections[i]) refers to the section in which the
@@ -143,10 +154,6 @@ void RuntimeDyldImpl::resolveRelocations() {
resolveRelocationList(it->second, Addr);
}
Relocations.clear();
-
- // Print out sections after relocation.
- LLVM_DEBUG(for (int i = 0, e = Sections.size(); i != e; ++i)
- dumpSectionMemory(Sections[i], "after relocations"););
}
void RuntimeDyldImpl::mapSectionAddress(const void *LocalAddress,
@@ -204,7 +211,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
// First, collect all weak and common symbols. We need to know if stronger
// definitions occur elsewhere.
- JITSymbolResolver::LookupFlagsResult SymbolFlags;
+ JITSymbolResolver::LookupSet ResponsibilitySet;
{
JITSymbolResolver::LookupSet Symbols;
for (auto &Sym : Obj.symbols()) {
@@ -218,10 +225,10 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
}
}
- if (auto FlagsResultOrErr = Resolver.lookupFlags(Symbols))
- SymbolFlags = std::move(*FlagsResultOrErr);
+ if (auto ResultOrErr = Resolver.getResponsibilitySet(Symbols))
+ ResponsibilitySet = std::move(*ResultOrErr);
else
- return FlagsResultOrErr.takeError();
+ return ResultOrErr.takeError();
}
// Parse symbols
@@ -249,37 +256,36 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
return NameOrErr.takeError();
// Compute JIT symbol flags.
- JITSymbolFlags JITSymFlags = getJITSymbolFlags(*I);
+ auto JITSymFlags = getJITSymbolFlags(*I);
+ if (!JITSymFlags)
+ return JITSymFlags.takeError();
// 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()) {
+ 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
+ // If we're not responsible for this symbol, skip it.
+ if (!ResponsibilitySet.count(Name))
continue;
+
+ // Otherwise update the flags on the symbol to make this definition
+ // strong.
+ 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);
+ }
}
if (Flags & SymbolRef::SF_Absolute &&
@@ -296,7 +302,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
<< " SID: " << SectionID
<< " Offset: " << format("%p", (uintptr_t)Addr)
<< " flags: " << Flags << "\n");
- GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, JITSymFlags);
+ GlobalSymbolTable[Name] = SymbolTableEntry(SectionID, Addr, *JITSymFlags);
} else if (SymType == object::SymbolRef::ST_Function ||
SymType == object::SymbolRef::ST_Data ||
SymType == object::SymbolRef::ST_Unknown ||
@@ -329,7 +335,7 @@ RuntimeDyldImpl::loadObjectImpl(const object::ObjectFile &Obj) {
<< " Offset: " << format("%p", (uintptr_t)SectOffset)
<< " flags: " << Flags << "\n");
GlobalSymbolTable[Name] =
- SymbolTableEntry(SectionID, SectOffset, JITSymFlags);
+ SymbolTableEntry(SectionID, SectOffset, *JITSymFlags);
}
}
@@ -642,7 +648,8 @@ void RuntimeDyldImpl::writeBytesUnaligned(uint64_t Value, uint8_t *Dst,
}
}
-JITSymbolFlags RuntimeDyldImpl::getJITSymbolFlags(const BasicSymbolRef &SR) {
+Expected<JITSymbolFlags>
+RuntimeDyldImpl::getJITSymbolFlags(const SymbolRef &SR) {
return JITSymbolFlags::fromObjectSymbol(SR);
}
@@ -683,11 +690,15 @@ Error RuntimeDyldImpl::emitCommonSymbols(const ObjectFile &Obj,
Addr += AlignOffset;
Offset += AlignOffset;
}
- JITSymbolFlags JITSymFlags = getJITSymbolFlags(Sym);
+ auto JITSymFlags = getJITSymbolFlags(Sym);
+
+ if (!JITSymFlags)
+ return JITSymFlags.takeError();
+
LLVM_DEBUG(dbgs() << "Allocating common symbol " << Name << " address "
<< format("%p", Addr) << "\n");
GlobalSymbolTable[Name] =
- SymbolTableEntry(SectionID, Offset, JITSymFlags);
+ SymbolTableEntry(SectionID, Offset, std::move(*JITSymFlags));
Offset += Size;
Addr += Size;
}
@@ -992,42 +1003,8 @@ void RuntimeDyldImpl::resolveRelocationList(const RelocationList &Relocs,
}
}
-Error RuntimeDyldImpl::resolveExternalSymbols() {
- StringMap<JITEvaluatedSymbol> ExternalSymbolMap;
-
- // Resolution can trigger emission of more symbols, so iterate until
- // we've resolved *everything*.
- {
- JITSymbolResolver::LookupSet ResolvedSymbols;
-
- while (true) {
- JITSymbolResolver::LookupSet 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();
-
- assert(NewResolverResults->size() == NewSymbols.size() &&
- "Should have errored on unresolved symbols");
-
- for (auto &RRKV : *NewResolverResults) {
- assert(!ResolvedSymbols.count(RRKV.first) && "Redundant resolution?");
- ExternalSymbolMap.insert(RRKV);
- ResolvedSymbols.insert(RRKV.first);
- }
- }
- }
-
+void RuntimeDyldImpl::applyExternalSymbolRelocations(
+ const StringMap<JITEvaluatedSymbol> ExternalSymbolMap) {
while (!ExternalSymbolRelocations.empty()) {
StringMap<RelocationList>::iterator i = ExternalSymbolRelocations.begin();
@@ -1089,10 +1066,114 @@ Error RuntimeDyldImpl::resolveExternalSymbols() {
ExternalSymbolRelocations.erase(i);
}
+}
+
+Error RuntimeDyldImpl::resolveExternalSymbols() {
+ StringMap<JITEvaluatedSymbol> ExternalSymbolMap;
+
+ // Resolution can trigger emission of more symbols, so iterate until
+ // we've resolved *everything*.
+ {
+ JITSymbolResolver::LookupSet ResolvedSymbols;
+
+ while (true) {
+ JITSymbolResolver::LookupSet 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;
+
+#ifdef _MSC_VER
+ using ExpectedLookupResult =
+ MSVCPExpected<JITSymbolResolver::LookupResult>;
+#else
+ using ExpectedLookupResult = Expected<JITSymbolResolver::LookupResult>;
+#endif
+
+ auto NewSymbolsP = std::make_shared<std::promise<ExpectedLookupResult>>();
+ auto NewSymbolsF = NewSymbolsP->get_future();
+ Resolver.lookup(NewSymbols,
+ [=](Expected<JITSymbolResolver::LookupResult> Result) {
+ NewSymbolsP->set_value(std::move(Result));
+ });
+
+ auto NewResolverResults = NewSymbolsF.get();
+
+ if (!NewResolverResults)
+ return NewResolverResults.takeError();
+
+ assert(NewResolverResults->size() == NewSymbols.size() &&
+ "Should have errored on unresolved symbols");
+
+ for (auto &RRKV : *NewResolverResults) {
+ assert(!ResolvedSymbols.count(RRKV.first) && "Redundant resolution?");
+ ExternalSymbolMap.insert(RRKV);
+ ResolvedSymbols.insert(RRKV.first);
+ }
+ }
+ }
+
+ applyExternalSymbolRelocations(ExternalSymbolMap);
return Error::success();
}
+void RuntimeDyldImpl::finalizeAsync(
+ std::unique_ptr<RuntimeDyldImpl> This, std::function<void(Error)> OnEmitted,
+ std::unique_ptr<MemoryBuffer> UnderlyingBuffer) {
+
+ // FIXME: Move-capture OnRelocsApplied and UnderlyingBuffer once we have
+ // c++14.
+ auto SharedUnderlyingBuffer =
+ std::shared_ptr<MemoryBuffer>(std::move(UnderlyingBuffer));
+ auto SharedThis = std::shared_ptr<RuntimeDyldImpl>(std::move(This));
+ auto PostResolveContinuation =
+ [SharedThis, OnEmitted, SharedUnderlyingBuffer](
+ Expected<JITSymbolResolver::LookupResult> Result) {
+ if (!Result) {
+ OnEmitted(Result.takeError());
+ return;
+ }
+
+ /// Copy the result into a StringMap, where the keys are held by value.
+ StringMap<JITEvaluatedSymbol> Resolved;
+ for (auto &KV : *Result)
+ Resolved[KV.first] = KV.second;
+
+ SharedThis->applyExternalSymbolRelocations(Resolved);
+ SharedThis->resolveLocalRelocations();
+ SharedThis->registerEHFrames();
+ std::string ErrMsg;
+ if (SharedThis->MemMgr.finalizeMemory(&ErrMsg))
+ OnEmitted(make_error<StringError>(std::move(ErrMsg),
+ inconvertibleErrorCode()));
+ else
+ OnEmitted(Error::success());
+ };
+
+ JITSymbolResolver::LookupSet Symbols;
+
+ for (auto &RelocKV : SharedThis->ExternalSymbolRelocations) {
+ StringRef Name = RelocKV.first();
+ assert(!Name.empty() && "Symbol has no name?");
+ assert(!SharedThis->GlobalSymbolTable.count(Name) &&
+ "Name already processed. RuntimeDyld instances can not be re-used "
+ "when finalizing with finalizeAsync.");
+ Symbols.insert(Name);
+ }
+
+ if (!Symbols.empty()) {
+ SharedThis->Resolver.lookup(Symbols, PostResolveContinuation);
+ } else
+ PostResolveContinuation(std::map<StringRef, JITEvaluatedSymbol>());
+}
+
//===----------------------------------------------------------------------===//
// RuntimeDyld class implementation
@@ -1240,5 +1321,35 @@ void RuntimeDyld::deregisterEHFrames() {
if (Dyld)
Dyld->deregisterEHFrames();
}
+// FIXME: Kill this with fire once we have a new JIT linker: this is only here
+// so that we can re-use RuntimeDyld's implementation without twisting the
+// interface any further for ORC's purposes.
+void jitLinkForORC(object::ObjectFile &Obj,
+ std::unique_ptr<MemoryBuffer> UnderlyingBuffer,
+ RuntimeDyld::MemoryManager &MemMgr,
+ JITSymbolResolver &Resolver, bool ProcessAllSections,
+ std::function<Error(
+ std::unique_ptr<RuntimeDyld::LoadedObjectInfo> LoadedObj,
+ std::map<StringRef, JITEvaluatedSymbol>)>
+ OnLoaded,
+ std::function<void(Error)> OnEmitted) {
+
+ RuntimeDyld RTDyld(MemMgr, Resolver);
+ RTDyld.setProcessAllSections(ProcessAllSections);
+
+ auto Info = RTDyld.loadObject(Obj);
+
+ if (RTDyld.hasError()) {
+ OnEmitted(make_error<StringError>(RTDyld.getErrorString(),
+ inconvertibleErrorCode()));
+ return;
+ }
+
+ if (auto Err = OnLoaded(std::move(Info), RTDyld.getSymbolTable()))
+ OnEmitted(std::move(Err));
+
+ RuntimeDyldImpl::finalizeAsync(std::move(RTDyld.Dyld), std::move(OnEmitted),
+ std::move(UnderlyingBuffer));
+}
} // end namespace llvm