xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/JITLink/COFF_x86_64.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
1753f127fSDimitry Andric //===----- COFF_x86_64.cpp - JIT linker implementation for COFF/x86_64 ----===//
2753f127fSDimitry Andric //
3753f127fSDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4753f127fSDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5753f127fSDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6753f127fSDimitry Andric //
7753f127fSDimitry Andric //===----------------------------------------------------------------------===//
8753f127fSDimitry Andric //
9753f127fSDimitry Andric // COFF/x86_64 jit-link implementation.
10753f127fSDimitry Andric //
11753f127fSDimitry Andric //===----------------------------------------------------------------------===//
12753f127fSDimitry Andric 
13753f127fSDimitry Andric #include "llvm/ExecutionEngine/JITLink/COFF_x86_64.h"
14753f127fSDimitry Andric #include "COFFLinkGraphBuilder.h"
15753f127fSDimitry Andric #include "JITLinkGeneric.h"
16972a253aSDimitry Andric #include "SEHFrameSupport.h"
17753f127fSDimitry Andric #include "llvm/BinaryFormat/COFF.h"
18753f127fSDimitry Andric #include "llvm/ExecutionEngine/JITLink/x86_64.h"
19753f127fSDimitry Andric #include "llvm/Object/COFF.h"
20753f127fSDimitry Andric #include "llvm/Support/Endian.h"
21753f127fSDimitry Andric 
22753f127fSDimitry Andric #define DEBUG_TYPE "jitlink"
23753f127fSDimitry Andric 
24753f127fSDimitry Andric using namespace llvm;
25753f127fSDimitry Andric using namespace llvm::jitlink;
26753f127fSDimitry Andric 
27753f127fSDimitry Andric namespace {
28753f127fSDimitry Andric 
29972a253aSDimitry Andric enum EdgeKind_coff_x86_64 : Edge::Kind {
30972a253aSDimitry Andric   PCRel32 = x86_64::FirstPlatformRelocation,
31972a253aSDimitry Andric   Pointer32NB,
32bdd1243dSDimitry Andric   Pointer64,
33bdd1243dSDimitry Andric   SectionIdx16,
34bdd1243dSDimitry Andric   SecRel32,
35972a253aSDimitry Andric };
36972a253aSDimitry Andric 
37753f127fSDimitry Andric class COFFJITLinker_x86_64 : public JITLinker<COFFJITLinker_x86_64> {
38753f127fSDimitry Andric   friend class JITLinker<COFFJITLinker_x86_64>;
39753f127fSDimitry Andric 
40753f127fSDimitry Andric public:
COFFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,std::unique_ptr<LinkGraph> G,PassConfiguration PassConfig)41753f127fSDimitry Andric   COFFJITLinker_x86_64(std::unique_ptr<JITLinkContext> Ctx,
42753f127fSDimitry Andric                        std::unique_ptr<LinkGraph> G,
43753f127fSDimitry Andric                        PassConfiguration PassConfig)
44753f127fSDimitry Andric       : JITLinker(std::move(Ctx), std::move(G), std::move(PassConfig)) {}
45753f127fSDimitry Andric 
46753f127fSDimitry Andric private:
applyFixup(LinkGraph & G,Block & B,const Edge & E) const47753f127fSDimitry Andric   Error applyFixup(LinkGraph &G, Block &B, const Edge &E) const {
48753f127fSDimitry Andric     return x86_64::applyFixup(G, B, E, nullptr);
49753f127fSDimitry Andric   }
50753f127fSDimitry Andric };
51753f127fSDimitry Andric 
52753f127fSDimitry Andric class COFFLinkGraphBuilder_x86_64 : public COFFLinkGraphBuilder {
53753f127fSDimitry Andric private:
addRelocations()54753f127fSDimitry Andric   Error addRelocations() override {
55753f127fSDimitry Andric     LLVM_DEBUG(dbgs() << "Processing relocations:\n");
56753f127fSDimitry Andric 
57753f127fSDimitry Andric     for (const auto &RelSect : sections())
58753f127fSDimitry Andric       if (Error Err = COFFLinkGraphBuilder::forEachRelocation(
59753f127fSDimitry Andric               RelSect, this, &COFFLinkGraphBuilder_x86_64::addSingleRelocation))
60753f127fSDimitry Andric         return Err;
61753f127fSDimitry Andric 
62753f127fSDimitry Andric     return Error::success();
63753f127fSDimitry Andric   }
64753f127fSDimitry Andric 
addSingleRelocation(const object::RelocationRef & Rel,const object::SectionRef & FixupSect,Block & BlockToFix)65753f127fSDimitry Andric   Error addSingleRelocation(const object::RelocationRef &Rel,
66753f127fSDimitry Andric                             const object::SectionRef &FixupSect,
67753f127fSDimitry Andric                             Block &BlockToFix) {
68753f127fSDimitry Andric     const object::coff_relocation *COFFRel = getObject().getCOFFRelocation(Rel);
69753f127fSDimitry Andric     auto SymbolIt = Rel.getSymbol();
70753f127fSDimitry Andric     if (SymbolIt == getObject().symbol_end()) {
71753f127fSDimitry Andric       return make_error<StringError>(
72753f127fSDimitry Andric           formatv("Invalid symbol index in relocation entry. "
73753f127fSDimitry Andric                   "index: {0}, section: {1}",
74753f127fSDimitry Andric                   COFFRel->SymbolTableIndex, FixupSect.getIndex()),
75753f127fSDimitry Andric           inconvertibleErrorCode());
76753f127fSDimitry Andric     }
77753f127fSDimitry Andric 
78753f127fSDimitry Andric     object::COFFSymbolRef COFFSymbol = getObject().getCOFFSymbol(*SymbolIt);
79753f127fSDimitry Andric     COFFSymbolIndex SymIndex = getObject().getSymbolIndex(COFFSymbol);
80753f127fSDimitry Andric 
81753f127fSDimitry Andric     Symbol *GraphSymbol = getGraphSymbol(SymIndex);
82753f127fSDimitry Andric     if (!GraphSymbol)
83753f127fSDimitry Andric       return make_error<StringError>(
84753f127fSDimitry Andric           formatv("Could not find symbol at given index, did you add it to "
85753f127fSDimitry Andric                   "JITSymbolTable? index: {0}, section: {1}",
86753f127fSDimitry Andric                   SymIndex, FixupSect.getIndex()),
87753f127fSDimitry Andric           inconvertibleErrorCode());
88753f127fSDimitry Andric 
89753f127fSDimitry Andric     int64_t Addend = 0;
90753f127fSDimitry Andric     orc::ExecutorAddr FixupAddress =
91753f127fSDimitry Andric         orc::ExecutorAddr(FixupSect.getAddress()) + Rel.getOffset();
92753f127fSDimitry Andric     Edge::OffsetT Offset = FixupAddress - BlockToFix.getAddress();
93753f127fSDimitry Andric 
94753f127fSDimitry Andric     Edge::Kind Kind = Edge::Invalid;
95972a253aSDimitry Andric     const char *FixupPtr = BlockToFix.getContent().data() + Offset;
96753f127fSDimitry Andric 
97972a253aSDimitry Andric     switch (Rel.getType()) {
98972a253aSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR32NB: {
99972a253aSDimitry Andric       Kind = EdgeKind_coff_x86_64::Pointer32NB;
100972a253aSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
101753f127fSDimitry Andric       break;
102753f127fSDimitry Andric     }
103972a253aSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32: {
104972a253aSDimitry Andric       Kind = EdgeKind_coff_x86_64::PCRel32;
105972a253aSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
106753f127fSDimitry Andric       break;
107753f127fSDimitry Andric     }
108972a253aSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_1: {
109972a253aSDimitry Andric       Kind = EdgeKind_coff_x86_64::PCRel32;
110972a253aSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
111972a253aSDimitry Andric       Addend -= 1;
112972a253aSDimitry Andric       break;
113972a253aSDimitry Andric     }
114bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_2: {
115bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::PCRel32;
116bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
117bdd1243dSDimitry Andric       Addend -= 2;
118bdd1243dSDimitry Andric       break;
119bdd1243dSDimitry Andric     }
120bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_3: {
121bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::PCRel32;
122bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
123bdd1243dSDimitry Andric       Addend -= 3;
124bdd1243dSDimitry Andric       break;
125bdd1243dSDimitry Andric     }
126bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_4: {
127bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::PCRel32;
128bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
129bdd1243dSDimitry Andric       Addend -= 4;
130bdd1243dSDimitry Andric       break;
131bdd1243dSDimitry Andric     }
132bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_REL32_5: {
133bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::PCRel32;
134bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
135bdd1243dSDimitry Andric       Addend -= 5;
136bdd1243dSDimitry Andric       break;
137bdd1243dSDimitry Andric     }
138bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_ADDR64: {
139bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::Pointer64;
140bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little64_t *>(FixupPtr);
141bdd1243dSDimitry Andric       break;
142bdd1243dSDimitry Andric     }
143bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_SECTION: {
144bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::SectionIdx16;
145bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little16_t *>(FixupPtr);
146bdd1243dSDimitry Andric       uint64_t SectionIdx = 0;
147bdd1243dSDimitry Andric       if (COFFSymbol.isAbsolute())
148bdd1243dSDimitry Andric         SectionIdx = getObject().getNumberOfSections() + 1;
149bdd1243dSDimitry Andric       else
150bdd1243dSDimitry Andric         SectionIdx = COFFSymbol.getSectionNumber();
151bdd1243dSDimitry Andric       auto *AbsSym = &getGraph().addAbsoluteSymbol(
152bdd1243dSDimitry Andric           "secidx", orc::ExecutorAddr(SectionIdx), 2, Linkage::Strong,
153bdd1243dSDimitry Andric           Scope::Local, false);
154bdd1243dSDimitry Andric       GraphSymbol = AbsSym;
155bdd1243dSDimitry Andric       break;
156bdd1243dSDimitry Andric     }
157bdd1243dSDimitry Andric     case COFF::RelocationTypeAMD64::IMAGE_REL_AMD64_SECREL: {
158bdd1243dSDimitry Andric       // FIXME: SECREL to external symbol should be handled
159bdd1243dSDimitry Andric       if (!GraphSymbol->isDefined())
160bdd1243dSDimitry Andric         return Error::success();
161bdd1243dSDimitry Andric       Kind = EdgeKind_coff_x86_64::SecRel32;
162bdd1243dSDimitry Andric       Addend = *reinterpret_cast<const support::little32_t *>(FixupPtr);
163bdd1243dSDimitry Andric       break;
164bdd1243dSDimitry Andric     }
165972a253aSDimitry Andric     default: {
166972a253aSDimitry Andric       return make_error<JITLinkError>("Unsupported x86_64 relocation:" +
167972a253aSDimitry Andric                                       formatv("{0:d}", Rel.getType()));
168972a253aSDimitry Andric     }
169753f127fSDimitry Andric     };
170753f127fSDimitry Andric 
171753f127fSDimitry Andric     Edge GE(Kind, Offset, *GraphSymbol, Addend);
172753f127fSDimitry Andric     LLVM_DEBUG({
173753f127fSDimitry Andric       dbgs() << "    ";
174972a253aSDimitry Andric       printEdge(dbgs(), BlockToFix, GE, getCOFFX86RelocationKindName(Kind));
175753f127fSDimitry Andric       dbgs() << "\n";
176753f127fSDimitry Andric     });
177753f127fSDimitry Andric 
178753f127fSDimitry Andric     BlockToFix.addEdge(std::move(GE));
179753f127fSDimitry Andric 
180972a253aSDimitry Andric     return Error::success();
181753f127fSDimitry Andric   }
182753f127fSDimitry Andric 
183753f127fSDimitry Andric public:
COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile & Obj,const Triple T,const SubtargetFeatures Features)184*06c3fb27SDimitry Andric   COFFLinkGraphBuilder_x86_64(const object::COFFObjectFile &Obj, const Triple T,
185*06c3fb27SDimitry Andric                               const SubtargetFeatures Features)
186*06c3fb27SDimitry Andric       : COFFLinkGraphBuilder(Obj, std::move(T), std::move(Features),
187*06c3fb27SDimitry Andric                              getCOFFX86RelocationKindName) {}
188753f127fSDimitry Andric };
189753f127fSDimitry Andric 
190972a253aSDimitry Andric class COFFLinkGraphLowering_x86_64 {
191972a253aSDimitry Andric public:
192972a253aSDimitry Andric   // Lowers COFF x86_64 specific edges to generic x86_64 edges.
lowerCOFFRelocationEdges(LinkGraph & G,JITLinkContext & Ctx)193972a253aSDimitry Andric   Error lowerCOFFRelocationEdges(LinkGraph &G, JITLinkContext &Ctx) {
194972a253aSDimitry Andric     for (auto *B : G.blocks()) {
195972a253aSDimitry Andric       for (auto &E : B->edges()) {
196972a253aSDimitry Andric         switch (E.getKind()) {
197972a253aSDimitry Andric         case EdgeKind_coff_x86_64::Pointer32NB: {
198972a253aSDimitry Andric           auto ImageBase = getImageBaseAddress(G, Ctx);
199972a253aSDimitry Andric           if (!ImageBase)
200972a253aSDimitry Andric             return ImageBase.takeError();
201*06c3fb27SDimitry Andric           E.setAddend(E.getAddend() - ImageBase->getValue());
202972a253aSDimitry Andric           E.setKind(x86_64::Pointer32);
203972a253aSDimitry Andric           break;
204972a253aSDimitry Andric         }
205972a253aSDimitry Andric         case EdgeKind_coff_x86_64::PCRel32: {
206972a253aSDimitry Andric           E.setKind(x86_64::PCRel32);
207972a253aSDimitry Andric           break;
208972a253aSDimitry Andric         }
209bdd1243dSDimitry Andric         case EdgeKind_coff_x86_64::Pointer64: {
210bdd1243dSDimitry Andric           E.setKind(x86_64::Pointer64);
211bdd1243dSDimitry Andric           break;
212bdd1243dSDimitry Andric         }
213bdd1243dSDimitry Andric         case EdgeKind_coff_x86_64::SectionIdx16: {
214bdd1243dSDimitry Andric           E.setKind(x86_64::Pointer16);
215bdd1243dSDimitry Andric           break;
216bdd1243dSDimitry Andric         }
217bdd1243dSDimitry Andric         case EdgeKind_coff_x86_64::SecRel32: {
218bdd1243dSDimitry Andric           E.setAddend(E.getAddend() -
219bdd1243dSDimitry Andric                       getSectionStart(E.getTarget().getBlock().getSection())
220bdd1243dSDimitry Andric                           .getValue());
221bdd1243dSDimitry Andric           E.setKind(x86_64::Pointer32);
222bdd1243dSDimitry Andric           break;
223bdd1243dSDimitry Andric         }
224972a253aSDimitry Andric         default:
225972a253aSDimitry Andric           break;
226972a253aSDimitry Andric         }
227972a253aSDimitry Andric       }
228972a253aSDimitry Andric     }
229972a253aSDimitry Andric     return Error::success();
230972a253aSDimitry Andric   }
231753f127fSDimitry Andric 
232972a253aSDimitry Andric private:
getImageBaseSymbolName()233972a253aSDimitry Andric   static StringRef getImageBaseSymbolName() { return "__ImageBase"; }
234bdd1243dSDimitry Andric 
getSectionStart(Section & Sec)235bdd1243dSDimitry Andric   orc::ExecutorAddr getSectionStart(Section &Sec) {
236bdd1243dSDimitry Andric     if (!SectionStartCache.count(&Sec)) {
237bdd1243dSDimitry Andric       SectionRange Range(Sec);
238bdd1243dSDimitry Andric       SectionStartCache[&Sec] = Range.getStart();
239bdd1243dSDimitry Andric     }
240bdd1243dSDimitry Andric     return SectionStartCache[&Sec];
241bdd1243dSDimitry Andric   }
242bdd1243dSDimitry Andric 
getImageBaseAddress(LinkGraph & G,JITLinkContext & Ctx)243*06c3fb27SDimitry Andric   Expected<orc::ExecutorAddr> getImageBaseAddress(LinkGraph &G,
244972a253aSDimitry Andric                                                   JITLinkContext &Ctx) {
245972a253aSDimitry Andric     if (this->ImageBase)
246972a253aSDimitry Andric       return this->ImageBase;
247972a253aSDimitry Andric     for (auto *S : G.defined_symbols())
248972a253aSDimitry Andric       if (S->getName() == getImageBaseSymbolName()) {
249*06c3fb27SDimitry Andric         this->ImageBase = S->getAddress();
250972a253aSDimitry Andric         return this->ImageBase;
251972a253aSDimitry Andric       }
252972a253aSDimitry Andric 
253972a253aSDimitry Andric     JITLinkContext::LookupMap Symbols;
254972a253aSDimitry Andric     Symbols[getImageBaseSymbolName()] = SymbolLookupFlags::RequiredSymbol;
255*06c3fb27SDimitry Andric     orc::ExecutorAddr ImageBase;
256972a253aSDimitry Andric     Error Err = Error::success();
257972a253aSDimitry Andric     Ctx.lookup(Symbols,
258972a253aSDimitry Andric                createLookupContinuation([&](Expected<AsyncLookupResult> LR) {
259972a253aSDimitry Andric                  ErrorAsOutParameter EAO(&Err);
260972a253aSDimitry Andric                  if (!LR) {
261972a253aSDimitry Andric                    Err = LR.takeError();
262972a253aSDimitry Andric                    return;
263972a253aSDimitry Andric                  }
264*06c3fb27SDimitry Andric                  ImageBase = LR->begin()->second.getAddress();
265972a253aSDimitry Andric                }));
266972a253aSDimitry Andric     if (Err)
267972a253aSDimitry Andric       return std::move(Err);
268972a253aSDimitry Andric     this->ImageBase = ImageBase;
269972a253aSDimitry Andric     return ImageBase;
270972a253aSDimitry Andric   }
271bdd1243dSDimitry Andric 
272bdd1243dSDimitry Andric   DenseMap<Section *, orc::ExecutorAddr> SectionStartCache;
273*06c3fb27SDimitry Andric   orc::ExecutorAddr ImageBase;
274972a253aSDimitry Andric };
275972a253aSDimitry Andric 
lowerEdges_COFF_x86_64(LinkGraph & G,JITLinkContext * Ctx)276972a253aSDimitry Andric Error lowerEdges_COFF_x86_64(LinkGraph &G, JITLinkContext *Ctx) {
277972a253aSDimitry Andric   LLVM_DEBUG(dbgs() << "Lowering COFF x86_64 edges:\n");
278972a253aSDimitry Andric   COFFLinkGraphLowering_x86_64 GraphLowering;
279972a253aSDimitry Andric 
280972a253aSDimitry Andric   if (auto Err = GraphLowering.lowerCOFFRelocationEdges(G, *Ctx))
281972a253aSDimitry Andric     return Err;
282972a253aSDimitry Andric 
283753f127fSDimitry Andric   return Error::success();
284753f127fSDimitry Andric }
285753f127fSDimitry Andric } // namespace
286753f127fSDimitry Andric 
287753f127fSDimitry Andric namespace llvm {
288753f127fSDimitry Andric namespace jitlink {
289753f127fSDimitry Andric 
290972a253aSDimitry Andric /// Return the string name of the given COFF x86_64 edge kind.
getCOFFX86RelocationKindName(Edge::Kind R)291972a253aSDimitry Andric const char *getCOFFX86RelocationKindName(Edge::Kind R) {
292972a253aSDimitry Andric   switch (R) {
293972a253aSDimitry Andric   case PCRel32:
294972a253aSDimitry Andric     return "PCRel32";
295972a253aSDimitry Andric   case Pointer32NB:
296972a253aSDimitry Andric     return "Pointer32NB";
297bdd1243dSDimitry Andric   case Pointer64:
298bdd1243dSDimitry Andric     return "Pointer64";
299bdd1243dSDimitry Andric   case SectionIdx16:
300bdd1243dSDimitry Andric     return "SectionIdx16";
301bdd1243dSDimitry Andric   case SecRel32:
302bdd1243dSDimitry Andric     return "SecRel32";
303972a253aSDimitry Andric   default:
304972a253aSDimitry Andric     return x86_64::getEdgeKindName(R);
305972a253aSDimitry Andric   }
306972a253aSDimitry Andric }
307972a253aSDimitry Andric 
308753f127fSDimitry Andric Expected<std::unique_ptr<LinkGraph>>
createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer)309753f127fSDimitry Andric createLinkGraphFromCOFFObject_x86_64(MemoryBufferRef ObjectBuffer) {
310753f127fSDimitry Andric   LLVM_DEBUG({
311753f127fSDimitry Andric     dbgs() << "Building jitlink graph for new input "
312753f127fSDimitry Andric            << ObjectBuffer.getBufferIdentifier() << "...\n";
313753f127fSDimitry Andric   });
314753f127fSDimitry Andric 
315753f127fSDimitry Andric   auto COFFObj = object::ObjectFile::createCOFFObjectFile(ObjectBuffer);
316753f127fSDimitry Andric   if (!COFFObj)
317753f127fSDimitry Andric     return COFFObj.takeError();
318753f127fSDimitry Andric 
319*06c3fb27SDimitry Andric   auto Features = (*COFFObj)->getFeatures();
320*06c3fb27SDimitry Andric   if (!Features)
321*06c3fb27SDimitry Andric     return Features.takeError();
322*06c3fb27SDimitry Andric 
323*06c3fb27SDimitry Andric   return COFFLinkGraphBuilder_x86_64(**COFFObj, (*COFFObj)->makeTriple(),
324*06c3fb27SDimitry Andric                                      std::move(*Features))
325753f127fSDimitry Andric       .buildGraph();
326753f127fSDimitry Andric }
327753f127fSDimitry Andric 
link_COFF_x86_64(std::unique_ptr<LinkGraph> G,std::unique_ptr<JITLinkContext> Ctx)328753f127fSDimitry Andric void link_COFF_x86_64(std::unique_ptr<LinkGraph> G,
329753f127fSDimitry Andric                       std::unique_ptr<JITLinkContext> Ctx) {
330753f127fSDimitry Andric   PassConfiguration Config;
331753f127fSDimitry Andric   const Triple &TT = G->getTargetTriple();
332753f127fSDimitry Andric   if (Ctx->shouldAddDefaultTargetPasses(TT)) {
333753f127fSDimitry Andric     // Add a mark-live pass.
334972a253aSDimitry Andric     if (auto MarkLive = Ctx->getMarkLivePass(TT)) {
335753f127fSDimitry Andric       Config.PrePrunePasses.push_back(std::move(MarkLive));
336972a253aSDimitry Andric       Config.PrePrunePasses.push_back(SEHFrameKeepAlivePass(".pdata"));
337972a253aSDimitry Andric     } else
338753f127fSDimitry Andric       Config.PrePrunePasses.push_back(markAllSymbolsLive);
339753f127fSDimitry Andric 
340972a253aSDimitry Andric     // Add COFF edge lowering passes.
341972a253aSDimitry Andric     JITLinkContext *CtxPtr = Ctx.get();
342972a253aSDimitry Andric     Config.PreFixupPasses.push_back(
343972a253aSDimitry Andric         [CtxPtr](LinkGraph &G) { return lowerEdges_COFF_x86_64(G, CtxPtr); });
344753f127fSDimitry Andric   }
345753f127fSDimitry Andric 
346753f127fSDimitry Andric   if (auto Err = Ctx->modifyPassConfig(*G, Config))
347753f127fSDimitry Andric     return Ctx->notifyFailed(std::move(Err));
348753f127fSDimitry Andric 
349753f127fSDimitry Andric   COFFJITLinker_x86_64::link(std::move(Ctx), std::move(G), std::move(Config));
350753f127fSDimitry Andric }
351753f127fSDimitry Andric 
352753f127fSDimitry Andric } // namespace jitlink
353753f127fSDimitry Andric } // namespace llvm
354