xref: /freebsd/contrib/llvm-project/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
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/JITLink/x86_64.h"
11 #include "llvm/ExecutionEngine/Orc/Layer.h"
12 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
13 #include "llvm/IR/Constants.h"
14 #include "llvm/IR/Function.h"
15 #include "llvm/IR/GlobalVariable.h"
16 #include "llvm/IR/Module.h"
17 #include "llvm/MC/TargetRegistry.h"
18 #include "llvm/Object/MachOUniversal.h"
19 #include "llvm/Support/FormatVariadic.h"
20 #include "llvm/Support/StringSaver.h"
21 #include "llvm/Target/TargetMachine.h"
22 #include <string>
23 
24 namespace llvm {
25 namespace orc {
26 
CtorDtorIterator(const GlobalVariable * GV,bool End)27 CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
28   : InitList(
29       GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
30     I((InitList && End) ? InitList->getNumOperands() : 0) {
31 }
32 
operator ==(const CtorDtorIterator & Other) const33 bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
34   assert(InitList == Other.InitList && "Incomparable iterators.");
35   return I == Other.I;
36 }
37 
operator !=(const CtorDtorIterator & Other) const38 bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
39   return !(*this == Other);
40 }
41 
operator ++()42 CtorDtorIterator& CtorDtorIterator::operator++() {
43   ++I;
44   return *this;
45 }
46 
operator ++(int)47 CtorDtorIterator CtorDtorIterator::operator++(int) {
48   CtorDtorIterator Temp = *this;
49   ++I;
50   return Temp;
51 }
52 
operator *() const53 CtorDtorIterator::Element CtorDtorIterator::operator*() const {
54   ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
55   assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
56 
57   Constant *FuncC = CS->getOperand(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>(FuncC)) {
63       Func = F;
64       break;
65     } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
66       if (CE->isCast())
67         FuncC = CE->getOperand(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>(CS->getOperand(0));
77   Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
78   if (Data && !isa<GlobalValue>(Data))
79     Data = nullptr;
80   return Element(Priority->getZExtValue(), Func, Data);
81 }
82 
getConstructors(const Module & M)83 iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
84   const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
85   return make_range(CtorDtorIterator(CtorsList, false),
86                     CtorDtorIterator(CtorsList, true));
87 }
88 
getDestructors(const Module & M)89 iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
90   const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
91   return make_range(CtorDtorIterator(DtorsList, false),
92                     CtorDtorIterator(DtorsList, true));
93 }
94 
isStaticInitGlobal(GlobalValue & GV)95 bool 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("__DATA,__objc_classlist") ||
108          GV.getSection().starts_with("__DATA,__objc_selrefs")))
109       return true;
110   }
111 
112   return false;
113 }
114 
add(iterator_range<CtorDtorIterator> CtorDtors)115 void 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>(CtorDtor.Data)->isDeclaration()) {
134       dbgs() << "  Skipping because why now?\n";
135       continue;
136     }
137 
138     CtorDtorsByPriority[CtorDtor.Priority].push_back(
139         Mangle(CtorDtor.Func->getName()));
140   }
141 }
142 
run()143 Error CtorDtorRunner::run() {
144   using CtorDtorTy = void (*)();
145 
146   SymbolLookupSet LookupSet;
147   for (auto &KV : CtorDtorsByPriority)
148     for (auto &Name : KV.second)
149       LookupSet.add(Name);
150   assert(!LookupSet.containsDuplicates() &&
151          "Ctor/Dtor list contains duplicates");
152 
153   auto &ES = JD.getExecutionSession();
154   if (auto CtorDtorMap = ES.lookup(
155           makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
156           std::move(LookupSet))) {
157     for (auto &KV : CtorDtorsByPriority) {
158       for (auto &Name : KV.second) {
159         assert(CtorDtorMap->count(Name) && "No entry for Name");
160         auto CtorDtor = (*CtorDtorMap)[Name].getAddress().toPtr<CtorDtorTy>();
161         CtorDtor();
162       }
163     }
164     CtorDtorsByPriority.clear();
165     return Error::success();
166   } else
167     return CtorDtorMap.takeError();
168 }
169 
runDestructors()170 void LocalCXXRuntimeOverridesBase::runDestructors() {
171   auto& CXXDestructorDataPairs = DSOHandleOverride;
172   for (auto &P : CXXDestructorDataPairs)
173     P.first(P.second);
174   CXXDestructorDataPairs.clear();
175 }
176 
CXAAtExitOverride(DestructorPtr Destructor,void * Arg,void * DSOHandle)177 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
178                                                     void *Arg,
179                                                     void *DSOHandle) {
180   auto& CXXDestructorDataPairs =
181     *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
182   CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
183   return 0;
184 }
185 
enable(JITDylib & JD,MangleAndInterner & Mangle)186 Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
187                                         MangleAndInterner &Mangle) {
188   SymbolMap RuntimeInterposes;
189   RuntimeInterposes[Mangle("__dso_handle")] = {
190       ExecutorAddr::fromPtr(&DSOHandleOverride), JITSymbolFlags::Exported};
191   RuntimeInterposes[Mangle("__cxa_atexit")] = {
192       ExecutorAddr::fromPtr(&CXAAtExitOverride), JITSymbolFlags::Exported};
193 
194   return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
195 }
196 
registerAtExit(void (* F)(void *),void * Ctx,void * DSOHandle)197 void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx,
198                                              void *DSOHandle) {
199   std::lock_guard<std::mutex> Lock(AtExitsMutex);
200   AtExitRecords[DSOHandle].push_back({F, Ctx});
201 }
202 
runAtExits(void * DSOHandle)203 void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
204   std::vector<AtExitRecord> AtExitsToRun;
205 
206   {
207     std::lock_guard<std::mutex> Lock(AtExitsMutex);
208     auto I = AtExitRecords.find(DSOHandle);
209     if (I != AtExitRecords.end()) {
210       AtExitsToRun = std::move(I->second);
211       AtExitRecords.erase(I);
212     }
213   }
214 
215   while (!AtExitsToRun.empty()) {
216     AtExitsToRun.back().F(AtExitsToRun.back().Ctx);
217     AtExitsToRun.pop_back();
218   }
219 }
220 
DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib,char GlobalPrefix,SymbolPredicate Allow,AddAbsoluteSymbolsFn AddAbsoluteSymbols)221 DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
222     sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow,
223     AddAbsoluteSymbolsFn AddAbsoluteSymbols)
224     : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
225       AddAbsoluteSymbols(std::move(AddAbsoluteSymbols)),
226       GlobalPrefix(GlobalPrefix) {}
227 
228 Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
Load(const char * FileName,char GlobalPrefix,SymbolPredicate Allow,AddAbsoluteSymbolsFn AddAbsoluteSymbols)229 DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
230                                     SymbolPredicate Allow,
231                                     AddAbsoluteSymbolsFn AddAbsoluteSymbols) {
232   std::string ErrMsg;
233   auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
234   if (!Lib.isValid())
235     return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
236   return std::make_unique<DynamicLibrarySearchGenerator>(
237       std::move(Lib), GlobalPrefix, std::move(Allow),
238       std::move(AddAbsoluteSymbols));
239 }
240 
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & Symbols)241 Error DynamicLibrarySearchGenerator::tryToGenerate(
242     LookupState &LS, LookupKind K, JITDylib &JD,
243     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
244   orc::SymbolMap NewSymbols;
245 
246   bool HasGlobalPrefix = (GlobalPrefix != '\0');
247 
248   for (auto &KV : Symbols) {
249     auto &Name = KV.first;
250 
251     if ((*Name).empty())
252       continue;
253 
254     if (Allow && !Allow(Name))
255       continue;
256 
257     if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
258       continue;
259 
260     std::string Tmp((*Name).data() + HasGlobalPrefix,
261                     (*Name).size() - HasGlobalPrefix);
262     if (void *P = Dylib.getAddressOfSymbol(Tmp.c_str()))
263       NewSymbols[Name] = {ExecutorAddr::fromPtr(P), JITSymbolFlags::Exported};
264   }
265 
266   if (NewSymbols.empty())
267     return Error::success();
268 
269   if (AddAbsoluteSymbols)
270     return AddAbsoluteSymbols(JD, std::move(NewSymbols));
271   return JD.define(absoluteSymbols(std::move(NewSymbols)));
272 }
273 
274 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Load(ObjectLayer & L,const char * FileName,GetObjectFileInterface GetObjFileInterface)275 StaticLibraryDefinitionGenerator::Load(
276     ObjectLayer &L, const char *FileName,
277     GetObjectFileInterface GetObjFileInterface) {
278 
279   auto B = object::createBinary(FileName);
280   if (!B)
281     return createFileError(FileName, B.takeError());
282 
283   // If this is a regular archive then create an instance from it.
284   if (isa<object::Archive>(B->getBinary())) {
285     auto [Archive, ArchiveBuffer] = B->takeBinary();
286     return Create(L, std::move(ArchiveBuffer),
287                   std::unique_ptr<object::Archive>(
288                       static_cast<object::Archive *>(Archive.release())),
289                   std::move(GetObjFileInterface));
290   }
291 
292   // If this is a universal binary then search for a slice matching the given
293   // Triple.
294   if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->getBinary())) {
295 
296     const auto &TT = L.getExecutionSession().getTargetTriple();
297 
298     auto SliceRange = getSliceRangeForArch(*UB, TT);
299     if (!SliceRange)
300       return SliceRange.takeError();
301 
302     auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, SliceRange->second,
303                                                   SliceRange->first);
304     if (!SliceBuffer)
305       return make_error<StringError>(
306           Twine("Could not create buffer for ") + TT.str() + " slice of " +
307               FileName + ": [ " + formatv("{0:x}", SliceRange->first) + " .. " +
308               formatv("{0:x}", SliceRange->first + SliceRange->second) + ": " +
309               SliceBuffer.getError().message(),
310           SliceBuffer.getError());
311 
312     return Create(L, std::move(*SliceBuffer), std::move(GetObjFileInterface));
313   }
314 
315   return make_error<StringError>(Twine("Unrecognized file type for ") +
316                                      FileName,
317                                  inconvertibleErrorCode());
318 }
319 
320 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> ArchiveBuffer,std::unique_ptr<object::Archive> Archive,GetObjectFileInterface GetObjFileInterface)321 StaticLibraryDefinitionGenerator::Create(
322     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
323     std::unique_ptr<object::Archive> Archive,
324     GetObjectFileInterface GetObjFileInterface) {
325 
326   Error Err = Error::success();
327 
328   std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
329       new StaticLibraryDefinitionGenerator(
330           L, std::move(ArchiveBuffer), std::move(Archive),
331           std::move(GetObjFileInterface), Err));
332 
333   if (Err)
334     return std::move(Err);
335 
336   return std::move(ADG);
337 }
338 
339 Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
Create(ObjectLayer & L,std::unique_ptr<MemoryBuffer> ArchiveBuffer,GetObjectFileInterface GetObjFileInterface)340 StaticLibraryDefinitionGenerator::Create(
341     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
342     GetObjectFileInterface GetObjFileInterface) {
343 
344   auto B = object::createBinary(ArchiveBuffer->getMemBufferRef());
345   if (!B)
346     return B.takeError();
347 
348   // If this is a regular archive then create an instance from it.
349   if (isa<object::Archive>(*B))
350     return Create(L, std::move(ArchiveBuffer),
351                   std::unique_ptr<object::Archive>(
352                       static_cast<object::Archive *>(B->release())),
353                   std::move(GetObjFileInterface));
354 
355   // If this is a universal binary then search for a slice matching the given
356   // Triple.
357   if (auto *UB = dyn_cast<object::MachOUniversalBinary>(B->get())) {
358 
359     const auto &TT = L.getExecutionSession().getTargetTriple();
360 
361     auto SliceRange = getSliceRangeForArch(*UB, TT);
362     if (!SliceRange)
363       return SliceRange.takeError();
364 
365     MemoryBufferRef SliceRef(
366         StringRef(ArchiveBuffer->getBufferStart() + SliceRange->first,
367                   SliceRange->second),
368         ArchiveBuffer->getBufferIdentifier());
369 
370     auto Archive = object::Archive::create(SliceRef);
371     if (!Archive)
372       return Archive.takeError();
373 
374     return Create(L, std::move(ArchiveBuffer), std::move(*Archive),
375                   std::move(GetObjFileInterface));
376   }
377 
378   return make_error<StringError>(Twine("Unrecognized file type for ") +
379                                      ArchiveBuffer->getBufferIdentifier(),
380                                  inconvertibleErrorCode());
381 }
382 
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & Symbols)383 Error StaticLibraryDefinitionGenerator::tryToGenerate(
384     LookupState &LS, LookupKind K, JITDylib &JD,
385     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
386   // Don't materialize symbols from static archives unless this is a static
387   // lookup.
388   if (K != LookupKind::Static)
389     return Error::success();
390 
391   // Bail out early if we've already freed the archive.
392   if (!Archive)
393     return Error::success();
394 
395   DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
396 
397   for (const auto &KV : Symbols) {
398     const auto &Name = KV.first;
399     if (!ObjectFilesMap.count(Name))
400       continue;
401     auto ChildBuffer = ObjectFilesMap[Name];
402     ChildBufferInfos.insert(
403         {ChildBuffer.getBuffer(), ChildBuffer.getBufferIdentifier()});
404   }
405 
406   for (auto ChildBufferInfo : ChildBufferInfos) {
407     MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
408                                    ChildBufferInfo.second);
409 
410     auto I = GetObjFileInterface(L.getExecutionSession(), ChildBufferRef);
411     if (!I)
412       return I.takeError();
413 
414     if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
415                          std::move(*I)))
416       return Err;
417   }
418 
419   return Error::success();
420 }
421 
buildObjectFilesMap()422 Error StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
423   DenseMap<uint64_t, MemoryBufferRef> MemoryBuffers;
424   DenseSet<uint64_t> Visited;
425   DenseSet<uint64_t> Excluded;
426   StringSaver FileNames(ObjFileNameStorage);
427   for (auto &S : Archive->symbols()) {
428     StringRef SymName = S.getName();
429     auto Member = S.getMember();
430     if (!Member)
431       return Member.takeError();
432     auto DataOffset = Member->getDataOffset();
433     if (!Visited.count(DataOffset)) {
434       Visited.insert(DataOffset);
435       auto Child = Member->getAsBinary();
436       if (!Child)
437         return Child.takeError();
438       if ((*Child)->isCOFFImportFile()) {
439         ImportedDynamicLibraries.insert((*Child)->getFileName().str());
440         Excluded.insert(DataOffset);
441         continue;
442       }
443 
444       // Give members of the archive a name that contains the archive path so
445       // that they can be differentiated from a member with the same name in a
446       // different archive. This also ensure initializer symbols names will be
447       // unique within a JITDylib.
448       StringRef FullName = FileNames.save(Archive->getFileName() + "(" +
449                                           (*Child)->getFileName() + ")");
450       MemoryBufferRef MemBuffer((*Child)->getMemoryBufferRef().getBuffer(),
451                                 FullName);
452 
453       MemoryBuffers[DataOffset] = MemBuffer;
454     }
455     if (!Excluded.count(DataOffset))
456       ObjectFilesMap[L.getExecutionSession().intern(SymName)] =
457           MemoryBuffers[DataOffset];
458   }
459 
460   return Error::success();
461 }
462 
463 Expected<std::pair<size_t, size_t>>
getSliceRangeForArch(object::MachOUniversalBinary & UB,const Triple & TT)464 StaticLibraryDefinitionGenerator::getSliceRangeForArch(
465     object::MachOUniversalBinary &UB, const Triple &TT) {
466 
467   for (const auto &Obj : UB.objects()) {
468     auto ObjTT = Obj.getTriple();
469     if (ObjTT.getArch() == TT.getArch() &&
470         ObjTT.getSubArch() == TT.getSubArch() &&
471         (TT.getVendor() == Triple::UnknownVendor ||
472          ObjTT.getVendor() == TT.getVendor())) {
473       // We found a match. Return the range for the slice.
474       return std::make_pair(Obj.getOffset(), Obj.getSize());
475     }
476   }
477 
478   return make_error<StringError>(Twine("Universal binary ") + UB.getFileName() +
479                                      " does not contain a slice for " +
480                                      TT.str(),
481                                  inconvertibleErrorCode());
482 }
483 
StaticLibraryDefinitionGenerator(ObjectLayer & L,std::unique_ptr<MemoryBuffer> ArchiveBuffer,std::unique_ptr<object::Archive> Archive,GetObjectFileInterface GetObjFileInterface,Error & Err)484 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
485     ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer,
486     std::unique_ptr<object::Archive> Archive,
487     GetObjectFileInterface GetObjFileInterface, Error &Err)
488     : L(L), GetObjFileInterface(std::move(GetObjFileInterface)),
489       ArchiveBuffer(std::move(ArchiveBuffer)), Archive(std::move(Archive)) {
490   ErrorAsOutParameter _(&Err);
491   if (!this->GetObjFileInterface)
492     this->GetObjFileInterface = getObjectFileInterface;
493   if (!Err)
494     Err = buildObjectFilesMap();
495 }
496 
497 std::unique_ptr<DLLImportDefinitionGenerator>
Create(ExecutionSession & ES,ObjectLinkingLayer & L)498 DLLImportDefinitionGenerator::Create(ExecutionSession &ES,
499                                      ObjectLinkingLayer &L) {
500   return std::unique_ptr<DLLImportDefinitionGenerator>(
501       new DLLImportDefinitionGenerator(ES, L));
502 }
503 
tryToGenerate(LookupState & LS,LookupKind K,JITDylib & JD,JITDylibLookupFlags JDLookupFlags,const SymbolLookupSet & Symbols)504 Error DLLImportDefinitionGenerator::tryToGenerate(
505     LookupState &LS, LookupKind K, JITDylib &JD,
506     JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) {
507   JITDylibSearchOrder LinkOrder;
508   JD.withLinkOrderDo([&](const JITDylibSearchOrder &LO) {
509     LinkOrder.reserve(LO.size());
510     for (auto &KV : LO) {
511       if (KV.first == &JD)
512         continue;
513       LinkOrder.push_back(KV);
514     }
515   });
516 
517   // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
518   // both __imp_ and stripped name and use the lookup information to resolve the
519   // real symbol name.
520   SymbolLookupSet LookupSet;
521   DenseMap<StringRef, SymbolLookupFlags> ToLookUpSymbols;
522   for (auto &KV : Symbols) {
523     StringRef Deinterned = *KV.first;
524     if (Deinterned.starts_with(getImpPrefix()))
525       Deinterned = Deinterned.drop_front(StringRef(getImpPrefix()).size());
526     // Don't degrade the required state
527     if (ToLookUpSymbols.count(Deinterned) &&
528         ToLookUpSymbols[Deinterned] == SymbolLookupFlags::RequiredSymbol)
529       continue;
530     ToLookUpSymbols[Deinterned] = KV.second;
531   }
532 
533   for (auto &KV : ToLookUpSymbols)
534     LookupSet.add(ES.intern(KV.first), KV.second);
535 
536   auto Resolved =
537       ES.lookup(LinkOrder, LookupSet, LookupKind::DLSym, SymbolState::Resolved);
538   if (!Resolved)
539     return Resolved.takeError();
540 
541   auto G = createStubsGraph(*Resolved);
542   if (!G)
543     return G.takeError();
544   return L.add(JD, std::move(*G));
545 }
546 
547 Expected<unsigned>
getTargetPointerSize(const Triple & TT)548 DLLImportDefinitionGenerator::getTargetPointerSize(const Triple &TT) {
549   switch (TT.getArch()) {
550   case Triple::x86_64:
551     return 8;
552   default:
553     return make_error<StringError>(
554         "architecture unsupported by DLLImportDefinitionGenerator",
555         inconvertibleErrorCode());
556   }
557 }
558 
559 Expected<llvm::endianness>
getEndianness(const Triple & TT)560 DLLImportDefinitionGenerator::getEndianness(const Triple &TT) {
561   switch (TT.getArch()) {
562   case Triple::x86_64:
563     return llvm::endianness::little;
564   default:
565     return make_error<StringError>(
566         "architecture unsupported by DLLImportDefinitionGenerator",
567         inconvertibleErrorCode());
568   }
569 }
570 
571 Expected<std::unique_ptr<jitlink::LinkGraph>>
createStubsGraph(const SymbolMap & Resolved)572 DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap &Resolved) {
573   Triple TT = ES.getTargetTriple();
574   auto PointerSize = getTargetPointerSize(TT);
575   if (!PointerSize)
576     return PointerSize.takeError();
577   auto Endianness = getEndianness(TT);
578   if (!Endianness)
579     return Endianness.takeError();
580 
581   auto G = std::make_unique<jitlink::LinkGraph>(
582       "<DLLIMPORT_STUBS>", TT, *PointerSize, *Endianness,
583       jitlink::getGenericEdgeKindName);
584   jitlink::Section &Sec =
585       G->createSection(getSectionName(), MemProt::Read | MemProt::Exec);
586 
587   for (auto &KV : Resolved) {
588     jitlink::Symbol &Target = G->addAbsoluteSymbol(
589         *KV.first, KV.second.getAddress(), *PointerSize,
590         jitlink::Linkage::Strong, jitlink::Scope::Local, false);
591 
592     // Create __imp_ symbol
593     jitlink::Symbol &Ptr =
594         jitlink::x86_64::createAnonymousPointer(*G, Sec, &Target);
595     auto NameCopy = G->allocateContent(Twine(getImpPrefix()) + *KV.first);
596     StringRef NameCopyRef = StringRef(NameCopy.data(), NameCopy.size());
597     Ptr.setName(NameCopyRef);
598     Ptr.setLinkage(jitlink::Linkage::Strong);
599     Ptr.setScope(jitlink::Scope::Default);
600 
601     // Create PLT stub
602     // FIXME: check PLT stub of data symbol is not accessed
603     jitlink::Block &StubBlock =
604         jitlink::x86_64::createPointerJumpStubBlock(*G, Sec, Ptr);
605     G->addDefinedSymbol(StubBlock, 0, *KV.first, StubBlock.getSize(),
606                         jitlink::Linkage::Strong, jitlink::Scope::Default, true,
607                         false);
608   }
609 
610   return std::move(G);
611 }
612 
613 } // End namespace orc.
614 } // End namespace llvm.
615