aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/ExecutionEngine
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2022-07-27 20:11:54 +0000
committerDimitry Andric <dim@FreeBSD.org>2023-02-08 19:04:48 +0000
commit972a253a57b6f144b0e4a3e2080a2a0076ec55a0 (patch)
treea8aeeb0997a0a52500f1fa0644244206cf71df94 /contrib/llvm-project/llvm/lib/ExecutionEngine
parentfcaf7f8644a9988098ac6be2165bce3ea4786e91 (diff)
parent08e8dd7b9db7bb4a9de26d44c1cbfd24e869c014 (diff)
Diffstat (limited to 'contrib/llvm-project/llvm/lib/ExecutionEngine')
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp124
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h10
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp179
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h61
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp2
-rw-r--r--contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp38
6 files changed, 286 insertions, 128 deletions
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
index dc07eaeaf615..3a6162db75c4 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.cpp
@@ -18,13 +18,19 @@ static const char *CommonSectionName = "__common";
namespace llvm {
namespace jitlink {
+static Triple createTripleWithCOFFFormat(Triple T) {
+ T.setObjectFormat(Triple::COFF);
+ return T;
+}
+
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))) {
+ G(std::make_unique<LinkGraph>(Obj.getFileName().str(),
+ createTripleWithCOFFFormat(TT),
+ getPointerSize(Obj), getEndianness(Obj),
+ std::move(GetEdgeKindName))) {
LLVM_DEBUG({
dbgs() << "Created COFFLinkGraphBuilder for \"" << Obj.getFileName()
<< "\"\n";
@@ -128,16 +134,6 @@ Error COFFLinkGraphBuilder::graphifySections() {
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({
@@ -145,6 +141,8 @@ Error COFFLinkGraphBuilder::graphifySections() {
<< "Creating section for \"" << SectionName << "\"\n";
});
+ // FIXME: Revisit crash when dropping IMAGE_SCN_MEM_DISCARDABLE sections
+
// Get the section's memory protection flags.
MemProt Prot = MemProt::None;
if ((*Sec)->Characteristics & COFF::IMAGE_SCN_MEM_EXECUTE)
@@ -190,6 +188,7 @@ Error COFFLinkGraphBuilder::graphifySymbols() {
LLVM_DEBUG(dbgs() << " Creating graph symbols...\n");
SymbolSets.resize(Obj.getNumberOfSections() + 1);
+ PendingComdatExports.resize(Obj.getNumberOfSections() + 1);
GraphSymbols.resize(Obj.getNumberOfSymbols());
for (COFFSymbolIndex SymIndex = 0;
@@ -232,18 +231,16 @@ Error COFFLinkGraphBuilder::graphifySymbols() {
<< getCOFFSectionName(SectionIndex, Sec, *Sym)
<< " (index: " << SectionIndex << ") \n";
});
- GSym =
- &G->addExternalSymbol(SymbolName, Sym->getValue(), Linkage::Strong);
+ if (!ExternalSymbols.count(SymbolName))
+ ExternalSymbols[SymbolName] =
+ &G->addExternalSymbol(SymbolName, Sym->getValue(), Linkage::Strong);
+ GSym = ExternalSymbols[SymbolName];
} 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});
+ auto *WeakExternal = Sym->getAux<object::coff_aux_weak_external>();
+ COFFSymbolIndex TagIndex = WeakExternal->TagIndex;
+ uint32_t Characteristics = WeakExternal->Characteristics;
+ WeakExternalRequests.push_back(
+ {SymIndex, TagIndex, Characteristics, SymbolName});
} else {
Expected<jitlink::Symbol *> NewGSym =
createDefinedSymbol(SymIndex, SymbolName, *Sym, Sec);
@@ -279,35 +276,41 @@ Error COFFLinkGraphBuilder::graphifySymbols() {
Error COFFLinkGraphBuilder::flushWeakAliasRequests() {
// Export the weak external symbols and alias it
- for (auto &WeakAlias : WeakAliasRequests) {
- if (auto *Target = getGraphSymbol(WeakAlias.Target)) {
+ for (auto &WeakExternal : WeakExternalRequests) {
+ if (auto *Target = getGraphSymbol(WeakExternal.Target)) {
Expected<object::COFFSymbolRef> AliasSymbol =
- Obj.getSymbol(WeakAlias.Alias);
+ Obj.getSymbol(WeakExternal.Alias);
if (!AliasSymbol)
return AliasSymbol.takeError();
+ // FIXME: IMAGE_WEAK_EXTERN_SEARCH_NOLIBRARY and
+ // IMAGE_WEAK_EXTERN_SEARCH_LIBRARY are handled in the same way.
+ Scope S =
+ WeakExternal.Characteristics == COFF::IMAGE_WEAK_EXTERN_SEARCH_ALIAS
+ ? Scope::Default
+ : Scope::Local;
+
// 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,
+ Target->getBlock(), Target->getOffset(), WeakExternal.SymbolName,
+ Target->getSize(), Linkage::Weak, S, Target->isCallable(), false);
+ setGraphSymbol(AliasSymbol->getSectionNumber(), WeakExternal.Alias,
*NewSymbol);
LLVM_DEBUG({
- dbgs() << " " << WeakAlias.Alias
+ dbgs() << " " << WeakExternal.Alias
<< ": Creating weak external symbol for COFF symbol \""
- << WeakAlias.SymbolName << "\" in section "
+ << WeakExternal.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));
+ formatv("{0:d}", WeakExternal.Alias));
}
return Error::success();
}
@@ -324,6 +327,8 @@ Error COFFLinkGraphBuilder::calculateImplicitSizeOfSymbols() {
SecIndex <= static_cast<COFFSectionIndex>(Obj.getNumberOfSections());
SecIndex++) {
auto &SymbolSet = SymbolSets[SecIndex];
+ if (SymbolSet.empty())
+ continue;
jitlink::Block *B = getGraphBlock(SecIndex);
orc::ExecutorAddrDiff LastOffset = B->getSize();
orc::ExecutorAddrDiff LastDifferentOffset = B->getSize();
@@ -394,25 +399,35 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
formatv("{0:d}", SymIndex));
Block *B = getGraphBlock(Symbol.getSectionNumber());
+ if (!B) {
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Skipping graph symbol since section was not created for "
+ "COFF symbol \""
+ << SymbolName << "\" in section " << Symbol.getSectionNumber()
+ << "\n";
+ });
+ return nullptr;
+ }
+
if (Symbol.isExternal()) {
// This is not a comdat sequence, export the symbol as it is
- if (!isComdatSection(Section))
+ 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)
+ } else {
+ if (!PendingComdatExports[Symbol.getSectionNumber()])
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) {
+ if (Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_STATIC ||
+ Symbol.getStorageClass() == COFF::IMAGE_SYM_CLASS_LABEL) {
const object::coff_aux_section_definition *Definition =
Symbol.getSectionDefinition();
if (!Definition || !isComdatSection(Section)) {
@@ -422,12 +437,14 @@ Expected<Symbol *> COFFLinkGraphBuilder::createDefinedSymbol(
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(
+ auto Target = Definition->getNumber(Symbol.isBigObj());
+ auto GSym = &G->addDefinedSymbol(
*B, Symbol.getValue(), SymbolName, 0, Linkage::Strong, Scope::Local,
Symbol.getComplexType() == COFF::IMAGE_SYM_DTYPE_FUNCTION, false);
+ getGraphBlock(Target)->addEdge(Edge::KeepAlive, 0, *GSym, 0);
+ return GSym;
}
- if (PendingComdatExport)
+ if (PendingComdatExports[Symbol.getSectionNumber()])
return make_error<JITLinkError>(
"COMDAT export request already exists before symbol " +
formatv("{0:d}", SymIndex));
@@ -474,10 +491,16 @@ Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
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.");
+ // FIXME: Support IMAGE_COMDAT_SELECT_LARGEST properly when LinkGraph is
+ // able to handle this.
+ LLVM_DEBUG({
+ dbgs() << " " << SymIndex
+ << ": Partially supported IMAGE_COMDAT_SELECT_LARGEST was used"
+ " in section "
+ << Symbol.getSectionNumber() << "\n";
+ });
+ L = Linkage::Weak;
+ break;
}
case COFF::IMAGE_COMDAT_SELECT_NEWEST: {
// Even link.exe doesn't support this selection properly.
@@ -489,7 +512,7 @@ Expected<Symbol *> COFFLinkGraphBuilder::createCOMDATExportRequest(
formatv("{0:d}", Definition->Selection));
}
}
- PendingComdatExport = {SymIndex, Symbol.getSectionNumber(), L};
+ PendingComdatExports[Symbol.getSectionNumber()] = {SymIndex, L};
return &G->addAnonymousSymbol(*B, Symbol.getValue(), Definition->Length,
false, false);
}
@@ -499,6 +522,7 @@ Expected<Symbol *>
COFFLinkGraphBuilder::exportCOMDATSymbol(COFFSymbolIndex SymIndex,
StringRef SymbolName,
object::COFFSymbolRef Symbol) {
+ auto &PendingComdatExport = PendingComdatExports[Symbol.getSectionNumber()];
COFFSymbolIndex TargetIndex = PendingComdatExport->SymbolIndex;
Linkage L = PendingComdatExport->Linkage;
jitlink::Symbol *Target = getGraphSymbol(TargetIndex);
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
index 4dc1b14dc4a2..f925f6d7aeef 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFFLinkGraphBuilder.h
@@ -111,19 +111,19 @@ private:
// COMDAT sequence.
struct ComdatExportRequest {
COFFSymbolIndex SymbolIndex;
- COFFSectionIndex SectionIndex;
jitlink::Linkage Linkage;
};
- Optional<ComdatExportRequest> PendingComdatExport;
+ std::vector<Optional<ComdatExportRequest>> PendingComdatExports;
// This represents a pending request to create a weak external symbol with a
// name.
- struct WeakAliasRequest {
+ struct WeakExternalRequest {
COFFSymbolIndex Alias;
COFFSymbolIndex Target;
+ uint32_t Characteristics;
StringRef SymbolName;
};
- std::vector<WeakAliasRequest> WeakAliasRequests;
+ std::vector<WeakExternalRequest> WeakExternalRequests;
// Per COFF section jitlink symbol set sorted by offset.
// Used for calculating implicit size of defined symbols.
@@ -162,6 +162,8 @@ private:
Section *CommonSection = nullptr;
std::vector<Block *> GraphBlocks;
std::vector<Symbol *> GraphSymbols;
+
+ DenseMap<StringRef, Symbol *> ExternalSymbols;
};
template <typename RelocHandlerFunction>
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
index 3d36ad1ed767..e2040dc95acc 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp
@@ -12,8 +12,8 @@
#include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
#include "COFFLinkGraphBuilder.h"
-#include "EHFrameSupportImpl.h"
#include "JITLinkGeneric.h"
+#include "SEHFrameSupport.h"
#include "llvm/BinaryFormat/COFF.h"
#include "llvm/ExecutionEngine/JITLink/x86_64.h"
#include "llvm/Object/COFF.h"
@@ -26,6 +26,11 @@ using namespace llvm::jitlink;
namespace {
+enum EdgeKind_coff_x86_64 : Edge::Kind {
+ PCRel32 = x86_64::FirstPlatformRelocation,
+ Pointer32NB,
+};
+
class COFFJITLinker_x86_64 : public JITLinker<COFFJITLinker_x86_64> {
friend class JITLinker<COFFJITLinker_x86_64>;
@@ -43,27 +48,7 @@ private:
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())
@@ -74,21 +59,9 @@ private:
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()) {
@@ -110,62 +83,122 @@ private:
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;
+ const char *FixupPtr = BlockToFix.getContent().data() + Offset;
- switch (*RelocKind) {
- case COFFAddr32NB: {
- Kind = x86_64::Pointer32;
- Offset -= getImageBase();
+ switch (Rel.getType()) {
+ case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR32NB: {
+ Kind = EdgeKind_coff_x86_64::Pointer32NB;
+ Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
break;
}
- case COFFRel32: {
- Kind = x86_64::BranchPCRel32;
+ case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32: {
+ Kind = EdgeKind_coff_x86_64::PCRel32;
+ Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
break;
}
+ case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_1: {
+ Kind = EdgeKind_coff_x86_64::PCRel32;
+ Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
+ Addend -= 1;
+ break;
+ }
+ default: {
+ return make_error<JITLinkError>("Unsupported x86_64 relocation:" +
+ formatv("{0:d}", Rel.getType()));
+ }
};
Edge GE(Kind, Offset, *GraphSymbol, Addend);
LLVM_DEBUG({
dbgs() << " ";
- printEdge(dbgs(), BlockToFix, GE, x86_64::getEdgeKindName(Kind));
+ printEdge(dbgs(), BlockToFix, GE, getCOFFX86RelocationKindName(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), getCOFFX86RelocationKindName) {}
+};
+
+class COFFLinkGraphLowering_x86_64 {
+public:
+ // Lowers COFF x86_64 specific edges to generic x86_64 edges.
+ Error lowerCOFFRelocationEdges(LinkGraph &G, JITLinkContext &Ctx) {
+ for (auto *B : G.blocks()) {
+ for (auto &E : B->edges()) {
+ switch (E.getKind()) {
+ case EdgeKind_coff_x86_64::Pointer32NB: {
+ auto ImageBase = getImageBaseAddress(G, Ctx);
+ if (!ImageBase)
+ return ImageBase.takeError();
+ E.setAddend(E.getAddend() - *ImageBase);
+ E.setKind(x86_64::Pointer32);
+ break;
+ }
+ case EdgeKind_coff_x86_64::PCRel32: {
+ E.setKind(x86_64::PCRel32);
+ break;
+ }
+ default:
+ break;
+ }
+ }
}
+ return Error::success();
}
-public:
- COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T)
- : COFFLinkGraphBuilder(Obj, std::move(T), x86_64::getEdgeKindName) {}
+private:
+ static StringRef getImageBaseSymbolName() { return "__ImageBase"; }
+ Expected<JITTargetAddress> getImageBaseAddress(LinkGraph &G,
+ JITLinkContext &Ctx) {
+ if (this->ImageBase)
+ return this->ImageBase;
+ for (auto *S : G.defined_symbols())
+ if (S->getName() == getImageBaseSymbolName()) {
+ this->ImageBase = S->getAddress().getValue();
+ return this->ImageBase;
+ }
+
+ JITLinkContext::LookupMap Symbols;
+ Symbols[getImageBaseSymbolName()] = SymbolLookupFlags::RequiredSymbol;
+ JITTargetAddress ImageBase;
+ Error Err = Error::success();
+ Ctx.lookup(Symbols,
+ createLookupContinuation([&](Expected<AsyncLookupResult> LR) {
+ ErrorAsOutParameter EAO(&Err);
+ if (!LR) {
+ Err = LR.takeError();
+ return;
+ }
+ auto &ImageBaseSymbol = LR->begin()->second;
+ ImageBase = ImageBaseSymbol.getAddress();
+ }));
+ if (Err)
+ return std::move(Err);
+ this->ImageBase = ImageBase;
+ return ImageBase;
+ }
+ JITTargetAddress ImageBase = 0;
};
-Error buildTables_COFF_x86_64(LinkGraph &G) {
- LLVM_DEBUG(dbgs() << "Visiting edges in graph:\n");
+Error lowerEdges_COFF_x86_64(LinkGraph &G, JITLinkContext *Ctx) {
+ LLVM_DEBUG(dbgs() << "Lowering COFF x86_64 edges:\n");
+ COFFLinkGraphLowering_x86_64 GraphLowering;
+
+ if (auto Err = GraphLowering.lowerCOFFRelocationEdges(G, *Ctx))
+ return Err;
- x86_64::GOTTableManager GOT;
- x86_64::PLTTableManager PLT(GOT);
- visitExistingEdges(G, GOT, PLT);
return Error::success();
}
} // namespace
@@ -173,6 +206,18 @@ Error buildTables_COFF_x86_64(LinkGraph &G) {
namespace llvm {
namespace jitlink {
+/// Return the string name of the given COFF x86_64 edge kind.
+const char *getCOFFX86RelocationKindName(Edge::Kind R) {
+ switch (R) {
+ case PCRel32:
+ return "PCRel32";
+ case Pointer32NB:
+ return "Pointer32NB";
+ default:
+ return x86_64::getEdgeKindName(R);
+ }
+}
+
Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer) {
LLVM_DEBUG({
@@ -194,16 +239,16 @@ void link_COFF_x86_64(std::unique_ptr<LinkGraph> G,
const Triple &TT = G->getTargetTriple();
if (Ctx->shouldAddDefaultTargetPasses(TT)) {
// Add a mark-live pass.
- if (auto MarkLive = Ctx->getMarkLivePass(TT))
+ if (auto MarkLive = Ctx->getMarkLivePass(TT)) {
Config.PrePrunePasses.push_back(std::move(MarkLive));
- else
+ Config.PrePrunePasses.push_back(SEHFrameKeepAlivePass(".pdata"));
+ } 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);
+ // Add COFF edge lowering passes.
+ JITLinkContext *CtxPtr = Ctx.get();
+ Config.PreFixupPasses.push_back(
+ [CtxPtr](LinkGraph &G) { return lowerEdges_COFF_x86_64(G, CtxPtr); });
}
if (auto Err = Ctx->modifyPassConfig(*G, Config))
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h
new file mode 100644
index 000000000000..f7689e4e4043
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/SEHFrameSupport.h
@@ -0,0 +1,61 @@
+//===------- SEHFrameSupport.h - JITLink seh-frame utils --------*- 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
+//
+//===----------------------------------------------------------------------===//
+//
+// SEHFrame utils for JITLink.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H
+#define LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H
+
+#include "llvm/ADT/Triple.h"
+#include "llvm/ExecutionEngine/JITLink/JITLink.h"
+#include "llvm/ExecutionEngine/JITSymbol.h"
+#include "llvm/Support/Error.h"
+
+namespace llvm {
+namespace jitlink {
+/// This pass adds keep-alive edge from SEH frame sections
+/// to the parent function content block.
+class SEHFrameKeepAlivePass {
+public:
+ SEHFrameKeepAlivePass(StringRef SEHFrameSectionName)
+ : SEHFrameSectionName(SEHFrameSectionName) {}
+
+ Error operator()(LinkGraph &G) {
+ auto *S = G.findSectionByName(SEHFrameSectionName);
+ if (!S)
+ return Error::success();
+
+ // Simply consider every block pointed by seh frame block as parants.
+ // This adds some unnecessary keep-alive edges to unwind info blocks,
+ // (xdata) but these blocks are usually dead by default, so they wouldn't
+ // count for the fate of seh frame block.
+ for (auto *B : S->blocks()) {
+ auto &DummySymbol = G.addAnonymousSymbol(*B, 0, 0, false, false);
+ DenseSet<Block *> Children;
+ for (auto &E : B->edges()) {
+ auto &Sym = E.getTarget();
+ if (!Sym.isDefined())
+ continue;
+ Children.insert(&Sym.getBlock());
+ }
+ for (auto *Child : Children)
+ Child->addEdge(Edge(Edge::KeepAlive, 0, DummySymbol, 0));
+ }
+ return Error::success();
+ }
+
+private:
+ StringRef SEHFrameSectionName;
+};
+
+} // end namespace jitlink
+} // end namespace llvm
+
+#endif // LLVM_EXECUTIONENGINE_JITLINK_SEHFRAMESUPPORT_H \ No newline at end of file
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp
index df9979b47e88..393250a5578b 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/x86_64.cpp
@@ -36,6 +36,8 @@ const char *getEdgeKindName(Edge::Kind K) {
return "NegDelta32";
case Delta64FromGOT:
return "Delta64FromGOT";
+ case PCRel32:
+ return "PCRel32";
case BranchPCRel32:
return "BranchPCRel32";
case BranchPCRel32ToPtrJumpStub:
diff --git a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
index 356b81b4f1c5..3de15db3f1c6 100644
--- a/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
+++ b/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ObjectFileInterface.cpp
@@ -150,16 +150,39 @@ static Expected<MaterializationUnit::Interface>
getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
const object::COFFObjectFile &Obj) {
MaterializationUnit::Interface I;
-
+ std::vector<Optional<object::coff_aux_section_definition>> ComdatDefs(
+ Obj.getNumberOfSections() + 1);
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;
+ // Handle comdat symbols
+ auto COFFSym = Obj.getCOFFSymbol(Sym);
+ bool IsWeak = false;
+ if (auto *Def = COFFSym.getSectionDefinition()) {
+ auto Sec = Obj.getSection(COFFSym.getSectionNumber());
+ if (!Sec)
+ return Sec.takeError();
+ if (((*Sec)->Characteristics & COFF::IMAGE_SCN_LNK_COMDAT) &&
+ Def->Selection != COFF::IMAGE_COMDAT_SELECT_ASSOCIATIVE) {
+ ComdatDefs[COFFSym.getSectionNumber()] = *Def;
+ continue;
+ }
+ }
+ if (!COFF::isReservedSectionNumber(COFFSym.getSectionNumber()) &&
+ ComdatDefs[COFFSym.getSectionNumber()]) {
+ auto Def = ComdatDefs[COFFSym.getSectionNumber()];
+ if (Def->Selection != COFF::IMAGE_COMDAT_SELECT_NODUPLICATES) {
+ IsWeak = true;
+ }
+ ComdatDefs[COFFSym.getSectionNumber()] = None;
+ } else {
+ // 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))
@@ -180,12 +203,13 @@ getCOFFObjectFileSymbolInfo(ExecutionSession &ES,
if (!SymFlags)
return SymFlags.takeError();
*SymFlags |= JITSymbolFlags::Exported;
- auto COFFSym = Obj.getCOFFSymbol(Sym);
// Weak external is always a function
- if (COFFSym.isWeakExternal()) {
+ if (COFFSym.isWeakExternal())
*SymFlags |= JITSymbolFlags::Callable;
- }
+
+ if (IsWeak)
+ *SymFlags |= JITSymbolFlags::Weak;
I.SymbolFlags[ES.intern(*Name)] = std::move(*SymFlags);
}