aboutsummaryrefslogtreecommitdiff
path: root/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
Diffstat (limited to 'llvm/lib/ExecutionEngine')
-rw-r--r--llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp30
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFF.cpp137
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp527
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h199
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp216
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp5
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp161
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp30
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/JITLink.cpp11
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp2
-rw-r--r--llvm/lib/ExecutionEngine/JITLink/aarch64.cpp8
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp6
-rw-r--r--llvm/lib/ExecutionEngine/Orc/LLJIT.cpp5
-rw-r--r--llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp52
-rw-r--r--llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp4
-rw-r--r--llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp10
-rw-r--r--llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp8
-rw-r--r--llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp10
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp6
-rw-r--r--llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp2
20 files changed, 1374 insertions, 55 deletions
diff --git a/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp b/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
index 29a623ebe449..f1eeee3b3599 100644
--- a/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
+++ b/llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
@@ -12,7 +12,6 @@
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/Compiler.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include <mutex>
@@ -91,11 +90,18 @@ typedef llvm::DenseMap<JITEventListener::ObjectKey, RegisteredObjectInfo>
/// object files that are in executable memory managed by the client of this
/// class.
class GDBJITRegistrationListener : public JITEventListener {
+ /// Lock used to serialize all jit registration events, since they
+ /// modify global variables.
+ ///
+ /// Only a single instance of GDBJITRegistrationListener is ever created,
+ /// and so the lock can be a member variable of that instance. This ensures
+ /// destructors are run in the correct order.
+ sys::Mutex JITDebugLock;
+
/// A map of in-memory object files that have been registered with the
/// JIT interface.
RegisteredObjectBufferMap ObjectBufferMap;
-public:
/// Instantiates the JIT service.
GDBJITRegistrationListener() = default;
@@ -103,6 +109,12 @@ public:
/// internal resources.
~GDBJITRegistrationListener() override;
+public:
+ static GDBJITRegistrationListener &instance() {
+ static GDBJITRegistrationListener Instance;
+ return Instance;
+ }
+
/// Creates an entry in the JIT registry for the buffer @p Object,
/// which must contain an object file in executable memory with any
/// debug information for the debugger.
@@ -121,10 +133,6 @@ private:
void deregisterObjectInternal(RegisteredObjectBufferMap::iterator I);
};
-/// Lock used to serialize all jit registration events, since they
-/// modify global variables.
-ManagedStatic<sys::Mutex> JITDebugLock;
-
/// Do the registration.
void NotifyDebugger(jit_code_entry* JITCodeEntry) {
__jit_debug_descriptor.action_flag = JIT_REGISTER_FN;
@@ -143,7 +151,7 @@ void NotifyDebugger(jit_code_entry* JITCodeEntry) {
GDBJITRegistrationListener::~GDBJITRegistrationListener() {
// Free all registered object files.
- std::lock_guard<llvm::sys::Mutex> locked(*JITDebugLock);
+ std::lock_guard<llvm::sys::Mutex> locked(JITDebugLock);
for (RegisteredObjectBufferMap::iterator I = ObjectBufferMap.begin(),
E = ObjectBufferMap.end();
I != E; ++I) {
@@ -167,7 +175,7 @@ void GDBJITRegistrationListener::notifyObjectLoaded(
const char *Buffer = DebugObj.getBinary()->getMemoryBufferRef().getBufferStart();
size_t Size = DebugObj.getBinary()->getMemoryBufferRef().getBufferSize();
- std::lock_guard<llvm::sys::Mutex> locked(*JITDebugLock);
+ std::lock_guard<llvm::sys::Mutex> locked(JITDebugLock);
assert(ObjectBufferMap.find(K) == ObjectBufferMap.end() &&
"Second attempt to perform debug registration.");
jit_code_entry* JITCodeEntry = new jit_code_entry();
@@ -186,7 +194,7 @@ void GDBJITRegistrationListener::notifyObjectLoaded(
}
void GDBJITRegistrationListener::notifyFreeingObject(ObjectKey K) {
- std::lock_guard<llvm::sys::Mutex> locked(*JITDebugLock);
+ std::lock_guard<llvm::sys::Mutex> locked(JITDebugLock);
RegisteredObjectBufferMap::iterator I = ObjectBufferMap.find(K);
if (I != ObjectBufferMap.end()) {
@@ -228,14 +236,12 @@ void GDBJITRegistrationListener::deregisterObjectInternal(
JITCodeEntry = nullptr;
}
-llvm::ManagedStatic<GDBJITRegistrationListener> GDBRegListener;
-
} // end namespace
namespace llvm {
JITEventListener* JITEventListener::createGDBRegistrationListener() {
- return &*GDBRegListener;
+ return &GDBJITRegistrationListener::instance();
}
} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
new file mode 100644
index 000000000000..fddc9b813fb2
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFF.cpp
@@ -0,0 +1,137 @@
+//===-------------- COFF.cpp - JIT linker function for COFF -------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// COFF jit-link function.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/COFF.h"
+
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Endian.h"
+#include "llvm/Support/Format.h"
+#include "llvm/Support/MemoryBuffer.h"
+#include <cstring>
+
+using namespace llvm;
+
+#define DEBUG_TYPE "jitlink"
+
+namespace llvm {
+namespace jitlink {
+
+static StringRef getMachineName(uint16_t Machine) {
+ switch (Machine) {
+ case COFF::IMAGE_FILE_MACHINE_I386:
+ return "i386";
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ return "x86_64";
+ case COFF::IMAGE_FILE_MACHINE_ARMNT:
+ return "ARM";
+ case COFF::IMAGE_FILE_MACHINE_ARM64:
+ return "ARM64";
+ default:
+ return "unknown";
+ }
+}
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromCOFFObject(MemoryBufferRef ObjectBuffer) {
+ StringRef Data = ObjectBuffer.getBuffer();
+
+ // Check magic
+ auto Magic = identify_magic(ObjectBuffer.getBuffer());
+ if (Magic != file_magic::coff_object)
+ return make_error<JITLinkError>("Invalid COFF buffer");
+
+ if (Data.size() < sizeof(object::coff_file_header))
+ return make_error<JITLinkError>("Truncated COFF buffer");
+
+ uint64_t CurPtr = 0;
+ bool IsPE = false;
+
+ // Check if this is a PE/COFF file.
+ if (Data.size() >= sizeof(object::dos_header) + sizeof(COFF::PEMagic)) {
+ const auto *DH =
+ reinterpret_cast<const object::dos_header *>(Data.data() + CurPtr);
+ if (DH->Magic[0] == 'M' && DH->Magic[1] == 'Z') {
+ // Check the PE magic bytes. ("PE\0\0")
+ CurPtr = DH->AddressOfNewExeHeader;
+ if (memcmp(Data.data() + CurPtr, COFF::PEMagic, sizeof(COFF::PEMagic)) !=
+ 0) {
+ return make_error<JITLinkError>("Incorrect PE magic");
+ }
+ CurPtr += sizeof(COFF::PEMagic);
+ IsPE = true;
+ }
+ }
+ if (Data.size() < CurPtr + sizeof(object::coff_file_header))
+ return make_error<JITLinkError>("Truncated COFF buffer");
+
+ const object::coff_file_header *COFFHeader =
+ reinterpret_cast<const object::coff_file_header *>(Data.data() + CurPtr);
+ const object::coff_bigobj_file_header *COFFBigObjHeader = nullptr;
+
+ // Deal with bigobj file
+ if (!IsPE && COFFHeader->Machine == COFF::IMAGE_FILE_MACHINE_UNKNOWN &&
+ COFFHeader->NumberOfSections == uint16_t(0xffff) &&
+ Data.size() >= sizeof(object::coff_bigobj_file_header)) {
+ if (Data.size() < sizeof(object::coff_file_header)) {
+ return make_error<JITLinkError>("Truncated COFF buffer");
+ }
+ COFFBigObjHeader =
+ reinterpret_cast<const object::coff_bigobj_file_header *>(Data.data() +
+ CurPtr);
+
+ // Verify that we are dealing with bigobj.
+ if (COFFBigObjHeader->Version >= COFF::BigObjHeader::MinBigObjectVersion &&
+ std::memcmp(COFFBigObjHeader->UUID, COFF::BigObjMagic,
+ sizeof(COFF::BigObjMagic)) == 0) {
+ COFFHeader = nullptr;
+ CurPtr += sizeof(object::coff_bigobj_file_header);
+ } else
+ COFFBigObjHeader = nullptr;
+ }
+
+ uint16_t Machine =
+ COFFHeader ? COFFHeader->Machine : COFFBigObjHeader->Machine;
+ LLVM_DEBUG({
+ dbgs() << "jitLink_COFF: PE = " << (IsPE ? "yes" : "no")
+ << ", bigobj = " << (COFFBigObjHeader ? "yes" : "no")
+ << ", identifier = \"" << ObjectBuffer.getBufferIdentifier() << "\" "
+ << "machine = " << getMachineName(Machine) << "\n";
+ });
+
+ switch (Machine) {
+ case COFF::IMAGE_FILE_MACHINE_AMD64:
+ return createLinkGraphFromCOFFObject_x86_64(ObjectBuffer);
+ default:
+ return make_error<JITLinkError>(
+ "Unsupported target machine architecture in COFF object " +
+ ObjectBuffer.getBufferIdentifier() + ": " + getMachineName(Machine));
+ }
+}
+
+void link_COFF(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ switch (G->getTargetTriple().getArch()) {
+ case Triple::x86_64:
+ link_COFF_x86_64(std::move(G), std::move(Ctx));
+ return;
+ default:
+ Ctx->notifyFailed(make_error<JITLinkError>(
+ "Unsupported target machine architecture in COFF link graph " +
+ G->getName()));
+ return;
+ }
+}
+
+} // end namespace jitlink
+} // end namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
new file mode 100644
index 000000000000..43b9c2ba400b
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
@@ -0,0 +1,527 @@
+//=--------- COFFLinkGraphBuilder.cpp - COFF LinkGraph builder ----------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic COFF LinkGraph buliding code.
+//
+//===----------------------------------------------------------------------===//
+#include "COFFLinkGraphBuilder.h"
+
+#define DEBUG_TYPE "jitlink"
+
+static const char *CommonSectionName = "__common";
+
+namespace llvm {
+namespace jitlink {
+
+COFFLinkGraphBuilder::COFFLinkGraphBuilder(
+ const object::COFFObjectFile &Obj, Triple TT,
+ LinkGraph::GetEdgeKindNameFunction GetEdgeKindName)
+ : Obj(Obj),
+ G(std::make_unique<LinkGraph>(
+ Obj.getFileName().str(), Triple(std::move(TT)), getPointerSize(Obj),
+ getEndianness(Obj), std::move(GetEdgeKindName))) {
+ LLVM_DEBUG({
+ dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()
+ << "\"\n";
+ });
+}
+
+COFFLinkGraphBuilder::~COFFLinkGraphBuilder() = default;
+
+unsigned
+COFFLinkGraphBuilder::getPointerSize(const object::COFFObjectFile &Obj) {
+ return Obj.getBytesInAddress();
+}
+
+support::endianness
+COFFLinkGraphBuilder::getEndianness(const object::COFFObjectFile &Obj) {
+ return Obj.isLittleEndian() ? support::little : support::big;
+}
+
+uint64_t COFFLinkGraphBuilder::getSectionSize(const object::COFFObjectFile &Obj,
+ const object::coff_section *Sec) {
+ // Consider the difference between executable form and object form.
+ // More information is inside COFFObjectFile::getSectionSize
+ if (Obj.getDOSHeader())
+ return std::min(Sec->VirtualSize, Sec->SizeOfRawData);
+ return Sec->SizeOfRawData;
+}
+
+uint64_t
+COFFLinkGraphBuilder::getSectionAddress(const object::COFFObjectFile &Obj,
+ const object::coff_section *Section) {
+ return Section->VirtualAddress + Obj.getImageBase();
+}
+
+bool COFFLinkGraphBuilder::isComdatSection(
+ const object::coff_section *Section) {
+ return Section->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT;
+}
+
+Section &COFFLinkGraphBuilder::getCommonSection() {
+ if (!CommonSection)
+ CommonSection =
+ &G->createSection(CommonSectionName, MemProt::Read | MemProt::Write);
+ return *CommonSection;
+}
+
+Expected<std::unique_ptr<LinkGraph>> COFFLinkGraphBuilder::buildGraph() {
+ if (!Obj.isRelocatableObject())
+ return make_error<JITLinkError>("Object is not a relocatable COFF file");
+
+ if (auto Err = graphifySections())
+ return std::move(Err);
+
+ if (auto Err = graphifySymbols())
+ return std::move(Err);
+
+ if (auto Err = addRelocations())
+ return std::move(Err);
+
+ return std::move(G);
+}
+
+StringRef
+COFFLinkGraphBuilder::getCOFFSectionName(COFFSectionIndex SectionIndex,
+ const object::coff_section *Sec,
+ object::COFFSymbolRef Sym) {
+ switch (SectionIndex) {
+ case COFF::IMAGE_SYM_UNDEFINED: {
+ if (Sym.getValue())
+ return "(common)";
+ else
+ return "(external)";
+ }
+ case COFF::IMAGE_SYM_ABSOLUTE:
+ return "(absolute)";
+ case COFF::IMAGE_SYM_DEBUG: {
+ // Used with .file symbol
+ return "(debug)";
+ }
+ default: {
+ // Non reserved regular section numbers
+ if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(Sec))
+ return *SecNameOrErr;
+ }
+ }
+ return "";
+}
+
+Error COFFLinkGraphBuilder::graphifySections() {
+ LLVM_DEBUG(dbgs() << " Creating graph sections...\n");
+
+ GraphBlocks.resize(Obj.getNumberOfSections() + 1);
+ // For each section...
+ for (COFFSectionIndex SecIndex = 1;
+ SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
+ SecIndex++) {
+ Expected<const object::coff_section *> Sec = Obj.getSection(SecIndex);
+ if (!Sec)
+ return Sec.takeError();
+
+ StringRef SectionName;
+ if (Expected<StringRef> SecNameOrErr = Obj.getSectionName(*Sec))
+ SectionName = *SecNameOrErr;
+
+ bool IsDiscardable =
+ (*Sec)->Characteristics &
+ (COFF::IMAGE_SCN_MEM_DISCARDABLE | COFF::IMAGE_SCN_LNK_INFO);
+ if (IsDiscardable) {
+ LLVM_DEBUG(dbgs() << " " << SecIndex << ": \"" << SectionName
+ << "\" is discardable: "
+ "No graph section will be created.\n");
+ continue;
+ }
+
+ // FIXME: Skip debug info sections
+
+ LLVM_DEBUG({
+ dbgs() << " "
+ << "Creating section for \"" << SectionName << "\"\n";
+ });
+
+ // Get the section's memory protection flags.
+ MemProt Prot = MemProt::None;
+ if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
+ Prot |= MemProt::Exec;
+ if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_READ)
+ Prot |= MemProt::Read;
+ if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_WRITE)
+ Prot |= MemProt::Write;
+
+ // Look for existing sections first.
+ auto *GraphSec = G->findSectionByName(SectionName);
+ if (!GraphSec)
+ GraphSec = &G->createSection(SectionName, Prot);
+ if (GraphSec->getMemProt() != Prot)
+ return make_error<JITLinkError>("MemProt should match");
+
+ Block *B = nullptr;
+ if ((*Sec)->Characteristics & COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA)
+ B = &G->createZeroFillBlock(
+ *GraphSec, getSectionSize(Obj, *Sec),
+ orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
+ (*Sec)->getAlignment(), 0);
+ else {
+ ArrayRef<uint8_t> Data;
+ if (auto Err = Obj.getSectionContents(*Sec, Data))
+ return Err;
+
+ B = &G->createContentBlock(
+ *GraphSec,
+ ArrayRef<char>(reinterpret_cast<const char *>(Data.data()),
+ Data.size()),
+ orc::ExecutorAddr(getSectionAddress(Obj, *Sec)),
+ (*Sec)->getAlignment(), 0);
+ }
+
+ setGraphBlock(SecIndex, B);
+ }
+
+ return Error::success();
+}
+
+Error COFFLinkGraphBuilder::graphifySymbols() {
+ LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
+
+ SymbolSets.resize(Obj.getNumberOfSections() + 1);
+ GraphSymbols.resize(Obj.getNumberOfSymbols());
+
+ for (COFFSymbolIndex SymIndex = 0;
+ SymIndex < static_cast<COFFSymbolIndex>(Obj.getNumberOfSymbols());
+ SymIndex++) {
+ Expected<object::COFFSymbolRef> Sym = Obj.getSymbol(SymIndex);
+ if (!Sym)
+ return Sym.takeError();
+
+ StringRef SymbolName;
+ if (Expected<StringRef> SymNameOrErr = Obj.getSymbolName(*Sym))
+ SymbolName = *SymNameOrErr;
+
+ COFFSectionIndex SectionIndex = Sym->getSectionNumber();
+ const object::coff_section *Sec = nullptr;
+
+ if (!COFF::isReservedSectionNumber(SectionIndex)) {
+ auto SecOrErr = Obj.getSection(SectionIndex);
+ if (!SecOrErr)
+ return make_error<JITLinkError>(
+ "Invalid COFF section number:" + formatv("{0:d}: ", SectionIndex) +
+ " (" + toString(SecOrErr.takeError()) + ")");
+ Sec = *SecOrErr;
+ }
+
+ // Create jitlink symbol
+ jitlink::Symbol *GSym = nullptr;
+ if (Sym->isFileRecord())
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex << ": Skipping FileRecord symbol \""
+ << SymbolName << "\" in "
+ << getCOFFSectionName(SectionIndex, Sec, *Sym)
+ << " (index: " << SectionIndex << ") \n";
+ });
+ else if (Sym->isUndefined()) {
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Creating external graph symbol for COFF symbol \""
+ << SymbolName << "\" in "
+ << getCOFFSectionName(SectionIndex, Sec, *Sym)
+ << " (index: " << SectionIndex << ") \n";
+ });
+ GSym =
+ &G->addExternalSymbol(SymbolName, Sym->getValue(), Linkage::Strong);
+ } else if (Sym->isWeakExternal()) {
+ COFFSymbolIndex TagIndex =
+ Sym->getAux<object::coff_aux_weak_external>()->TagIndex;
+ assert(Sym->getAux<object::coff_aux_weak_external>()->Characteristics !=
+ COFF::IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY &&
+ "IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY is not supported.");
+ assert(Sym->getAux<object::coff_aux_weak_external>()->Characteristics !=
+ COFF::IMAGE_WEAK_EXTERN_SEARCH_LIBRARY &&
+ "IMAGE_WEAK_EXTERN_SEARCH_LIBRARY is not supported.");
+ WeakAliasRequests.push_back({SymIndex, TagIndex, SymbolName});
+ } else {
+ Expected<jitlink::Symbol *> NewGSym =
+ createDefinedSymbol(SymIndex, SymbolName, *Sym, Sec);
+ if (!NewGSym)
+ return NewGSym.takeError();
+ GSym = *NewGSym;
+ if (GSym) {
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Creating defined graph symbol for COFF symbol \""
+ << SymbolName << "\" in "
+ << getCOFFSectionName(SectionIndex, Sec, *Sym)
+ << " (index: " << SectionIndex << ") \n";
+ dbgs() << " " << *GSym << "\n";
+ });
+ }
+ }
+
+ // Register the symbol
+ if (GSym)
+ setGraphSymbol(SectionIndex, SymIndex, *GSym);
+ SymIndex += Sym->getNumberOfAuxSymbols();
+ }
+
+ if (auto Err = flushWeakAliasRequests())
+ return Err;
+
+ if (auto Err = calculateImplicitSizeOfSymbols())
+ return Err;
+
+ return Error::success();
+}
+
+Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
+ // Export the weak external symbols and alias it
+ for (auto &WeakAlias : WeakAliasRequests) {
+ if (auto *Target = getGraphSymbol(WeakAlias.Target)) {
+ Expected<object::COFFSymbolRef> AliasSymbol =
+ Obj.getSymbol(WeakAlias.Alias);
+ if (!AliasSymbol)
+ return AliasSymbol.takeError();
+
+ // FIXME: Support this when there's a way to handle this.
+ if (!Target->isDefined())
+ return make_error<JITLinkError>("Weak external symbol with external "
+ "symbol as alternative not supported.");
+
+ jitlink::Symbol *NewSymbol = &G->addDefinedSymbol(
+ Target->getBlock(), Target->getOffset(), WeakAlias.SymbolName,
+ Target->getSize(), Linkage::Weak, Scope::Default,
+ Target->isCallable(), false);
+ setGraphSymbol(AliasSymbol->getSectionNumber(), WeakAlias.Alias,
+ *NewSymbol);
+ LLVM_DEBUG({
+ dbgs() << " " << WeakAlias.Alias
+ << ": Creating weak external symbol for COFF symbol \""
+ << WeakAlias.SymbolName << "\" in section "
+ << AliasSymbol->getSectionNumber() << "\n";
+ dbgs() << " " << *NewSymbol << "\n";
+ });
+ } else
+ return make_error<JITLinkError>("Weak symbol alias requested but actual "
+ "symbol not found for symbol " +
+ formatv("{0:d}", WeakAlias.Alias));
+ }
+ return Error::success();
+}
+
+// In COFF, most of the defined symbols don't contain the size information.
+// Hence, we calculate the "implicit" size of symbol by taking the delta of
+// offsets of consecutive symbols within a block. We maintain a balanced tree
+// set of symbols sorted by offset per each block in order to achieve
+// logarithmic time complexity of sorted symbol insertion. Symbol is inserted to
+// the set once it's processed in graphifySymbols. In this function, we iterate
+// each collected symbol in sorted order and calculate the implicit size.
+Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
+ for (COFFSectionIndex SecIndex = 1;
+ SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
+ SecIndex++) {
+ auto &SymbolSet = SymbolSets[SecIndex];
+ jitlink::Block *B = getGraphBlock(SecIndex);
+ orc::ExecutorAddrDiff LastOffset = B->getSize();
+ orc::ExecutorAddrDiff LastDifferentOffset = B->getSize();
+ orc::ExecutorAddrDiff LastSize = 0;
+ for (auto It = SymbolSet.rbegin(); It != SymbolSet.rend(); It++) {
+ orc::ExecutorAddrDiff Offset = It->first;
+ jitlink::Symbol *Symbol = It->second;
+ orc::ExecutorAddrDiff CandSize;
+ // Last offset can be same when aliasing happened
+ if (Symbol->getOffset() == LastOffset)
+ CandSize = LastSize;
+ else
+ CandSize = LastOffset - Offset;
+
+ LLVM_DEBUG({
+ if (Offset + Symbol->getSize() > LastDifferentOffset)
+ dbgs() << " Overlapping symbol range generated for the following "
+ "symbol:"
+ << "\n"
+ << " " << *Symbol << "\n";
+ });
+ (void)LastDifferentOffset;
+ if (LastOffset != Offset)
+ LastDifferentOffset = Offset;
+ LastSize = CandSize;
+ LastOffset = Offset;
+ if (Symbol->getSize()) {
+ // Non empty symbol can happen in COMDAT symbol.
+ // We don't consider the possibility of overlapping symbol range that
+ // could be introduced by disparity between inferred symbol size and
+ // defined symbol size because symbol size information is currently only
+ // used by jitlink-check where we have control to not make overlapping
+ // ranges.
+ continue;
+ }
+
+ LLVM_DEBUG({
+ if (!CandSize)
+ dbgs() << " Empty implicit symbol size generated for the following "
+ "symbol:"
+ << "\n"
+ << " " << *Symbol << "\n";
+ });
+
+ Symbol->setSize(CandSize);
+ }
+ }
+ return Error::success();
+}
+
+Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
+ COFFSymbolIndex SymIndex, StringRef SymbolName,
+ object::COFFSymbolRef Symbol, const object::coff_section *Section) {
+ if (Symbol.isCommon()) {
+ // FIXME: correct alignment
+ return &G->addCommonSymbol(SymbolName, Scope::Default, getCommonSection(),
+ orc::ExecutorAddr(), Symbol.getValue(),
+ Symbol.getValue(), false);
+ }
+ if (Symbol.isAbsolute())
+ return &G->addAbsoluteSymbol(SymbolName,
+ orc::ExecutorAddr(Symbol.getValue()), 0,
+ Linkage::Strong, Scope::Local, false);
+
+ if (llvm::COFF::isReservedSectionNumber(Symbol.getSectionNumber()))
+ return make_error<JITLinkError>(
+ "Reserved section number used in regular symbol " +
+ formatv("{0:d}", SymIndex));
+
+ Block *B = getGraphBlock(Symbol.getSectionNumber());
+ if (Symbol.isExternal()) {
+ // This is not a comdat sequence, export the symbol as it is
+ if (!isComdatSection(Section))
+ return &G->addDefinedSymbol(
+ *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Default,
+ Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
+ else {
+ if (!PendingComdatExport)
+ return make_error<JITLinkError>("No pending COMDAT export for symbol " +
+ formatv("{0:d}", SymIndex));
+ if (PendingComdatExport->SectionIndex != Symbol.getSectionNumber())
+ return make_error<JITLinkError>(
+ "COMDAT export section number mismatch for symbol " +
+ formatv("{0:d}", SymIndex));
+ return exportCOMDATSymbol(SymIndex, SymbolName, Symbol);
+ }
+ }
+
+ if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC) {
+ const object::coff_aux_section_definition *Definition =
+ Symbol.getSectionDefinition();
+ if (!Definition || !isComdatSection(Section)) {
+ // Handle typical static symbol
+ return &G->addDefinedSymbol(
+ *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
+ Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
+ }
+ if (Definition->Selection == COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+ // FIXME: don't dead strip this when parent section is alive
+ return &G->addDefinedSymbol(
+ *B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
+ Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
+ }
+ if (PendingComdatExport)
+ return make_error<JITLinkError>(
+ "COMDAT export request already exists before symbol " +
+ formatv("{0:d}", SymIndex));
+ return createCOMDATExportRequest(SymIndex, Symbol, Definition);
+ }
+ return make_error<JITLinkError>("Unsupported storage class " +
+ formatv("{0:d}", Symbol.getStorageClass()) +
+ " in symbol " + formatv("{0:d}", SymIndex));
+}
+
+// COMDAT handling:
+// When IMAGE_SCN_LNK_COMDAT flag is set in the flags of a section,
+// the section is called a COMDAT section. It contains two symbols
+// in a sequence that specifes the behavior. First symbol is the section
+// symbol which contains the size and name of the section. It also contains
+// selection type that specifies how duplicate of the symbol is handled.
+// Second symbol is COMDAT symbol which usually defines the external name and
+// data type.
+//
+// Since two symbols always come in a specific order, we initiate pending COMDAT
+// export request when we encounter the first symbol and actually exports it
+// when we process the second symbol.
+//
+// Process the first symbol of COMDAT sequence.
+Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
+ COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
+ const object::coff_aux_section_definition *Definition) {
+ Block *B = getGraphBlock(Symbol.getSectionNumber());
+ Linkage L = Linkage::Strong;
+ switch (Definition->Selection) {
+ case COFF::IMAGE_COMDAT_SELECT_NODUPLICATES: {
+ L = Linkage::Strong;
+ break;
+ }
+ case COFF::IMAGE_COMDAT_SELECT_ANY: {
+ L = Linkage::Weak;
+ break;
+ }
+ case COFF::IMAGE_COMDAT_SELECT_EXACT_MATCH:
+ case COFF::IMAGE_COMDAT_SELECT_SAME_SIZE: {
+ // FIXME: Implement size/content validation when LinkGraph is able to
+ // handle this.
+ L = Linkage::Weak;
+ break;
+ }
+ case COFF::IMAGE_COMDAT_SELECT_LARGEST: {
+ // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST when LinkGraph is able to
+ // handle this.
+ return make_error<JITLinkError>(
+ "IMAGE_COMDAT_SELECT_LARGEST is not supported.");
+ }
+ case COFF::IMAGE_COMDAT_SELECT_NEWEST: {
+ // Even link.exe doesn't support this selection properly.
+ return make_error<JITLinkError>(
+ "IMAGE_COMDAT_SELECT_NEWEST is not supported.");
+ }
+ default: {
+ return make_error<JITLinkError>("Invalid comdat selection type: " +
+ formatv("{0:d}", Definition->Selection));
+ }
+ }
+ PendingComdatExport = {SymIndex, Symbol.getSectionNumber(), L};
+ return &G->addAnonymousSymbol(*B, Symbol.getValue(), Definition->Length,
+ false, false);
+}
+
+// Process the second symbol of COMDAT sequence.
+Expected<Symbol *>
+COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
+ StringRef SymbolName,
+ object::COFFSymbolRef Symbol) {
+ COFFSymbolIndex TargetIndex = PendingComdatExport->SymbolIndex;
+ Linkage L = PendingComdatExport->Linkage;
+ jitlink::Symbol *Target = getGraphSymbol(TargetIndex);
+ assert(Target && "COMDAT leaader is invalid.");
+ assert((llvm::count_if(G->defined_symbols(),
+ [&](const jitlink::Symbol *Sym) {
+ return Sym->getName() == SymbolName;
+ }) == 0) &&
+ "Duplicate defined symbol");
+ Target->setName(SymbolName);
+ Target->setLinkage(L);
+ Target->setCallable(Symbol.getComplexType() ==
+ COFF::IMAGE_SYM_DTYPE_FUNCTION);
+ Target->setScope(Scope::Default);
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Exporting COMDAT graph symbol for COFF symbol \"" << SymbolName
+ << "\" in section " << Symbol.getSectionNumber() << "\n";
+ dbgs() << " " << *Target << "\n";
+ });
+ PendingComdatExport = None;
+ return Target;
+}
+
+} // namespace jitlink
+} // namespace llvm \ No newline at end of file
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
new file mode 100644
index 000000000000..4dc1b14dc4a2
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
@@ -0,0 +1,199 @@
+//===----- COFFLinkGraphBuilder.h - COFF LinkGraph builder ----*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// Generic COFF LinkGraph building code.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
+#define LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
+
+#include "llvm/ADT/DenseMap.h"
+#include "llvm/ADT/StringMap.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/Object/COFF.h"
+
+#include "EHFrameSupportImpl.h"
+#include "JITLinkGeneric.h"
+
+#define DEBUG_TYPE "jitlink"
+
+#include <list>
+
+namespace llvm {
+namespace jitlink {
+
+class COFFLinkGraphBuilder {
+public:
+ virtual ~COFFLinkGraphBuilder();
+ Expected<std::unique_ptr<LinkGraph>> buildGraph();
+
+protected:
+ using COFFSectionIndex = int32_t;
+ using COFFSymbolIndex = int32_t;
+
+ COFFLinkGraphBuilder(const object::COFFObjectFile &Obj, Triple TT,
+ LinkGraph::GetEdgeKindNameFunction GetEdgeKindName);
+
+ LinkGraph &getGraph() const { return *G; }
+
+ const object::COFFObjectFile &getObject() const { return Obj; }
+
+ virtual Error addRelocations() = 0;
+
+ Error graphifySections();
+ Error graphifySymbols();
+
+ void setGraphSymbol(COFFSectionIndex SecIndex, COFFSymbolIndex SymIndex,
+ Symbol &Sym) {
+ assert(!GraphSymbols[SymIndex] && "Duplicate symbol at index");
+ GraphSymbols[SymIndex] = &Sym;
+ if (!COFF::isReservedSectionNumber(SecIndex))
+ SymbolSets[SecIndex].insert({Sym.getOffset(), &Sym});
+ }
+
+ Symbol *getGraphSymbol(COFFSymbolIndex SymIndex) const {
+ if (SymIndex < 0 ||
+ SymIndex >= static_cast<COFFSymbolIndex>(GraphSymbols.size()))
+ return nullptr;
+ return GraphSymbols[SymIndex];
+ }
+
+ void setGraphBlock(COFFSectionIndex SecIndex, Block *B) {
+ assert(!GraphBlocks[SecIndex] && "Duplicate section at index");
+ assert(!COFF::isReservedSectionNumber(SecIndex) && "Invalid section index");
+ GraphBlocks[SecIndex] = B;
+ }
+
+ Block *getGraphBlock(COFFSectionIndex SecIndex) const {
+ if (SecIndex <= 0 ||
+ SecIndex >= static_cast<COFFSectionIndex>(GraphSymbols.size()))
+ return nullptr;
+ return GraphBlocks[SecIndex];
+ }
+
+ object::COFFObjectFile::section_iterator_range sections() const {
+ return Obj.sections();
+ }
+
+ /// Traverse all matching relocation records in the given section. The handler
+ /// function Func should be callable with this signature:
+ /// Error(const object::RelocationRef&,
+ /// const object::SectionRef&, Section &)
+ ///
+ template <typename RelocHandlerFunction>
+ Error forEachRelocation(const object::SectionRef &RelSec,
+ RelocHandlerFunction &&Func,
+ bool ProcessDebugSections = false);
+
+ /// Traverse all matching relocation records in the given section. Convenience
+ /// wrapper to allow passing a member function for the handler.
+ ///
+ template <typename ClassT, typename RelocHandlerMethod>
+ Error forEachRelocation(const object::SectionRef &RelSec, ClassT *Instance,
+ RelocHandlerMethod &&Method,
+ bool ProcessDebugSections = false) {
+ return forEachRelocation(
+ RelSec,
+ [Instance, Method](const auto &Rel, const auto &Target, auto &GS) {
+ return (Instance->*Method)(Rel, Target, GS);
+ },
+ ProcessDebugSections);
+ }
+
+private:
+ // Pending comdat symbol export that is initiated by the first symbol of
+ // COMDAT sequence.
+ struct ComdatExportRequest {
+ COFFSymbolIndex SymbolIndex;
+ COFFSectionIndex SectionIndex;
+ jitlink::Linkage Linkage;
+ };
+ Optional<ComdatExportRequest> PendingComdatExport;
+
+ // This represents a pending request to create a weak external symbol with a
+ // name.
+ struct WeakAliasRequest {
+ COFFSymbolIndex Alias;
+ COFFSymbolIndex Target;
+ StringRef SymbolName;
+ };
+ std::vector<WeakAliasRequest> WeakAliasRequests;
+
+ // Per COFF section jitlink symbol set sorted by offset.
+ // Used for calculating implicit size of defined symbols.
+ using SymbolSet = std::set<std::pair<orc::ExecutorAddrDiff, Symbol *>>;
+ std::vector<SymbolSet> SymbolSets;
+
+ Section &getCommonSection();
+
+ Expected<Symbol *> createDefinedSymbol(COFFSymbolIndex SymIndex,
+ StringRef SymbolName,
+ object::COFFSymbolRef Symbol,
+ const object::coff_section *Section);
+ Expected<Symbol *> createCOMDATExportRequest(
+ COFFSymbolIndex SymIndex, object::COFFSymbolRef Symbol,
+ const object::coff_aux_section_definition *Definition);
+ Expected<Symbol *> exportCOMDATSymbol(COFFSymbolIndex SymIndex,
+ StringRef SymbolName,
+ object::COFFSymbolRef Symbol);
+ Error flushWeakAliasRequests();
+ Error calculateImplicitSizeOfSymbols();
+
+ static uint64_t getSectionAddress(const object::COFFObjectFile &Obj,
+ const object::coff_section *Section);
+ static uint64_t getSectionSize(const object::COFFObjectFile &Obj,
+ const object::coff_section *Section);
+ static bool isComdatSection(const object::coff_section *Section);
+ static unsigned getPointerSize(const object::COFFObjectFile &Obj);
+ static support::endianness getEndianness(const object::COFFObjectFile &Obj);
+ StringRef getCOFFSectionName(COFFSectionIndex SectionIndex,
+ const object::coff_section *Sec,
+ object::COFFSymbolRef Sym);
+
+ const object::COFFObjectFile &Obj;
+ std::unique_ptr<LinkGraph> G;
+
+ Section *CommonSection = nullptr;
+ std::vector<Block *> GraphBlocks;
+ std::vector<Symbol *> GraphSymbols;
+};
+
+template <typename RelocHandlerFunction>
+Error COFFLinkGraphBuilder::forEachRelocation(const object::SectionRef &RelSec,
+ RelocHandlerFunction &&Func,
+ bool ProcessDebugSections) {
+
+ auto COFFRelSect = Obj.getCOFFSection(RelSec);
+
+ // Target sections have names in valid COFF object files.
+ Expected<StringRef> Name = Obj.getSectionName(COFFRelSect);
+ if (!Name)
+ return Name.takeError();
+ LLVM_DEBUG(dbgs() << " " << *Name << ":\n");
+
+ // Lookup the link-graph node corresponding to the target section name.
+ auto *BlockToFix = getGraphBlock(RelSec.getIndex() + 1);
+ if (!BlockToFix)
+ return make_error<StringError>(
+ "Referencing a section that wasn't added to the graph: " + *Name,
+ inconvertibleErrorCode());
+
+ // Let the callee process relocation entries one by one.
+ for (const auto &R : RelSec.relocations())
+ if (Error Err = Func(R, RelSec, *BlockToFix))
+ return Err;
+
+ LLVM_DEBUG(dbgs() << "\n");
+ return Error::success();
+}
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LIB_EXECUTIONENGINE_JITLINK_COFFLINKGRAPHBUILDER_H
diff --git a/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
new file mode 100644
index 000000000000..3d36ad1ed767
--- /dev/null
+++ b/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
@@ -0,0 +1,216 @@
+//===----- COFF_x86_64.cpp - JIT linker implementation for COFF/x86_64 ----===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+//
+// COFF/x86_64 jit-link implementation.
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
+#include "COFFLinkGraphBuilder.h"
+#include "EHFrameSupportImpl.h"
+#include "JITLinkGeneric.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/ExecutionEngine/JITLink/x86_64.h"
+#include "llvm/Object/COFF.h"
+#include "llvm/Support/Endian.h"
+
+#define DEBUG_TYPE "jitlink"
+
+using namespace llvm;
+using namespace llvm::jitlink;
+
+namespace {
+
+class COFFJITLinker_x86_64 : public JITLinker<COFFJITLinker_x86_64> {
+ friend class JITLinker<COFFJITLinker_x86_64>;
+
+public:
+ COFFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
+ std::unique_ptr<LinkGraph> G,
+ PassConfiguration PassConfig)
+ : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
+
+private:
+ Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
+ return x86_64::applyFixup(G, B, E, nullptr);
+ }
+};
+
+class COFFLinkGraphBuilder_x86_64 : public COFFLinkGraphBuilder {
+private:
+ uint64_t ImageBase = 0;
+ enum COFFX86RelocationKind {
+ COFFAddr32NB,
+ COFFRel32,
+ };
+
+ static Expected<COFFX86RelocationKind>
+ getRelocationKind(const uint32_t Type) {
+ switch (Type) {
+ case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR32NB:
+ return COFFAddr32NB;
+ case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32:
+ return COFFRel32;
+ }
+
+ return make_error<JITLinkError>("Unsupported x86_64 relocation:" +
+ formatv("{0:d}", Type));
+ }
+
+ Error addRelocations() override {
+
+ LLVM_DEBUG(dbgs() << "Processing relocations:\n");
+
+ for (const auto &RelSect : sections())
+ if (Error Err = COFFLinkGraphBuilder::forEachRelocation(
+ RelSect, this, &COFFLinkGraphBuilder_x86_64::addSingleRelocation))
+ return Err;
+
+ return Error::success();
+ }
+
+ uint64_t getImageBase() {
+ if (!ImageBase) {
+ ImageBase = std::numeric_limits<uint64_t>::max();
+ for (const auto &Block : getGraph().blocks()) {
+ if (Block->getAddress().getValue())
+ ImageBase = std::min(ImageBase, Block->getAddress().getValue());
+ }
+ }
+ return ImageBase;
+ }
+
+ Error addSingleRelocation(const object::RelocationRef &Rel,
+ const object::SectionRef &FixupSect,
+ Block &BlockToFix) {
+
+ const object::coff_relocation *COFFRel = getObject().getCOFFRelocation(Rel);
+ auto SymbolIt = Rel.getSymbol();
+ if (SymbolIt == getObject().symbol_end()) {
+ return make_error<StringError>(
+ formatv("Invalid symbol index in relocation entry. "
+ "index: {0}, section: {1}",
+ COFFRel->SymbolTableIndex, FixupSect.getIndex()),
+ inconvertibleErrorCode());
+ }
+
+ object::COFFSymbolRef COFFSymbol = getObject().getCOFFSymbol(*SymbolIt);
+ COFFSymbolIndex SymIndex = getObject().getSymbolIndex(COFFSymbol);
+
+ Symbol *GraphSymbol = getGraphSymbol(SymIndex);
+ if (!GraphSymbol)
+ return make_error<StringError>(
+ formatv("Could not find symbol at given index, did you add it to "
+ "JITSymbolTable? index: {0}, section: {1}",
+ SymIndex, FixupSect.getIndex()),
+ inconvertibleErrorCode());
+
+ Expected<COFFX86RelocationKind> RelocKind =
+ getRelocationKind(Rel.getType());
+ if (!RelocKind)
+ return RelocKind.takeError();
+
+ int64_t Addend = 0;
+ orc::ExecutorAddr FixupAddress =
+ orc::ExecutorAddr(FixupSect.getAddress()) + Rel.getOffset();
+ Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
+
+ Edge::Kind Kind = Edge::Invalid;
+
+ switch (*RelocKind) {
+ case COFFAddr32NB: {
+ Kind = x86_64::Pointer32;
+ Offset -= getImageBase();
+ break;
+ }
+ case COFFRel32: {
+ Kind = x86_64::BranchPCRel32;
+ break;
+ }
+ };
+
+ Edge GE(Kind, Offset, *GraphSymbol, Addend);
+ LLVM_DEBUG({
+ dbgs() << " ";
+ printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind));
+ dbgs() << "\n";
+ });
+
+ BlockToFix.addEdge(std::move(GE));
+ return Error::success();
+ }
+
+ /// Return the string name of the given COFF x86_64 edge kind.
+ const char *getCOFFX86RelocationKindName(COFFX86RelocationKind R) {
+ switch (R) {
+ case COFFAddr32NB:
+ return "COFFAddr32NB";
+ case COFFRel32:
+ return "COFFRel32";
+ }
+ }
+
+public:
+ COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T)
+ : COFFLinkGraphBuilder(Obj, std::move(T), x86_64::getEdgeKindName) {}
+};
+
+Error buildTables_COFF_x86_64(LinkGraph &G) {
+ LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
+
+ x86_64::GOTTableManager GOT;
+ x86_64::PLTTableManager PLT(GOT);
+ visitExistingEdges(G, GOT, PLT);
+ return Error::success();
+}
+} // namespace
+
+namespace llvm {
+namespace jitlink {
+
+Expected<std::unique_ptr<LinkGraph>>
+createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer) {
+ LLVM_DEBUG({
+ dbgs() << "Building jitlink graph for new input "
+ << ObjectBuffer.getBufferIdentifier() << "...\n";
+ });
+
+ auto COFFObj = object::ObjectFile::createCOFFObjectFile(ObjectBuffer);
+ if (!COFFObj)
+ return COFFObj.takeError();
+
+ return COFFLinkGraphBuilder_x86_64(**COFFObj, (*COFFObj)->makeTriple())
+ .buildGraph();
+}
+
+void link_COFF_x86_64(std::unique_ptr<LinkGraph> G,
+ std::unique_ptr<JITLinkContext> Ctx) {
+ PassConfiguration Config;
+ const Triple &TT = G->getTargetTriple();
+ if (Ctx->shouldAddDefaultTargetPasses(TT)) {
+ // Add a mark-live pass.
+ if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ Config.PrePrunePasses.push_back(std::move(MarkLive));
+ else
+ Config.PrePrunePasses.push_back(markAllSymbolsLive);
+
+ // Add an in-place GOT/Stubs/TLSInfoEntry build pass.
+ Config.PostPrunePasses.push_back(buildTables_COFF_x86_64);
+
+ // Add GOT/Stubs optimizer pass.
+ Config.PreFixupPasses.push_back(x86_64::optimizeGOTAndStubAccesses);
+ }
+
+ if (auto Err = Ctx->modifyPassConfig(*G, Config))
+ return Ctx->notifyFailed(std::move(Err));
+
+ COFFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
+}
+
+} // namespace jitlink
+} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
index b1492cd74508..389fd14c0f29 100644
--- a/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/EHFrameSupport.cpp
@@ -33,7 +33,7 @@ Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
if (!EHFrame) {
LLVM_DEBUG({
dbgs() << "EHFrameEdgeFixer: No " << EHFrameSectionName
- << " section. Nothing to do\n";
+ << " section in \"" << G.getName() << "\". Nothing to do.\n";
});
return Error::success();
}
@@ -44,7 +44,8 @@ Error EHFrameEdgeFixer::operator()(LinkGraph &G) {
"EHFrameEdgeFixer only supports 32 and 64 bit targets");
LLVM_DEBUG({
- dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << "...\n";
+ dbgs() << "EHFrameEdgeFixer: Processing " << EHFrameSectionName << " in \""
+ << G.getName() << "\"...\n";
});
ParseContext PC(G);
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
index 98da3f155c3e..7d67e5ef343a 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_aarch64.cpp
@@ -63,6 +63,10 @@ private:
ELFPrel64,
ELFAdrGOTPage21,
ELFLd64GOTLo12,
+ ELFTLSDescAdrPage21,
+ ELFTLSDescAddLo12,
+ ELFTLSDescLd64Lo12,
+ ELFTLSDescCall,
};
static Expected<ELFAArch64RelocationKind>
@@ -104,6 +108,14 @@ private:
return ELFAdrGOTPage21;
case ELF::R_AARCH64_LD64_GOT_LO12_NC:
return ELFLd64GOTLo12;
+ case ELF::R_AARCH64_TLSDESC_ADR_PAGE21:
+ return ELFTLSDescAdrPage21;
+ case ELF::R_AARCH64_TLSDESC_ADD_LO12:
+ return ELFTLSDescAddLo12;
+ case ELF::R_AARCH64_TLSDESC_LD64_LO12:
+ return ELFTLSDescLd64Lo12;
+ case ELF::R_AARCH64_TLSDESC_CALL:
+ return ELFTLSDescCall;
}
return make_error<JITLinkError>(
@@ -292,6 +304,21 @@ private:
Kind = aarch64::GOTPageOffset12;
break;
}
+ case ELFTLSDescAdrPage21: {
+ Kind = aarch64::TLSDescPage21;
+ break;
+ }
+ case ELFTLSDescAddLo12: {
+ Kind = aarch64::TLSDescPageOffset12;
+ break;
+ }
+ case ELFTLSDescLd64Lo12: {
+ Kind = aarch64::TLSDescPageOffset12;
+ break;
+ }
+ case ELFTLSDescCall: {
+ return Error::success();
+ }
};
Edge GE(Kind, Offset, *GraphSymbol, Addend);
@@ -302,6 +329,7 @@ private:
});
BlockToFix.addEdge(std::move(GE));
+
return Error::success();
}
@@ -342,6 +370,14 @@ private:
return "ELFAdrGOTPage21";
case ELFLd64GOTLo12:
return "ELFLd64GOTLo12";
+ case ELFTLSDescAdrPage21:
+ return "ELFTLSDescAdrPage21";
+ case ELFTLSDescAddLo12:
+ return "ELFTLSDescAddLo12";
+ case ELFTLSDescLd64Lo12:
+ return "ELFTLSDescLd64Lo12";
+ case ELFTLSDescCall:
+ return "ELFTLSDescCall";
default:
return getGenericEdgeKindName(static_cast<Edge::Kind>(R));
}
@@ -354,12 +390,133 @@ public:
aarch64::getEdgeKindName) {}
};
+// TLS Info Builder.
+class TLSInfoTableManager_ELF_aarch64
+ : public TableManager<TLSInfoTableManager_ELF_aarch64> {
+public:
+ static StringRef getSectionName() { return "$__TLSINFO"; }
+
+ static const uint8_t TLSInfoEntryContent[16];
+
+ bool visitEdge(LinkGraph &G, Block *B, Edge &E) { return false; }
+
+ Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+ // the TLS Info entry's key value will be written by the fixTLVSectionByName
+ // pass, so create mutable content.
+ auto &TLSInfoEntry = G.createMutableContentBlock(
+ getTLSInfoSection(G), G.allocateContent(getTLSInfoEntryContent()),
+ orc::ExecutorAddr(), 8, 0);
+ TLSInfoEntry.addEdge(aarch64::Pointer64, 8, Target, 0);
+ return G.addAnonymousSymbol(TLSInfoEntry, 0, 16, false, false);
+ }
+
+private:
+ Section &getTLSInfoSection(LinkGraph &G) {
+ if (!TLSInfoTable)
+ TLSInfoTable = &G.createSection(getSectionName(), MemProt::Read);
+ return *TLSInfoTable;
+ }
+
+ ArrayRef<char> getTLSInfoEntryContent() const {
+ return {reinterpret_cast<const char *>(TLSInfoEntryContent),
+ sizeof(TLSInfoEntryContent)};
+ }
+
+ Section *TLSInfoTable = nullptr;
+};
+
+const uint8_t TLSInfoTableManager_ELF_aarch64::TLSInfoEntryContent[16] = {
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /*pthread key */
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 /*data address*/
+};
+
+// TLS Descriptor Builder.
+class TLSDescTableManager_ELF_aarch64
+ : public TableManager<TLSDescTableManager_ELF_aarch64> {
+public:
+ TLSDescTableManager_ELF_aarch64(
+ TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager)
+ : TLSInfoTableManager(TLSInfoTableManager) {}
+
+ static StringRef getSectionName() { return "$__TLSDESC"; }
+
+ static const uint8_t TLSDescEntryContent[16];
+
+ bool visitEdge(LinkGraph &G, Block *B, Edge &E) {
+ Edge::Kind KindToSet = Edge::Invalid;
+ switch (E.getKind()) {
+ case aarch64::TLSDescPage21: {
+ KindToSet = aarch64::Page21;
+ break;
+ }
+ case aarch64::TLSDescPageOffset12: {
+ KindToSet = aarch64::PageOffset12;
+ break;
+ }
+ default:
+ return false;
+ }
+ assert(KindToSet != Edge::Invalid &&
+ "Fell through switch, but no new kind to set");
+ DEBUG_WITH_TYPE("jitlink", {
+ dbgs() << " Fixing " << G.getEdgeKindName(E.getKind()) << " edge at "
+ << B->getFixupAddress(E) << " (" << B->getAddress() << " + "
+ << formatv("{0:x}", E.getOffset()) << ")\n";
+ });
+ E.setKind(KindToSet);
+ E.setTarget(getEntryForTarget(G, E.getTarget()));
+ return true;
+ }
+
+ Symbol &createEntry(LinkGraph &G, Symbol &Target) {
+ auto &EntryBlock =
+ G.createContentBlock(getTLSDescSection(G), getTLSDescBlockContent(),
+ orc::ExecutorAddr(), 8, 0);
+ EntryBlock.addEdge(aarch64::Pointer64, 0, getTLSDescResolver(G), 0);
+ EntryBlock.addEdge(aarch64::Pointer64, 8,
+ TLSInfoTableManager.getEntryForTarget(G, Target), 0);
+ return G.addAnonymousSymbol(EntryBlock, 0, 8, false, false);
+ }
+
+private:
+ Section &getTLSDescSection(LinkGraph &G) {
+ if (!GOTSection)
+ GOTSection = &G.createSection(getSectionName(), MemProt::Read);
+ return *GOTSection;
+ }
+
+ Symbol &getTLSDescResolver(LinkGraph &G) {
+ if (!TLSDescResolver)
+ TLSDescResolver =
+ &G.addExternalSymbol("__tlsdesc_resolver", 8, Linkage::Strong);
+ return *TLSDescResolver;
+ }
+
+ ArrayRef<char> getTLSDescBlockContent() {
+ return {reinterpret_cast<const char *>(TLSDescEntryContent),
+ sizeof(TLSDescEntryContent)};
+ }
+
+ Section *GOTSection = nullptr;
+ Symbol *TLSDescResolver = nullptr;
+ TLSInfoTableManager_ELF_aarch64 &TLSInfoTableManager;
+};
+
+const uint8_t TLSDescTableManager_ELF_aarch64::TLSDescEntryContent[16] = {
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, /*resolver function pointer*/
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00 /*pointer to tls info*/
+};
+
Error buildTables_ELF_aarch64(LinkGraph &G) {
LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
aarch64::GOTTableManager GOT;
aarch64::PLTTableManager PLT(GOT);
- visitExistingEdges(G, GOT, PLT);
+ TLSInfoTableManager_ELF_aarch64 TLSInfo;
+ TLSDescTableManager_ELF_aarch64 TLSDesc(TLSInfo);
+ visitExistingEdges(G, GOT, PLT, TLSDesc, TLSInfo);
return Error::success();
}
@@ -406,7 +563,7 @@ void link_ELF_aarch64(std::unique_ptr<LinkGraph> G,
else
Config.PrePrunePasses.push_back(markAllSymbolsLive);
- // Add an in-place GOT/Stubs build pass.
+ // Add an in-place GOT/TLS/Stubs build pass.
Config.PostPrunePasses.push_back(buildTables_ELF_aarch64);
}
diff --git a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
index 197ab71f5274..c7596efe2bb8 100644
--- a/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/ELF_riscv.cpp
@@ -494,6 +494,30 @@ private:
Block &BlockToFix) {
using Base = ELFLinkGraphBuilder<ELFT>;
+ uint32_t Type = Rel.getType(false);
+ // We do not implement linker relaxation, except what is required for
+ // alignment (see below).
+ if (Type == llvm::ELF::R_RISCV_RELAX)
+ return Error::success();
+
+ int64_t Addend = Rel.r_addend;
+ if (Type == llvm::ELF::R_RISCV_ALIGN) {
+ uint64_t Alignment = PowerOf2Ceil(Addend);
+ // FIXME: Implement support for ensuring alignment together with linker
+ // relaxation; 2 bytes are guaranteed by the length of compressed
+ // instructions, so this does not need any action from our side.
+ if (Alignment > 2)
+ return make_error<JITLinkError>(
+ formatv("Unsupported relocation R_RISCV_ALIGN with alignment {0} "
+ "larger than 2 (addend: {1})",
+ Alignment, Addend));
+ return Error::success();
+ }
+
+ Expected<riscv::EdgeKind_riscv> Kind = getRelocationKind(Type);
+ if (!Kind)
+ return Kind.takeError();
+
uint32_t SymbolIndex = Rel.getSymbol(false);
auto ObjSymbol = Base::Obj.getRelocationSymbol(Rel, Base::SymTabSec);
if (!ObjSymbol)
@@ -508,12 +532,6 @@ private:
Base::GraphSymbols.size()),
inconvertibleErrorCode());
- uint32_t Type = Rel.getType(false);
- Expected<riscv::EdgeKind_riscv> Kind = getRelocationKind(Type);
- if (!Kind)
- return Kind.takeError();
-
- int64_t Addend = Rel.r_addend;
auto FixupAddress = orc::ExecutorAddr(FixupSect.sh_addr) + Rel.r_offset;
Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
Edge GE(*Kind, Offset, *GraphSymbol, Addend);
diff --git a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
index 43efe0725cfe..08fdc7c9e6b1 100644
--- a/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/JITLink.cpp
@@ -9,10 +9,10 @@
#include "llvm/ExecutionEngine/JITLink/JITLink.h"
#include "llvm/BinaryFormat/Magic.h"
+#include "llvm/ExecutionEngine/JITLink/COFF.h"
#include "llvm/ExecutionEngine/JITLink/ELF.h"
#include "llvm/ExecutionEngine/JITLink/MachO.h"
#include "llvm/Support/Format.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/raw_ostream.h"
@@ -41,8 +41,6 @@ public:
}
};
-static ManagedStatic<JITLinkerErrorCategory> JITLinkerErrorCategory;
-
} // namespace
namespace llvm {
@@ -53,7 +51,8 @@ char JITLinkError::ID = 0;
void JITLinkError::log(raw_ostream &OS) const { OS << ErrMsg; }
std::error_code JITLinkError::convertToErrorCode() const {
- return std::error_code(GenericJITLinkError, *JITLinkerErrorCategory);
+ static JITLinkerErrorCategory TheJITLinkerErrorCategory;
+ return std::error_code(GenericJITLinkError, TheJITLinkerErrorCategory);
}
const char *getGenericEdgeKindName(Edge::Kind K) {
@@ -410,6 +409,8 @@ createLinkGraphFromObject(MemoryBufferRef ObjectBuffer) {
return createLinkGraphFromMachOObject(ObjectBuffer);
case file_magic::elf_relocatable:
return createLinkGraphFromELFObject(ObjectBuffer);
+ case file_magic::coff_object:
+ return createLinkGraphFromCOFFObject(ObjectBuffer);
default:
return make_error<JITLinkError>("Unsupported file format");
};
@@ -421,6 +422,8 @@ void link(std::unique_ptr<LinkGraph> G, std::unique_ptr<JITLinkContext> Ctx) {
return link_MachO(std::move(G), std::move(Ctx));
case Triple::ELF:
return link_ELF(std::move(G), std::move(Ctx));
+ case Triple::COFF:
+ return link_COFF(std::move(G), std::move(Ctx));
default:
Ctx->notifyFailed(make_error<JITLinkError>("Unsupported object format"));
};
diff --git a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
index dd50314d3ed7..04194318498f 100644
--- a/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/MachO_arm64.cpp
@@ -425,7 +425,7 @@ private:
else
return TargetSymbolOrErr.takeError();
- Kind = aarch64::PointerToGOT;
+ Kind = aarch64::Delta32ToGOT;
break;
case MachODelta32:
case MachODelta64: {
diff --git a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
index 28a6f9ce90d9..9ecc71dfbb54 100644
--- a/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
+++ b/llvm/lib/ExecutionEngine/JITLink/aarch64.cpp
@@ -48,8 +48,12 @@ const char *getEdgeKindName(Edge::Kind R) {
return "TLVPage21";
case TLVPageOffset12:
return "TLVPageOffset12";
- case PointerToGOT:
- return "PointerToGOT";
+ case TLSDescPage21:
+ return "TLSDescPage21";
+ case TLSDescPageOffset12:
+ return "TLSDescPageOffset12";
+ case Delta32ToGOT:
+ return "Delta32ToGOT";
case PairedAddend:
return "PairedAddend";
case LDRLiteral19:
diff --git a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
index e476c549412a..e7ca636c83e9 100644
--- a/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ELFNixPlatform.cpp
@@ -839,11 +839,13 @@ Error ELFNixPlatform::ELFNixPlatformPlugin::registerInitSections(
Error ELFNixPlatform::ELFNixPlatformPlugin::fixTLVSectionsAndEdges(
jitlink::LinkGraph &G, JITDylib &JD) {
- // TODO implement TLV support
- for (auto *Sym : G.external_symbols())
+ for (auto *Sym : G.external_symbols()) {
if (Sym->getName() == "__tls_get_addr") {
Sym->setName("___orc_rt_elfnix_tls_get_addr");
+ } else if (Sym->getName() == "__tlsdesc_resolver") {
+ Sym->setName("___orc_rt_elfnix_tlsdesc_resolver");
}
+ }
auto *TLSInfoEntrySection = G.findSectionByName("$__TLSINFO");
diff --git a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
index 6d67e6d87b56..1926ef1ecc72 100644
--- a/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/LLJIT.cpp
@@ -666,8 +666,9 @@ Error LLJITBuilderState::prepareForConstruction() {
// JIT linker.
if (!CreateObjectLinkingLayer) {
auto &TT = JTMB->getTargetTriple();
- if (TT.isOSBinFormatMachO() &&
- (TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64)) {
+ if (TT.getArch() == Triple::riscv64 ||
+ (TT.isOSBinFormatMachO() &&
+ (TT.getArch() == Triple::aarch64 || TT.getArch() == Triple::x86_64))) {
JTMB->setRelocationModel(Reloc::PIC_);
JTMB->setCodeModel(CodeModel::Small);
diff --git a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
index 394a555e453b..356b81b4f1c5 100644
--- a/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
@@ -9,6 +9,7 @@
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
+#include "llvm/Object/COFF.h"
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
@@ -145,6 +146,55 @@ getELFObjectFileSymbolInfo(ExecutionSession &ES,
return I;
}
+static Expected<MaterializationUnit::Interface>
+getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
+ const object::COFFObjectFile &Obj) {
+ MaterializationUnit::Interface I;
+
+ for (auto &Sym : Obj.symbols()) {
+ Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();
+ if (!SymFlagsOrErr)
+ // TODO: Test this error.
+ return SymFlagsOrErr.takeError();
+
+ // Skip symbols not defined in this object file.
+ if (*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined)
+ continue;
+
+ // Skip symbols that are not global.
+ if (!(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))
+ continue;
+
+ // Skip symbols that have type SF_File.
+ if (auto SymType = Sym.getType()) {
+ if (*SymType == object::SymbolRef::ST_File)
+ continue;
+ } else
+ return SymType.takeError();
+
+ auto Name = Sym.getName();
+ if (!Name)
+ return Name.takeError();
+
+ auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);
+ if (!SymFlags)
+ return SymFlags.takeError();
+ *SymFlags |= JITSymbolFlags::Exported;
+ auto COFFSym = Obj.getCOFFSymbol(Sym);
+
+ // Weak external is always a function
+ if (COFFSym.isWeakExternal()) {
+ *SymFlags |= JITSymbolFlags::Callable;
+ }
+
+ I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
+ }
+
+ // FIXME: handle init symbols
+
+ return I;
+}
+
Expected<MaterializationUnit::Interface>
getGenericObjectFileSymbolInfo(ExecutionSession &ES,
const object::ObjectFile &Obj) {
@@ -196,6 +246,8 @@ getObjectFileInterface(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {
return getMachOObjectFileSymbolInfo(ES, *MachOObj);
else if (auto *ELFObj = dyn_cast<object::ELFObjectFileBase>(Obj->get()))
return getELFObjectFileSymbolInfo(ES, *ELFObj);
+ else if (auto *COFFObj = dyn_cast<object::COFFObjectFile>(Obj->get()))
+ return getCOFFObjectFileSymbolInfo(ES, *COFFObj);
return getGenericObjectFileSymbolInfo(ES, **Obj);
}
diff --git a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
index ef764a3f0d7f..da8aaad08cad 100644
--- a/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/OrcABISupport.cpp
@@ -665,7 +665,7 @@ void OrcMips32_Base::writeIndirectStubsBlock(
//
// i..
- assert(stubAndPointerRangesOk<OrcAArch64>(
+ assert(stubAndPointerRangesOk<OrcMips32_Base>(
StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
"PointersBlock is out of range");
@@ -884,7 +884,7 @@ void OrcMips64::writeIndirectStubsBlock(
//
// ...
- assert(stubAndPointerRangesOk<OrcAArch64>(
+ assert(stubAndPointerRangesOk<OrcMips64>(
StubsBlockTargetAddress, PointersBlockTargetAddress, NumStubs) &&
"PointersBlock is out of range");
diff --git a/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp b/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
index fdad90cbcfb7..2cc2bddeb21a 100644
--- a/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/Shared/OrcError.cpp
@@ -12,7 +12,6 @@
#include "llvm/ExecutionEngine/Orc/Shared/OrcError.h"
#include "llvm/Support/ErrorHandling.h"
-#include "llvm/Support/ManagedStatic.h"
#include <type_traits>
@@ -70,7 +69,10 @@ public:
}
};
-static ManagedStatic<OrcErrorCategory> OrcErrCat;
+OrcErrorCategory &getOrcErrCat() {
+ static OrcErrorCategory OrcErrCat;
+ return OrcErrCat;
+}
} // namespace
namespace llvm {
@@ -81,7 +83,7 @@ char JITSymbolNotFound::ID = 0;
std::error_code orcError(OrcErrorCode ErrCode) {
typedef std::underlying_type<OrcErrorCode>::type UT;
- return std::error_code(static_cast<UT>(ErrCode), *OrcErrCat);
+ return std::error_code(static_cast<UT>(ErrCode), getOrcErrCat());
}
DuplicateDefinition::DuplicateDefinition(std::string SymbolName)
@@ -105,7 +107,7 @@ JITSymbolNotFound::JITSymbolNotFound(std::string SymbolName)
std::error_code JITSymbolNotFound::convertToErrorCode() const {
typedef std::underlying_type<OrcErrorCode>::type UT;
return std::error_code(static_cast<UT>(OrcErrorCode::JITSymbolNotFound),
- *OrcErrCat);
+ getOrcErrCat());
}
void JITSymbolNotFound::log(raw_ostream &OS) const {
diff --git a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
index ffa2969536e7..8296b03398a0 100644
--- a/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
+++ b/llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
@@ -11,7 +11,6 @@
#include "llvm/ExecutionEngine/JITSymbol.h"
#include "llvm/Support/BinaryStreamReader.h"
#include "llvm/Support/FormatVariadic.h"
-#include "llvm/Support/ManagedStatic.h"
#include <cstdint>
#include <mutex>
@@ -67,9 +66,6 @@ LLVM_ATTRIBUTE_NOINLINE void __jit_debug_register_code() {
using namespace llvm;
using namespace llvm::orc;
-// Serialize rendezvous with the debugger as well as access to shared data.
-ManagedStatic<std::mutex> JITDebugLock;
-
// Register debug object, return error message or null for success.
static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
LLVM_DEBUG({
@@ -85,7 +81,9 @@ static void registerJITLoaderGDBImpl(const char *ObjAddr, size_t Size) {
E->symfile_size = Size;
E->prev_entry = nullptr;
- std::lock_guard<std::mutex> Lock(*JITDebugLock);
+ // Serialize rendezvous with the debugger as well as access to shared data.
+ static std::mutex JITDebugLock;
+ std::lock_guard<std::mutex> Lock(JITDebugLock);
// Insert this entry at the head of the list.
jit_code_entry *NextEntry = __jit_debug_descriptor.first_entry;
diff --git a/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp b/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
index 4a236e183c8b..bb41bac32534 100644
--- a/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
+++ b/llvm/lib/ExecutionEngine/PerfJITEvents/PerfJITEventListener.cpp
@@ -24,7 +24,6 @@
#include "llvm/Support/Debug.h"
#include "llvm/Support/Errno.h"
#include "llvm/Support/FileSystem.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Mutex.h"
#include "llvm/Support/Path.h"
@@ -488,15 +487,14 @@ void PerfJITEventListener::NotifyDebug(uint64_t CodeAddr,
}
}
-// There should be only a single event listener per process, otherwise perf gets
-// confused.
-llvm::ManagedStatic<PerfJITEventListener> PerfListener;
-
} // end anonymous namespace
namespace llvm {
JITEventListener *JITEventListener::createPerfJITEventListener() {
- return &*PerfListener;
+ // There should be only a single event listener per process, otherwise perf
+ // gets confused.
+ static PerfJITEventListener PerfListener;
+ return &PerfListener;
}
} // namespace llvm
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
index 2e0cba849165..54ab00732330 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyld.cpp
@@ -19,7 +19,6 @@
#include "llvm/Object/ELFObjectFile.h"
#include "llvm/Support/Alignment.h"
#include "llvm/Support/MSVCErrorWorkarounds.h"
-#include "llvm/Support/ManagedStatic.h"
#include "llvm/Support/MathExtras.h"
#include <mutex>
@@ -51,8 +50,6 @@ public:
}
};
-static ManagedStatic<RuntimeDyldErrorCategory> RTDyldErrorCategory;
-
}
char RuntimeDyldError::ID = 0;
@@ -62,7 +59,8 @@ void RuntimeDyldError::log(raw_ostream &OS) const {
}
std::error_code RuntimeDyldError::convertToErrorCode() const {
- return std::error_code(GenericRTDyldError, *RTDyldErrorCategory);
+ static RuntimeDyldErrorCategory RTDyldErrorCategory;
+ return std::error_code(GenericRTDyldError, RTDyldErrorCategory);
}
// Empty out-of-line virtual destructor as the key function.
diff --git a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
index da1102fc9f07..c702584b7a33 100644
--- a/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
+++ b/llvm/lib/ExecutionEngine/RuntimeDyld/RuntimeDyldELF.cpp
@@ -479,7 +479,7 @@ void RuntimeDyldELF::resolveAArch64Relocation(const SectionEntry &Section,
*TargetPtr &= 0xfff8001fU;
// Immediate:15:2 goes in bits 18:5 of TBZ, TBNZ
- or32le(TargetPtr, (BranchImm & 0x0FFFFFFC) << 3);
+ or32le(TargetPtr, (BranchImm & 0x0000FFFC) << 3);
break;
}
case ELF::R_AARCH64_CALL26: // fallthrough