1//===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
10#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"
11#include "llvm/ExecutionEngine/Orc/Layer.h"
12#include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
13#include "llvm/ExecutionEngine/Orc/MachO.h"
14#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
15#include "llvm/ExecutionEngine/Orc/SymbolStringPool.h"
16#include "llvm/IR/Constants.h"
17#include "llvm/IR/Function.h"
18#include "llvm/IR/GlobalVariable.h"
19#include "llvm/IR/Module.h"
20#include "llvm/Object/MachOUniversal.h"
21#include "llvm/Target/TargetMachine.h"
22#include <string>
23
24namespace llvm {
25namespace orc {
26
27CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
28 : InitList(
29 GV ? dyn_cast_or_null<ConstantArray>(Val: GV->getInitializer()) : nullptr),
30 I((InitList && End) ? InitList->getNumOperands() : 0) {
31}
32
33bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
34 assert(InitList == Other.InitList && "Incomparable iterators.");
35 return I == Other.I;
36}
37
38bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
39 return !(*this == Other);
40}
41
42CtorDtorIterator& CtorDtorIterator::operator++() {
43 ++I;
44 return *this;
45}
46
47CtorDtorIterator CtorDtorIterator::operator++(int) {
48 CtorDtorIterator Temp = *this;
49 ++I;
50 return Temp;
51}
52
53CtorDtorIterator::Element CtorDtorIterator::operator*() const {
54 ConstantStruct *CS = dyn_cast<ConstantStruct>(Val: InitList->getOperand(i_nocapture: I));
55 assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
56
57 Constant *FuncC = CS->getOperand(i_nocapture: 1);
58 Function *Func = nullptr;
59
60 // Extract function pointer, pulling off any casts.
61 while (FuncC) {
62 if (Function *F = dyn_cast_or_null<Function>(Val: FuncC)) {
63 Func = F;
64 break;
65 } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(Val: FuncC)) {
66 if (CE->isCast())
67 FuncC = CE->getOperand(i_nocapture: 0);
68 else
69 break;
70 } else {
71 // This isn't anything we recognize. Bail out with Func left set to null.
72 break;
73 }
74 }
75
76 auto *Priority = cast<ConstantInt>(Val: CS->getOperand(i_nocapture: 0));
77 Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(i_nocapture: 2) : nullptr;
78 if (Data && !isa<GlobalValue>(Val: Data))
79 Data = nullptr;
80 return Element(Priority->getZExtValue(), Func, Data);
81}
82
83iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
84 const GlobalVariable *CtorsList = M.getNamedGlobal(Name: "llvm.global_ctors");
85 return make_range(x: CtorDtorIterator(CtorsList, false),
86 y: CtorDtorIterator(CtorsList, true));
87}
88
89iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
90 const GlobalVariable *DtorsList = M.getNamedGlobal(Name: "llvm.global_dtors");
91 return make_range(x: CtorDtorIterator(DtorsList, false),
92 y: CtorDtorIterator(DtorsList, true));
93}
94
95bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) {
96 if (GV.isDeclaration())
97 return false;
98
99 if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||
100 GV.getName() == "llvm.global_dtors"))
101 return true;
102
103 if (ObjFmt == Triple::MachO) {
104 // FIXME: These section checks are too strict: We should match first and
105 // second word split by comma.
106 if (GV.hasSection() &&
107 (GV.getSection().starts_with(Prefix: "__DATA,__objc_classlist") ||
108 GV.getSection().starts_with(Prefix: "__DATA,__objc_selrefs")))
109 return true;
110 }
111
112 return false;
113}
114
115void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {
116 if (CtorDtors.empty())
117 return;
118
119 MangleAndInterner Mangle(
120 JD.getExecutionSession(),
121 (*CtorDtors.begin()).Func->getDataLayout());
122
123 for (auto CtorDtor : CtorDtors) {
124 assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
125 "Ctor/Dtor function must be named to be runnable under the JIT");
126
127 // FIXME: Maybe use a symbol promoter here instead.
128 if (CtorDtor.Func->hasLocalLinkage()) {
129 CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
130 CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
131 }
132
133 if (CtorDtor.Data && cast<GlobalValue>(Val: CtorDtor.Data)->isDeclaration())
134 continue;
135
136 CtorDtorsByPriority[CtorDtor.Priority].push_back(
137 x: Mangle(CtorDtor.Func->getName()));
138 }
139}
140
141Error CtorDtorRunner::run() {
142 using CtorDtorTy = void (*)();
143
144 SymbolLookupSet LookupSet;
145 for (auto &KV : CtorDtorsByPriority)
146 for (auto &Name : KV.second)
147 LookupSet.add(Name);
148 assert(!LookupSet.containsDuplicates() &&
149 "Ctor/Dtor list contains duplicates");
150
151 auto &ES = JD.getExecutionSession();
152 if (auto CtorDtorMap = ES.lookup(
153 SearchOrder: makeJITDylibSearchOrder(JDs: &JD, Flags: JITDylibLookupFlags::MatchAllSymbols),
154 Symbols: std::move(LookupSet))) {
155 for (auto &KV : CtorDtorsByPriority) {
156 for (auto &Name : KV.second) {
157 assert(CtorDtorMap->count(Name) && "No entry for Name");
158 auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>();
159 CtorDtor();
160 }
161 }
162 CtorDtorsByPriority.clear();
163 return Error::success();
164 } else
165 return CtorDtorMap.takeError();
166}
167
168void LocalCXXRuntimeOverridesBase::runDestructors() {
169 auto& CXXDestructorDataPairs = DSOHandleOverride;
170 for (auto &P : CXXDestructorDataPairs)
171 P.first(P.second);
172 CXXDestructorDataPairs.clear();
173}
174
175int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
176 void *Arg,
177 void *DSOHandle) {
178 auto& CXXDestructorDataPairs =
179 *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
180 CXXDestructorDataPairs.push_back(x: std::make_pair(x&: Destructor, y&: Arg));
181 return 0;
182}
183
184Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
185 MangleAndInterner &Mangle) {
186 SymbolMap RuntimeInterposes;
187 RuntimeInterposes[Mangle("__dso_handle")] = {
188 ExecutorAddr::fromPtr(Ptr: &DSOHandleOverride), JITSymbolFlags::Exported};
189 RuntimeInterposes[Mangle("__cxa_atexit")] = {
190 ExecutorAddr::fromPtr(Ptr: &CXAAtExitOverride), JITSymbolFlags::Exported};
191
192 return JD.define(MU: absoluteSymbols(Symbols: std::move(RuntimeInterposes)));
193}
194
195void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx,
196 void *DSOHandle) {
197 std::lock_guard<std::mutex> Lock(AtExitsMutex);
198 AtExitRecords[DSOHandle].push_back(x: {.F: F, .Ctx: Ctx});
199}
200
201void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
202 std::vector<AtExitRecord> AtExitsToRun;
203
204 {
205 std::lock_guard<std::mutex> Lock(AtExitsMutex);
206 auto I = AtExitRecords.find(Val: DSOHandle);
207 if (I != AtExitRecords.end()) {
208 AtExitsToRun = std::move(I->second);
209 AtExitRecords.erase(I);
210 }
211 }
212
213 while (!AtExitsToRun.empty()) {
214 AtExitsToRun.back().F(AtExitsToRun.back().Ctx);
215 AtExitsToRun.pop_back();
216 }
217}
218
219DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
220 sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow,
221 AddAbsoluteSymbolsFn AddAbsoluteSymbols)
222 : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
223 AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)),
224 GlobalPrefix(GlobalPrefix) {}
225
226Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
227DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
228 SymbolPredicate Allow,
229 AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
230 std::string ErrMsg;
231 auto Lib = sys::DynamicLibrary::getPermanentLibrary(filename: FileName, errMsg: &ErrMsg);
232 if (!Lib.isValid())
233 return make_error<StringError>(Args: std::move(ErrMsg), Args: inconvertibleErrorCode());
234 return std::make_unique<DynamicLibrarySearchGenerator>(
235 args: std::move(Lib), args&: GlobalPrefix, args: std::move(Allow),
236 args: std::move(AddAbsoluteSymbols));
237}
238
239Error DynamicLibrarySearchGenerator::tryToGenerate(
240 LookupState &LS, LookupKind K, JITDylib &JD,
241 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
242 orc::SymbolMap NewSymbols;
243
244 bool HasGlobalPrefix = (GlobalPrefix != '\0');
245
246 for (auto &KV : Symbols) {
247 auto &Name = KV.first;
248
249 if ((*Name).empty())
250 continue;
251
252 if (Allow && !Allow(Name))
253 continue;
254
255 if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
256 continue;
257
258 std::string Tmp((*Name).data() + HasGlobalPrefix,
259 (*Name).size() - HasGlobalPrefix);
260 if (void *P = Dylib.getAddressOfSymbol(symbolName: Tmp.c_str()))
261 NewSymbols[Name] = {ExecutorAddr::fromPtr(Ptr: P), JITSymbolFlags::Exported};
262 }
263
264 if (NewSymbols.empty())
265 return Error::success();
266
267 if (AddAbsoluteSymbols)
268 return AddAbsoluteSymbols(JD, std::move(NewSymbols));
269 return JD.define(MU: absoluteSymbols(Symbols: std::move(NewSymbols)));
270}
271
272StaticLibraryDefinitionGenerator::VisitMembersFunction
273StaticLibraryDefinitionGenerator::loadAllObjectFileMembers(ObjectLayer &L,
274 JITDylib &JD) {
275 return [&](object::Archive &A, MemoryBufferRef Buf,
276 size_t Index) -> Expected<bool> {
277 switch (identify_magic(magic: Buf.getBuffer())) {
278 case file_magic::elf_relocatable:
279 case file_magic::macho_object:
280 case file_magic::coff_object:
281 if (auto Err = L.add(JD, O: createMemberBuffer(A, BufRef: Buf, Index)))
282 return std::move(Err);
283 // Since we've loaded it already, mark this as not loadable.
284 return false;
285 default:
286 // Non-object-file members are not loadable.
287 return false;
288 }
289 };
290}
291
292Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
293StaticLibraryDefinitionGenerator::Load(
294 ObjectLayer &L, const char *FileName, VisitMembersFunction VisitMembers,
295 GetObjectFileInterface GetObjFileInterface) {
296
297 const auto &TT = L.getExecutionSession().getTargetTriple();
298 auto Linkable = loadLinkableFile(Path: FileName, TT, LA: LoadArchives::Required);
299 if (!Linkable)
300 return Linkable.takeError();
301
302 return Create(L, ArchiveBuffer: std::move(Linkable->first), VisitMembers: std::move(VisitMembers),
303 GetObjFileInterface: std::move(GetObjFileInterface));
304}
305
306Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
307StaticLibraryDefinitionGenerator::Create(
308 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
309 std::unique_ptr<object::Archive> Archive, VisitMembersFunction VisitMembers,
310 GetObjectFileInterface GetObjFileInterface) {
311
312 DenseSet<uint64_t> Excluded;
313
314 if (VisitMembers) {
315 size_t Index = 0;
316 Error Err = Error::success();
317 for (auto Child : Archive->children(Err)) {
318 if (auto ChildBuf = Child.getMemoryBufferRef()) {
319 if (auto Loadable = VisitMembers(*Archive, *ChildBuf, Index++)) {
320 if (!*Loadable)
321 Excluded.insert(V: Child.getDataOffset());
322 } else
323 return Loadable.takeError();
324 } else {
325 // We silently allow non-object archive members. This matches the
326 // behavior of ld.
327 consumeError(Err: ChildBuf.takeError());
328 }
329 }
330 if (Err)
331 return std::move(Err);
332 }
333
334 DenseMap<SymbolStringPtr, size_t> SymbolToMemberIndexMap;
335 {
336 DenseMap<uint64_t, size_t> OffsetToIndex;
337 size_t Index = 0;
338 Error Err = Error::success();
339 for (auto &Child : Archive->children(Err)) {
340 // For all members not excluded above, add them to the OffsetToIndex map.
341 if (!Excluded.count(V: Child.getDataOffset()))
342 OffsetToIndex[Child.getDataOffset()] = Index;
343 ++Index;
344 }
345 if (Err)
346 return Err;
347
348 auto &ES = L.getExecutionSession();
349 for (auto &Sym : Archive->symbols()) {
350 auto Member = Sym.getMember();
351 if (!Member)
352 return Member.takeError();
353 auto EntryItr = OffsetToIndex.find(Val: Member->getDataOffset());
354
355 // Missing entry means this member should be ignored.
356 if (EntryItr == OffsetToIndex.end())
357 continue;
358
359 SymbolToMemberIndexMap[ES.intern(SymName: Sym.getName())] = EntryItr->second;
360 }
361 }
362
363 return std::unique_ptr<StaticLibraryDefinitionGenerator>(
364 new StaticLibraryDefinitionGenerator(
365 L, std::move(ArchiveBuffer), std::move(Archive),
366 std::move(GetObjFileInterface), std::move(SymbolToMemberIndexMap)));
367}
368
369Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
370StaticLibraryDefinitionGenerator::Create(
371 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
372 VisitMembersFunction VisitMembers,
373 GetObjectFileInterface GetObjFileInterface) {
374
375 auto B = object::createBinary(Source: ArchiveBuffer->getMemBufferRef());
376 if (!B)
377 return B.takeError();
378
379 // If this is a regular archive then create an instance from it.
380 if (isa<object::Archive>(Val: *B))
381 return Create(L, ArchiveBuffer: std::move(ArchiveBuffer),
382 Archive: std::unique_ptr<object::Archive>(
383 static_cast<object::Archive *>(B->release())),
384 VisitMembers: std::move(VisitMembers), GetObjFileInterface: std::move(GetObjFileInterface));
385
386 // If this is a universal binary then search for a slice matching the given
387 // Triple.
388 if (auto *UB = dyn_cast<object::MachOUniversalBinary>(Val: B->get())) {
389
390 const auto &TT = L.getExecutionSession().getTargetTriple();
391
392 auto SliceRange = getMachOSliceRangeForTriple(UB&: *UB, TT);
393 if (!SliceRange)
394 return SliceRange.takeError();
395
396 MemoryBufferRef SliceRef(
397 StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first,
398 SliceRange->second),
399 ArchiveBuffer->getBufferIdentifier());
400
401 auto Archive = object::Archive::create(Source: SliceRef);
402 if (!Archive)
403 return Archive.takeError();
404
405 return Create(L, ArchiveBuffer: std::move(ArchiveBuffer), Archive: std::move(*Archive),
406 VisitMembers: std::move(VisitMembers), GetObjFileInterface: std::move(GetObjFileInterface));
407 }
408
409 return make_error<StringError>(Args: Twine("Unrecognized file type for ") +
410 ArchiveBuffer->getBufferIdentifier(),
411 Args: inconvertibleErrorCode());
412}
413
414Error StaticLibraryDefinitionGenerator::tryToGenerate(
415 LookupState &LS, LookupKind K, JITDylib &JD,
416 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
417 // Don't materialize symbols from static archives unless this is a static
418 // lookup.
419 if (K != LookupKind::Static)
420 return Error::success();
421
422 // Bail out early if we've already freed the archive.
423 if (!Archive)
424 return Error::success();
425
426 DenseMap<size_t, MemoryBufferRef> ToLoad;
427
428 for (const auto &[Name, _] : Symbols) {
429 // Check whehter the archive contains this symbol.
430 auto It = SymbolToMemberIndexMap.find(Val: Name);
431 if (It == SymbolToMemberIndexMap.end())
432 continue;
433 size_t Index = It->second;
434
435 // If we're already loading the member containing this symbol then we're
436 // done.
437 if (ToLoad.count(Val: Index))
438 continue;
439
440 auto Member = Archive->findSym(name: *Name);
441 if (!Member)
442 return Member.takeError();
443 if (!*Member) // Skip "none" children.
444 continue;
445
446 auto MemberBuf = (*Member)->getMemoryBufferRef();
447 if (!MemberBuf)
448 return MemberBuf.takeError();
449
450 ToLoad[Index] = *MemberBuf;
451 }
452
453 // Remove symbols to be loaded.
454 {
455 // FIXME: Enable DenseMap removal using NonOwningSymbolStringPtr?
456 std::vector<SymbolStringPtr> ToRemove;
457 for (auto &[Name, Index] : SymbolToMemberIndexMap)
458 if (ToLoad.count(Val: Index))
459 ToRemove.push_back(x: Name);
460 for (auto &Name : ToRemove)
461 SymbolToMemberIndexMap.erase(Val: Name);
462 }
463
464 // Add loaded files to JITDylib.
465 for (auto &[Index, Buf] : ToLoad) {
466 auto MemberBuf = createMemberBuffer(A&: *Archive, BufRef: Buf, Index);
467
468 auto Interface = GetObjFileInterface(L.getExecutionSession(),
469 MemberBuf->getMemBufferRef());
470 if (!Interface)
471 return Interface.takeError();
472
473 if (auto Err = L.add(JD, O: std::move(MemberBuf), I: std::move(*Interface)))
474 return Err;
475 }
476
477 return Error::success();
478}
479
480std::unique_ptr<MemoryBuffer>
481StaticLibraryDefinitionGenerator::createMemberBuffer(object::Archive &A,
482 MemoryBufferRef BufRef,
483 size_t Index) {
484 return MemoryBuffer::getMemBuffer(InputData: BufRef.getBuffer(),
485 BufferName: (A.getFileName() + "[" + Twine(Index) +
486 "](" + BufRef.getBufferIdentifier() + ")")
487 .str(),
488 RequiresNullTerminator: false);
489}
490
491StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
492 ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
493 std::unique_ptr<object::Archive> Archive,
494 GetObjectFileInterface GetObjFileInterface,
495 DenseMap<SymbolStringPtr, size_t> SymbolToMemberIndexMap)
496 : L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
497 ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)),
498 SymbolToMemberIndexMap(std::move(SymbolToMemberIndexMap)) {
499 if (!this->GetObjFileInterface)
500 this->GetObjFileInterface = getObjectFileInterface;
501}
502
503std::unique_ptr<DLLImportDefinitionGenerator>
504DLLImportDefinitionGenerator::Create(ExecutionSession &ES,
505 ObjectLinkingLayer &L) {
506 return std::unique_ptr<DLLImportDefinitionGenerator>(
507 new DLLImportDefinitionGenerator(ES, L));
508}
509
510Error DLLImportDefinitionGenerator::tryToGenerate(
511 LookupState &LS, LookupKind K, JITDylib &JD,
512 JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
513 JITDylibSearchOrder LinkOrder;
514 JD.withLinkOrderDo(F: [&](const JITDylibSearchOrder &LO) {
515 LinkOrder.reserve(n: LO.size());
516 for (auto &KV : LO) {
517 if (KV.first == &JD)
518 continue;
519 LinkOrder.push_back(x: KV);
520 }
521 });
522
523 // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
524 // both __imp_ and stripped name and use the lookup information to resolve the
525 // real symbol name.
526 SymbolLookupSet LookupSet;
527 DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols;
528 for (auto &KV : Symbols) {
529 StringRef Deinterned = *KV.first;
530 if (Deinterned.starts_with(Prefix: getImpPrefix()))
531 Deinterned = Deinterned.drop_front(N: StringRef(getImpPrefix()).size());
532 // Don't degrade the required state
533 auto [It, Inserted] = ToLookUpSymbols.try_emplace(Key: Deinterned);
534 if (Inserted || It->second != SymbolLookupFlags::RequiredSymbol)
535 It->second = KV.second;
536 }
537
538 for (auto &KV : ToLookUpSymbols)
539 LookupSet.add(Name: ES.intern(SymName: KV.first), Flags: KV.second);
540
541 auto Resolved = ES.lookup(SearchOrder: LinkOrder, Symbols: LookupSet, K: LookupKind::Static,
542 RequiredState: SymbolState::Resolved);
543 if (!Resolved)
544 return Resolved.takeError();
545
546 auto G = createStubsGraph(Resolved: *Resolved);
547 if (!G)
548 return G.takeError();
549 return L.add(JD, G: std::move(*G));
550}
551
552Expected<std::unique_ptr<jitlink::LinkGraph>>
553DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
554 Triple TT = ES.getTargetTriple();
555
556 auto CreatePointer = jitlink::getAnonymousPointerCreator(TT);
557 if (!CreatePointer)
558 return make_error<StringError>(
559 Args: "DLLImportDefinitionGenerator: no pointer creator for " + TT.str(),
560 Args: inconvertibleErrorCode());
561
562 auto CreateStub = jitlink::getPointerJumpStubCreator(TT);
563 if (!CreateStub)
564 return make_error<StringError>(
565 Args: "DLLImportDefinitionGenerator: no stub creator for " + TT.str(),
566 Args: inconvertibleErrorCode());
567
568 auto G = std::make_unique<jitlink::LinkGraph>(
569 args: "<DLLIMPORT_STUBS>", args: ES.getSymbolStringPool(), args&: TT, args: SubtargetFeatures(),
570 args&: jitlink::getGenericEdgeKindName);
571 jitlink::Section &Sec =
572 G->createSection(Name: getSectionName(), Prot: MemProt::Read | MemProt::Exec);
573
574 for (auto &KV : Resolved) {
575 jitlink::Symbol &Target = G->addAbsoluteSymbol(
576 Name: *KV.first, Address: KV.second.getAddress(), Size: G->getPointerSize(),
577 L: jitlink::Linkage::Strong, S: jitlink::Scope::Local, IsLive: false);
578
579 // Create __imp_ symbol
580 jitlink::Symbol &Ptr = CreatePointer(*G, Sec, &Target, 0);
581 Ptr.setName(G->intern(SymbolName: (Twine(getImpPrefix()) + *KV.first).str()));
582 Ptr.setLinkage(jitlink::Linkage::Strong);
583 Ptr.setScope(jitlink::Scope::Default);
584
585 // Create PLT stub
586 // FIXME: check PLT stub of data symbol is not accessed
587 jitlink::Symbol &Stub = CreateStub(*G, Sec, Ptr);
588 Stub.setName(G->intern(SymbolName: *KV.first));
589 Stub.setLinkage(jitlink::Linkage::Strong);
590 Stub.setScope(jitlink::Scope::Default);
591 }
592
593 return std::move(G);
594}
595
596} // End namespace orc.
597} // End namespace llvm.
598