1 //===---- ExecutionUtils.cpp - Utilities for executing functions in Orc ---===//
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
7 //===----------------------------------------------------------------------===//
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/Target/TargetMachine.h"
26 CtorDtorIterator::CtorDtorIterator(const GlobalVariable
*GV
, bool End
)
28 GV
? dyn_cast_or_null
<ConstantArray
>(GV
->getInitializer()) : nullptr),
29 I((InitList
&& End
) ? InitList
->getNumOperands() : 0) {
32 bool CtorDtorIterator::operator==(const CtorDtorIterator
&Other
) const {
33 assert(InitList
== Other
.InitList
&& "Incomparable iterators.");
37 bool CtorDtorIterator::operator!=(const CtorDtorIterator
&Other
) const {
38 return !(*this == Other
);
41 CtorDtorIterator
& CtorDtorIterator::operator++() {
46 CtorDtorIterator
CtorDtorIterator::operator++(int) {
47 CtorDtorIterator Temp
= *this;
52 CtorDtorIterator::Element
CtorDtorIterator::operator*() const {
53 ConstantStruct
*CS
= dyn_cast
<ConstantStruct
>(InitList
->getOperand(I
));
54 assert(CS
&& "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
56 Constant
*FuncC
= CS
->getOperand(1);
57 Function
*Func
= nullptr;
59 // Extract function pointer, pulling off any casts.
61 if (Function
*F
= dyn_cast_or_null
<Function
>(FuncC
)) {
64 } else if (ConstantExpr
*CE
= dyn_cast_or_null
<ConstantExpr
>(FuncC
)) {
66 FuncC
= CE
->getOperand(0);
70 // This isn't anything we recognize. Bail out with Func left set to null.
75 auto *Priority
= cast
<ConstantInt
>(CS
->getOperand(0));
76 Value
*Data
= CS
->getNumOperands() == 3 ? CS
->getOperand(2) : nullptr;
77 if (Data
&& !isa
<GlobalValue
>(Data
))
79 return Element(Priority
->getZExtValue(), Func
, Data
);
82 iterator_range
<CtorDtorIterator
> getConstructors(const Module
&M
) {
83 const GlobalVariable
*CtorsList
= M
.getNamedGlobal("llvm.global_ctors");
84 return make_range(CtorDtorIterator(CtorsList
, false),
85 CtorDtorIterator(CtorsList
, true));
88 iterator_range
<CtorDtorIterator
> getDestructors(const Module
&M
) {
89 const GlobalVariable
*DtorsList
= M
.getNamedGlobal("llvm.global_dtors");
90 return make_range(CtorDtorIterator(DtorsList
, false),
91 CtorDtorIterator(DtorsList
, true));
94 bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue
&GV
) {
95 if (GV
.isDeclaration())
98 if (GV
.hasName() && (GV
.getName() == "llvm.global_ctors" ||
99 GV
.getName() == "llvm.global_dtors"))
102 if (ObjFmt
== Triple::MachO
) {
103 // FIXME: These section checks are too strict: We should match first and
104 // second word split by comma.
105 if (GV
.hasSection() &&
106 (GV
.getSection().startswith("__DATA,__objc_classlist") ||
107 GV
.getSection().startswith("__DATA,__objc_selrefs")))
114 void CtorDtorRunner::add(iterator_range
<CtorDtorIterator
> CtorDtors
) {
115 if (CtorDtors
.empty())
118 MangleAndInterner
Mangle(
119 JD
.getExecutionSession(),
120 (*CtorDtors
.begin()).Func
->getParent()->getDataLayout());
122 for (auto CtorDtor
: CtorDtors
) {
123 assert(CtorDtor
.Func
&& CtorDtor
.Func
->hasName() &&
124 "Ctor/Dtor function must be named to be runnable under the JIT");
126 // FIXME: Maybe use a symbol promoter here instead.
127 if (CtorDtor
.Func
->hasLocalLinkage()) {
128 CtorDtor
.Func
->setLinkage(GlobalValue::ExternalLinkage
);
129 CtorDtor
.Func
->setVisibility(GlobalValue::HiddenVisibility
);
132 if (CtorDtor
.Data
&& cast
<GlobalValue
>(CtorDtor
.Data
)->isDeclaration()) {
133 dbgs() << " Skipping because why now?\n";
137 CtorDtorsByPriority
[CtorDtor
.Priority
].push_back(
138 Mangle(CtorDtor
.Func
->getName()));
142 Error
CtorDtorRunner::run() {
143 using CtorDtorTy
= void (*)();
145 SymbolLookupSet LookupSet
;
146 for (auto &KV
: CtorDtorsByPriority
)
147 for (auto &Name
: KV
.second
)
149 assert(!LookupSet
.containsDuplicates() &&
150 "Ctor/Dtor list contains duplicates");
152 auto &ES
= JD
.getExecutionSession();
153 if (auto CtorDtorMap
= ES
.lookup(
154 makeJITDylibSearchOrder(&JD
, JITDylibLookupFlags::MatchAllSymbols
),
155 std::move(LookupSet
))) {
156 for (auto &KV
: CtorDtorsByPriority
) {
157 for (auto &Name
: KV
.second
) {
158 assert(CtorDtorMap
->count(Name
) && "No entry for Name");
159 auto CtorDtor
= (*CtorDtorMap
)[Name
].getAddress().toPtr
<CtorDtorTy
>();
163 CtorDtorsByPriority
.clear();
164 return Error::success();
166 return CtorDtorMap
.takeError();
169 void LocalCXXRuntimeOverridesBase::runDestructors() {
170 auto& CXXDestructorDataPairs
= DSOHandleOverride
;
171 for (auto &P
: CXXDestructorDataPairs
)
173 CXXDestructorDataPairs
.clear();
176 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor
,
179 auto& CXXDestructorDataPairs
=
180 *reinterpret_cast<CXXDestructorDataPairList
*>(DSOHandle
);
181 CXXDestructorDataPairs
.push_back(std::make_pair(Destructor
, Arg
));
185 Error
LocalCXXRuntimeOverrides::enable(JITDylib
&JD
,
186 MangleAndInterner
&Mangle
) {
187 SymbolMap RuntimeInterposes
;
188 RuntimeInterposes
[Mangle("__dso_handle")] = {
189 ExecutorAddr::fromPtr(&DSOHandleOverride
), JITSymbolFlags::Exported
};
190 RuntimeInterposes
[Mangle("__cxa_atexit")] = {
191 ExecutorAddr::fromPtr(&CXAAtExitOverride
), JITSymbolFlags::Exported
};
193 return JD
.define(absoluteSymbols(std::move(RuntimeInterposes
)));
196 void ItaniumCXAAtExitSupport::registerAtExit(void (*F
)(void *), void *Ctx
,
198 std::lock_guard
<std::mutex
> Lock(AtExitsMutex
);
199 AtExitRecords
[DSOHandle
].push_back({F
, Ctx
});
202 void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle
) {
203 std::vector
<AtExitRecord
> AtExitsToRun
;
206 std::lock_guard
<std::mutex
> Lock(AtExitsMutex
);
207 auto I
= AtExitRecords
.find(DSOHandle
);
208 if (I
!= AtExitRecords
.end()) {
209 AtExitsToRun
= std::move(I
->second
);
210 AtExitRecords
.erase(I
);
214 while (!AtExitsToRun
.empty()) {
215 AtExitsToRun
.back().F(AtExitsToRun
.back().Ctx
);
216 AtExitsToRun
.pop_back();
220 DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
221 sys::DynamicLibrary Dylib
, char GlobalPrefix
, SymbolPredicate Allow
)
222 : Dylib(std::move(Dylib
)), Allow(std::move(Allow
)),
223 GlobalPrefix(GlobalPrefix
) {}
225 Expected
<std::unique_ptr
<DynamicLibrarySearchGenerator
>>
226 DynamicLibrarySearchGenerator::Load(const char *FileName
, char GlobalPrefix
,
227 SymbolPredicate Allow
) {
229 auto Lib
= sys::DynamicLibrary::getPermanentLibrary(FileName
, &ErrMsg
);
231 return make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode());
232 return std::make_unique
<DynamicLibrarySearchGenerator
>(
233 std::move(Lib
), GlobalPrefix
, std::move(Allow
));
236 Error
DynamicLibrarySearchGenerator::tryToGenerate(
237 LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
238 JITDylibLookupFlags JDLookupFlags
, const SymbolLookupSet
&Symbols
) {
239 orc::SymbolMap NewSymbols
;
241 bool HasGlobalPrefix
= (GlobalPrefix
!= '\0');
243 for (auto &KV
: Symbols
) {
244 auto &Name
= KV
.first
;
249 if (Allow
&& !Allow(Name
))
252 if (HasGlobalPrefix
&& (*Name
).front() != GlobalPrefix
)
255 std::string
Tmp((*Name
).data() + HasGlobalPrefix
,
256 (*Name
).size() - HasGlobalPrefix
);
257 if (void *P
= Dylib
.getAddressOfSymbol(Tmp
.c_str()))
258 NewSymbols
[Name
] = {ExecutorAddr::fromPtr(P
), JITSymbolFlags::Exported
};
261 if (NewSymbols
.empty())
262 return Error::success();
264 return JD
.define(absoluteSymbols(std::move(NewSymbols
)));
267 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
268 StaticLibraryDefinitionGenerator::Load(
269 ObjectLayer
&L
, const char *FileName
,
270 GetObjectFileInterface GetObjFileInterface
) {
272 auto B
= object::createBinary(FileName
);
274 return createFileError(FileName
, B
.takeError());
276 // If this is a regular archive then create an instance from it.
277 if (isa
<object::Archive
>(B
->getBinary())) {
278 auto [Archive
, ArchiveBuffer
] = B
->takeBinary();
279 return Create(L
, std::move(ArchiveBuffer
),
280 std::unique_ptr
<object::Archive
>(
281 static_cast<object::Archive
*>(Archive
.release())),
282 std::move(GetObjFileInterface
));
285 // If this is a universal binary then search for a slice matching the given
287 if (auto *UB
= cast
<object::MachOUniversalBinary
>(B
->getBinary())) {
289 const auto &TT
= L
.getExecutionSession().getTargetTriple();
291 auto SliceRange
= getSliceRangeForArch(*UB
, TT
);
293 return SliceRange
.takeError();
295 auto SliceBuffer
= MemoryBuffer::getFileSlice(FileName
, SliceRange
->second
,
298 return make_error
<StringError
>(
299 Twine("Could not create buffer for ") + TT
.str() + " slice of " +
300 FileName
+ ": [ " + formatv("{0:x}", SliceRange
->first
) + " .. " +
301 formatv("{0:x}", SliceRange
->first
+ SliceRange
->second
) + ": " +
302 SliceBuffer
.getError().message(),
303 SliceBuffer
.getError());
305 return Create(L
, std::move(*SliceBuffer
), std::move(GetObjFileInterface
));
308 return make_error
<StringError
>(Twine("Unrecognized file type for ") +
310 inconvertibleErrorCode());
313 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
314 StaticLibraryDefinitionGenerator::Create(
315 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
,
316 std::unique_ptr
<object::Archive
> Archive
,
317 GetObjectFileInterface GetObjFileInterface
) {
319 Error Err
= Error::success();
321 std::unique_ptr
<StaticLibraryDefinitionGenerator
> ADG(
322 new StaticLibraryDefinitionGenerator(
323 L
, std::move(ArchiveBuffer
), std::move(Archive
),
324 std::move(GetObjFileInterface
), Err
));
327 return std::move(Err
);
329 return std::move(ADG
);
332 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
333 StaticLibraryDefinitionGenerator::Create(
334 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
,
335 GetObjectFileInterface GetObjFileInterface
) {
337 auto B
= object::createBinary(ArchiveBuffer
->getMemBufferRef());
339 return B
.takeError();
341 // If this is a regular archive then create an instance from it.
342 if (isa
<object::Archive
>(*B
))
343 return Create(L
, std::move(ArchiveBuffer
),
344 std::unique_ptr
<object::Archive
>(
345 static_cast<object::Archive
*>(B
->release())),
346 std::move(GetObjFileInterface
));
348 // If this is a universal binary then search for a slice matching the given
350 if (auto *UB
= cast
<object::MachOUniversalBinary
>(B
->get())) {
352 const auto &TT
= L
.getExecutionSession().getTargetTriple();
354 auto SliceRange
= getSliceRangeForArch(*UB
, TT
);
356 return SliceRange
.takeError();
358 MemoryBufferRef
SliceRef(
359 StringRef(ArchiveBuffer
->getBufferStart() + SliceRange
->first
,
361 ArchiveBuffer
->getBufferIdentifier());
363 auto Archive
= object::Archive::create(SliceRef
);
365 return Archive
.takeError();
367 return Create(L
, std::move(ArchiveBuffer
), std::move(*Archive
),
368 std::move(GetObjFileInterface
));
371 return make_error
<StringError
>(Twine("Unrecognized file type for ") +
372 ArchiveBuffer
->getBufferIdentifier(),
373 inconvertibleErrorCode());
376 Error
StaticLibraryDefinitionGenerator::tryToGenerate(
377 LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
378 JITDylibLookupFlags JDLookupFlags
, const SymbolLookupSet
&Symbols
) {
379 // Don't materialize symbols from static archives unless this is a static
381 if (K
!= LookupKind::Static
)
382 return Error::success();
384 // Bail out early if we've already freed the archive.
386 return Error::success();
388 DenseSet
<std::pair
<StringRef
, StringRef
>> ChildBufferInfos
;
390 for (const auto &KV
: Symbols
) {
391 const auto &Name
= KV
.first
;
392 if (!ObjectFilesMap
.count(Name
))
394 auto ChildBuffer
= ObjectFilesMap
[Name
];
395 ChildBufferInfos
.insert(
396 {ChildBuffer
.getBuffer(), ChildBuffer
.getBufferIdentifier()});
399 for (auto ChildBufferInfo
: ChildBufferInfos
) {
400 MemoryBufferRef
ChildBufferRef(ChildBufferInfo
.first
,
401 ChildBufferInfo
.second
);
403 auto I
= GetObjFileInterface(L
.getExecutionSession(), ChildBufferRef
);
405 return I
.takeError();
407 if (auto Err
= L
.add(JD
, MemoryBuffer::getMemBuffer(ChildBufferRef
, false),
412 return Error::success();
415 Error
StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
416 DenseMap
<uint64_t, MemoryBufferRef
> MemoryBuffers
;
417 DenseSet
<uint64_t> Visited
;
418 DenseSet
<uint64_t> Excluded
;
419 for (auto &S
: Archive
->symbols()) {
420 StringRef SymName
= S
.getName();
421 auto Member
= S
.getMember();
423 return Member
.takeError();
424 auto DataOffset
= Member
->getDataOffset();
425 if (!Visited
.count(DataOffset
)) {
426 Visited
.insert(DataOffset
);
427 auto Child
= Member
->getAsBinary();
429 return Child
.takeError();
430 if ((*Child
)->isCOFFImportFile()) {
431 ImportedDynamicLibraries
.insert((*Child
)->getFileName().str());
432 Excluded
.insert(DataOffset
);
435 MemoryBuffers
[DataOffset
] = (*Child
)->getMemoryBufferRef();
437 if (!Excluded
.count(DataOffset
))
438 ObjectFilesMap
[L
.getExecutionSession().intern(SymName
)] =
439 MemoryBuffers
[DataOffset
];
442 return Error::success();
445 Expected
<std::pair
<size_t, size_t>>
446 StaticLibraryDefinitionGenerator::getSliceRangeForArch(
447 object::MachOUniversalBinary
&UB
, const Triple
&TT
) {
449 for (const auto &Obj
: UB
.objects()) {
450 auto ObjTT
= Obj
.getTriple();
451 if (ObjTT
.getArch() == TT
.getArch() &&
452 ObjTT
.getSubArch() == TT
.getSubArch() &&
453 (TT
.getVendor() == Triple::UnknownVendor
||
454 ObjTT
.getVendor() == TT
.getVendor())) {
455 // We found a match. Return the range for the slice.
456 return std::make_pair(Obj
.getOffset(), Obj
.getSize());
460 return make_error
<StringError
>(Twine("Universal binary ") + UB
.getFileName() +
461 " does not contain a slice for " +
463 inconvertibleErrorCode());
466 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
467 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
,
468 std::unique_ptr
<object::Archive
> Archive
,
469 GetObjectFileInterface GetObjFileInterface
, Error
&Err
)
470 : L(L
), GetObjFileInterface(std::move(GetObjFileInterface
)),
471 ArchiveBuffer(std::move(ArchiveBuffer
)), Archive(std::move(Archive
)) {
472 ErrorAsOutParameter
_(&Err
);
473 if (!this->GetObjFileInterface
)
474 this->GetObjFileInterface
= getObjectFileInterface
;
476 Err
= buildObjectFilesMap();
479 std::unique_ptr
<DLLImportDefinitionGenerator
>
480 DLLImportDefinitionGenerator::Create(ExecutionSession
&ES
,
481 ObjectLinkingLayer
&L
) {
482 return std::unique_ptr
<DLLImportDefinitionGenerator
>(
483 new DLLImportDefinitionGenerator(ES
, L
));
486 Error
DLLImportDefinitionGenerator::tryToGenerate(
487 LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
488 JITDylibLookupFlags JDLookupFlags
, const SymbolLookupSet
&Symbols
) {
489 JITDylibSearchOrder LinkOrder
;
490 JD
.withLinkOrderDo([&](const JITDylibSearchOrder
&LO
) {
491 LinkOrder
.reserve(LO
.size());
492 for (auto &KV
: LO
) {
495 LinkOrder
.push_back(KV
);
499 // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
500 // both __imp_ and stripped name and use the lookup information to resolve the
502 SymbolLookupSet LookupSet
;
503 DenseMap
<StringRef
, SymbolLookupFlags
> ToLookUpSymbols
;
504 for (auto &KV
: Symbols
) {
505 StringRef Deinterned
= *KV
.first
;
506 if (Deinterned
.startswith(getImpPrefix()))
507 Deinterned
= Deinterned
.drop_front(StringRef(getImpPrefix()).size());
508 // Don't degrade the required state
509 if (ToLookUpSymbols
.count(Deinterned
) &&
510 ToLookUpSymbols
[Deinterned
] == SymbolLookupFlags::RequiredSymbol
)
512 ToLookUpSymbols
[Deinterned
] = KV
.second
;
515 for (auto &KV
: ToLookUpSymbols
)
516 LookupSet
.add(ES
.intern(KV
.first
), KV
.second
);
519 ES
.lookup(LinkOrder
, LookupSet
, LookupKind::DLSym
, SymbolState::Resolved
);
521 return Resolved
.takeError();
523 auto G
= createStubsGraph(*Resolved
);
525 return G
.takeError();
526 return L
.add(JD
, std::move(*G
));
530 DLLImportDefinitionGenerator::getTargetPointerSize(const Triple
&TT
) {
531 switch (TT
.getArch()) {
535 return make_error
<StringError
>(
536 "architecture unsupported by DLLImportDefinitionGenerator",
537 inconvertibleErrorCode());
541 Expected
<llvm::endianness
>
542 DLLImportDefinitionGenerator::getTargetEndianness(const Triple
&TT
) {
543 switch (TT
.getArch()) {
545 return llvm::endianness::little
;
547 return make_error
<StringError
>(
548 "architecture unsupported by DLLImportDefinitionGenerator",
549 inconvertibleErrorCode());
553 Expected
<std::unique_ptr
<jitlink::LinkGraph
>>
554 DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap
&Resolved
) {
555 Triple TT
= ES
.getTargetTriple();
556 auto PointerSize
= getTargetPointerSize(TT
);
558 return PointerSize
.takeError();
559 auto Endianness
= getTargetEndianness(TT
);
561 return Endianness
.takeError();
563 auto G
= std::make_unique
<jitlink::LinkGraph
>(
564 "<DLLIMPORT_STUBS>", TT
, *PointerSize
, *Endianness
,
565 jitlink::getGenericEdgeKindName
);
566 jitlink::Section
&Sec
=
567 G
->createSection(getSectionName(), MemProt::Read
| MemProt::Exec
);
569 for (auto &KV
: Resolved
) {
570 jitlink::Symbol
&Target
= G
->addAbsoluteSymbol(
571 *KV
.first
, KV
.second
.getAddress(), *PointerSize
,
572 jitlink::Linkage::Strong
, jitlink::Scope::Local
, false);
574 // Create __imp_ symbol
575 jitlink::Symbol
&Ptr
=
576 jitlink::x86_64::createAnonymousPointer(*G
, Sec
, &Target
);
577 auto NameCopy
= G
->allocateContent(Twine(getImpPrefix()) + *KV
.first
);
578 StringRef NameCopyRef
= StringRef(NameCopy
.data(), NameCopy
.size());
579 Ptr
.setName(NameCopyRef
);
580 Ptr
.setLinkage(jitlink::Linkage::Strong
);
581 Ptr
.setScope(jitlink::Scope::Default
);
584 // FIXME: check PLT stub of data symbol is not accessed
585 jitlink::Block
&StubBlock
=
586 jitlink::x86_64::createPointerJumpStubBlock(*G
, Sec
, Ptr
);
587 G
->addDefinedSymbol(StubBlock
, 0, *KV
.first
, StubBlock
.getSize(),
588 jitlink::Linkage::Strong
, jitlink::Scope::Default
, true,
595 } // End namespace orc.
596 } // End namespace llvm.