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/AbsoluteSymbols.h"
12 #include "llvm/ExecutionEngine/Orc/Layer.h"
13 #include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
14 #include "llvm/ExecutionEngine/Orc/MachO.h"
15 #include "llvm/ExecutionEngine/Orc/ObjectFileInterface.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/MC/TargetRegistry.h"
21 #include "llvm/Object/MachOUniversal.h"
22 #include "llvm/Support/StringSaver.h"
23 #include "llvm/Target/TargetMachine.h"
29 CtorDtorIterator::CtorDtorIterator(const GlobalVariable
*GV
, bool End
)
31 GV
? dyn_cast_or_null
<ConstantArray
>(GV
->getInitializer()) : nullptr),
32 I((InitList
&& End
) ? InitList
->getNumOperands() : 0) {
35 bool CtorDtorIterator::operator==(const CtorDtorIterator
&Other
) const {
36 assert(InitList
== Other
.InitList
&& "Incomparable iterators.");
40 bool CtorDtorIterator::operator!=(const CtorDtorIterator
&Other
) const {
41 return !(*this == Other
);
44 CtorDtorIterator
& CtorDtorIterator::operator++() {
49 CtorDtorIterator
CtorDtorIterator::operator++(int) {
50 CtorDtorIterator Temp
= *this;
55 CtorDtorIterator::Element
CtorDtorIterator::operator*() const {
56 ConstantStruct
*CS
= dyn_cast
<ConstantStruct
>(InitList
->getOperand(I
));
57 assert(CS
&& "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
59 Constant
*FuncC
= CS
->getOperand(1);
60 Function
*Func
= nullptr;
62 // Extract function pointer, pulling off any casts.
64 if (Function
*F
= dyn_cast_or_null
<Function
>(FuncC
)) {
67 } else if (ConstantExpr
*CE
= dyn_cast_or_null
<ConstantExpr
>(FuncC
)) {
69 FuncC
= CE
->getOperand(0);
73 // This isn't anything we recognize. Bail out with Func left set to null.
78 auto *Priority
= cast
<ConstantInt
>(CS
->getOperand(0));
79 Value
*Data
= CS
->getNumOperands() == 3 ? CS
->getOperand(2) : nullptr;
80 if (Data
&& !isa
<GlobalValue
>(Data
))
82 return Element(Priority
->getZExtValue(), Func
, Data
);
85 iterator_range
<CtorDtorIterator
> getConstructors(const Module
&M
) {
86 const GlobalVariable
*CtorsList
= M
.getNamedGlobal("llvm.global_ctors");
87 return make_range(CtorDtorIterator(CtorsList
, false),
88 CtorDtorIterator(CtorsList
, true));
91 iterator_range
<CtorDtorIterator
> getDestructors(const Module
&M
) {
92 const GlobalVariable
*DtorsList
= M
.getNamedGlobal("llvm.global_dtors");
93 return make_range(CtorDtorIterator(DtorsList
, false),
94 CtorDtorIterator(DtorsList
, true));
97 bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue
&GV
) {
98 if (GV
.isDeclaration())
101 if (GV
.hasName() && (GV
.getName() == "llvm.global_ctors" ||
102 GV
.getName() == "llvm.global_dtors"))
105 if (ObjFmt
== Triple::MachO
) {
106 // FIXME: These section checks are too strict: We should match first and
107 // second word split by comma.
108 if (GV
.hasSection() &&
109 (GV
.getSection().starts_with("__DATA,__objc_classlist") ||
110 GV
.getSection().starts_with("__DATA,__objc_selrefs")))
117 void CtorDtorRunner::add(iterator_range
<CtorDtorIterator
> CtorDtors
) {
118 if (CtorDtors
.empty())
121 MangleAndInterner
Mangle(
122 JD
.getExecutionSession(),
123 (*CtorDtors
.begin()).Func
->getDataLayout());
125 for (auto CtorDtor
: CtorDtors
) {
126 assert(CtorDtor
.Func
&& CtorDtor
.Func
->hasName() &&
127 "Ctor/Dtor function must be named to be runnable under the JIT");
129 // FIXME: Maybe use a symbol promoter here instead.
130 if (CtorDtor
.Func
->hasLocalLinkage()) {
131 CtorDtor
.Func
->setLinkage(GlobalValue::ExternalLinkage
);
132 CtorDtor
.Func
->setVisibility(GlobalValue::HiddenVisibility
);
135 if (CtorDtor
.Data
&& cast
<GlobalValue
>(CtorDtor
.Data
)->isDeclaration()) {
136 dbgs() << " Skipping because why now?\n";
140 CtorDtorsByPriority
[CtorDtor
.Priority
].push_back(
141 Mangle(CtorDtor
.Func
->getName()));
145 Error
CtorDtorRunner::run() {
146 using CtorDtorTy
= void (*)();
148 SymbolLookupSet LookupSet
;
149 for (auto &KV
: CtorDtorsByPriority
)
150 for (auto &Name
: KV
.second
)
152 assert(!LookupSet
.containsDuplicates() &&
153 "Ctor/Dtor list contains duplicates");
155 auto &ES
= JD
.getExecutionSession();
156 if (auto CtorDtorMap
= ES
.lookup(
157 makeJITDylibSearchOrder(&JD
, JITDylibLookupFlags::MatchAllSymbols
),
158 std::move(LookupSet
))) {
159 for (auto &KV
: CtorDtorsByPriority
) {
160 for (auto &Name
: KV
.second
) {
161 assert(CtorDtorMap
->count(Name
) && "No entry for Name");
162 auto CtorDtor
= (*CtorDtorMap
)[Name
].getAddress().toPtr
<CtorDtorTy
>();
166 CtorDtorsByPriority
.clear();
167 return Error::success();
169 return CtorDtorMap
.takeError();
172 void LocalCXXRuntimeOverridesBase::runDestructors() {
173 auto& CXXDestructorDataPairs
= DSOHandleOverride
;
174 for (auto &P
: CXXDestructorDataPairs
)
176 CXXDestructorDataPairs
.clear();
179 int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor
,
182 auto& CXXDestructorDataPairs
=
183 *reinterpret_cast<CXXDestructorDataPairList
*>(DSOHandle
);
184 CXXDestructorDataPairs
.push_back(std::make_pair(Destructor
, Arg
));
188 Error
LocalCXXRuntimeOverrides::enable(JITDylib
&JD
,
189 MangleAndInterner
&Mangle
) {
190 SymbolMap RuntimeInterposes
;
191 RuntimeInterposes
[Mangle("__dso_handle")] = {
192 ExecutorAddr::fromPtr(&DSOHandleOverride
), JITSymbolFlags::Exported
};
193 RuntimeInterposes
[Mangle("__cxa_atexit")] = {
194 ExecutorAddr::fromPtr(&CXAAtExitOverride
), JITSymbolFlags::Exported
};
196 return JD
.define(absoluteSymbols(std::move(RuntimeInterposes
)));
199 void ItaniumCXAAtExitSupport::registerAtExit(void (*F
)(void *), void *Ctx
,
201 std::lock_guard
<std::mutex
> Lock(AtExitsMutex
);
202 AtExitRecords
[DSOHandle
].push_back({F
, Ctx
});
205 void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle
) {
206 std::vector
<AtExitRecord
> AtExitsToRun
;
209 std::lock_guard
<std::mutex
> Lock(AtExitsMutex
);
210 auto I
= AtExitRecords
.find(DSOHandle
);
211 if (I
!= AtExitRecords
.end()) {
212 AtExitsToRun
= std::move(I
->second
);
213 AtExitRecords
.erase(I
);
217 while (!AtExitsToRun
.empty()) {
218 AtExitsToRun
.back().F(AtExitsToRun
.back().Ctx
);
219 AtExitsToRun
.pop_back();
223 DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
224 sys::DynamicLibrary Dylib
, char GlobalPrefix
, SymbolPredicate Allow
,
225 AddAbsoluteSymbolsFn AddAbsoluteSymbols
)
226 : Dylib(std::move(Dylib
)), Allow(std::move(Allow
)),
227 AddAbsoluteSymbols(std::move(AddAbsoluteSymbols
)),
228 GlobalPrefix(GlobalPrefix
) {}
230 Expected
<std::unique_ptr
<DynamicLibrarySearchGenerator
>>
231 DynamicLibrarySearchGenerator::Load(const char *FileName
, char GlobalPrefix
,
232 SymbolPredicate Allow
,
233 AddAbsoluteSymbolsFn AddAbsoluteSymbols
) {
235 auto Lib
= sys::DynamicLibrary::getPermanentLibrary(FileName
, &ErrMsg
);
237 return make_error
<StringError
>(std::move(ErrMsg
), inconvertibleErrorCode());
238 return std::make_unique
<DynamicLibrarySearchGenerator
>(
239 std::move(Lib
), GlobalPrefix
, std::move(Allow
),
240 std::move(AddAbsoluteSymbols
));
243 Error
DynamicLibrarySearchGenerator::tryToGenerate(
244 LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
245 JITDylibLookupFlags JDLookupFlags
, const SymbolLookupSet
&Symbols
) {
246 orc::SymbolMap NewSymbols
;
248 bool HasGlobalPrefix
= (GlobalPrefix
!= '\0');
250 for (auto &KV
: Symbols
) {
251 auto &Name
= KV
.first
;
256 if (Allow
&& !Allow(Name
))
259 if (HasGlobalPrefix
&& (*Name
).front() != GlobalPrefix
)
262 std::string
Tmp((*Name
).data() + HasGlobalPrefix
,
263 (*Name
).size() - HasGlobalPrefix
);
264 if (void *P
= Dylib
.getAddressOfSymbol(Tmp
.c_str()))
265 NewSymbols
[Name
] = {ExecutorAddr::fromPtr(P
), JITSymbolFlags::Exported
};
268 if (NewSymbols
.empty())
269 return Error::success();
271 if (AddAbsoluteSymbols
)
272 return AddAbsoluteSymbols(JD
, std::move(NewSymbols
));
273 return JD
.define(absoluteSymbols(std::move(NewSymbols
)));
276 StaticLibraryDefinitionGenerator::VisitMembersFunction
277 StaticLibraryDefinitionGenerator::loadAllObjectFileMembers(ObjectLayer
&L
,
279 return [&](MemoryBufferRef Buf
) -> Error
{
280 switch (identify_magic(Buf
.getBuffer())) {
281 case file_magic::elf_relocatable
:
282 case file_magic::macho_object
:
283 case file_magic::coff_object
:
284 return L
.add(JD
, MemoryBuffer::getMemBuffer(Buf
));
286 return Error::success();
291 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
292 StaticLibraryDefinitionGenerator::Load(
293 ObjectLayer
&L
, const char *FileName
, VisitMembersFunction VisitMembers
,
294 GetObjectFileInterface GetObjFileInterface
) {
296 const auto &TT
= L
.getExecutionSession().getTargetTriple();
297 auto Linkable
= loadLinkableFile(FileName
, TT
, LoadArchives::Required
);
299 return Linkable
.takeError();
301 return Create(L
, std::move(Linkable
->first
), std::move(VisitMembers
),
302 std::move(GetObjFileInterface
));
305 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
306 StaticLibraryDefinitionGenerator::Create(
307 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
,
308 std::unique_ptr
<object::Archive
> Archive
, VisitMembersFunction VisitMembers
,
309 GetObjectFileInterface GetObjFileInterface
) {
311 Error Err
= Error::success();
314 for (auto Child
: Archive
->children(Err
)) {
315 if (auto ChildBuf
= Child
.getMemoryBufferRef()) {
316 if (auto Err2
= VisitMembers(*ChildBuf
))
317 return std::move(Err2
);
319 // We silently allow non-object archive members. This matches the
321 consumeError(ChildBuf
.takeError());
325 return std::move(Err
);
328 std::unique_ptr
<StaticLibraryDefinitionGenerator
> ADG(
329 new StaticLibraryDefinitionGenerator(
330 L
, std::move(ArchiveBuffer
), std::move(Archive
),
331 std::move(GetObjFileInterface
), Err
));
334 return std::move(Err
);
336 return std::move(ADG
);
339 Expected
<std::unique_ptr
<StaticLibraryDefinitionGenerator
>>
340 StaticLibraryDefinitionGenerator::Create(
341 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
,
342 VisitMembersFunction VisitMembers
,
343 GetObjectFileInterface GetObjFileInterface
) {
345 auto B
= object::createBinary(ArchiveBuffer
->getMemBufferRef());
347 return B
.takeError();
349 // If this is a regular archive then create an instance from it.
350 if (isa
<object::Archive
>(*B
))
351 return Create(L
, std::move(ArchiveBuffer
),
352 std::unique_ptr
<object::Archive
>(
353 static_cast<object::Archive
*>(B
->release())),
354 std::move(VisitMembers
), std::move(GetObjFileInterface
));
356 // If this is a universal binary then search for a slice matching the given
358 if (auto *UB
= dyn_cast
<object::MachOUniversalBinary
>(B
->get())) {
360 const auto &TT
= L
.getExecutionSession().getTargetTriple();
362 auto SliceRange
= getMachOSliceRangeForTriple(*UB
, TT
);
364 return SliceRange
.takeError();
366 MemoryBufferRef
SliceRef(
367 StringRef(ArchiveBuffer
->getBufferStart() + SliceRange
->first
,
369 ArchiveBuffer
->getBufferIdentifier());
371 auto Archive
= object::Archive::create(SliceRef
);
373 return Archive
.takeError();
375 return Create(L
, std::move(ArchiveBuffer
), std::move(*Archive
),
376 std::move(VisitMembers
), std::move(GetObjFileInterface
));
379 return make_error
<StringError
>(Twine("Unrecognized file type for ") +
380 ArchiveBuffer
->getBufferIdentifier(),
381 inconvertibleErrorCode());
384 Error
StaticLibraryDefinitionGenerator::tryToGenerate(
385 LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
386 JITDylibLookupFlags JDLookupFlags
, const SymbolLookupSet
&Symbols
) {
387 // Don't materialize symbols from static archives unless this is a static
389 if (K
!= LookupKind::Static
)
390 return Error::success();
392 // Bail out early if we've already freed the archive.
394 return Error::success();
396 DenseSet
<std::pair
<StringRef
, StringRef
>> ChildBufferInfos
;
398 for (const auto &KV
: Symbols
) {
399 const auto &Name
= KV
.first
;
400 if (!ObjectFilesMap
.count(Name
))
402 auto ChildBuffer
= ObjectFilesMap
[Name
];
403 ChildBufferInfos
.insert(
404 {ChildBuffer
.getBuffer(), ChildBuffer
.getBufferIdentifier()});
407 for (auto ChildBufferInfo
: ChildBufferInfos
) {
408 MemoryBufferRef
ChildBufferRef(ChildBufferInfo
.first
,
409 ChildBufferInfo
.second
);
411 auto I
= GetObjFileInterface(L
.getExecutionSession(), ChildBufferRef
);
413 return I
.takeError();
415 if (auto Err
= L
.add(JD
, MemoryBuffer::getMemBuffer(ChildBufferRef
, false),
420 return Error::success();
423 Error
StaticLibraryDefinitionGenerator::buildObjectFilesMap() {
424 DenseMap
<uint64_t, MemoryBufferRef
> MemoryBuffers
;
425 DenseSet
<uint64_t> Visited
;
426 DenseSet
<uint64_t> Excluded
;
427 StringSaver
FileNames(ObjFileNameStorage
);
428 for (auto &S
: Archive
->symbols()) {
429 StringRef SymName
= S
.getName();
430 auto Member
= S
.getMember();
432 return Member
.takeError();
433 auto DataOffset
= Member
->getDataOffset();
434 if (!Visited
.count(DataOffset
)) {
435 Visited
.insert(DataOffset
);
436 auto Child
= Member
->getAsBinary();
438 return Child
.takeError();
439 if ((*Child
)->isCOFFImportFile()) {
440 ImportedDynamicLibraries
.insert((*Child
)->getFileName().str());
441 Excluded
.insert(DataOffset
);
445 // Give members of the archive a name that contains the archive path so
446 // that they can be differentiated from a member with the same name in a
447 // different archive. This also ensure initializer symbols names will be
448 // unique within a JITDylib.
449 StringRef FullName
= FileNames
.save(Archive
->getFileName() + "(" +
450 (*Child
)->getFileName() + ")");
451 MemoryBufferRef
MemBuffer((*Child
)->getMemoryBufferRef().getBuffer(),
454 MemoryBuffers
[DataOffset
] = MemBuffer
;
456 if (!Excluded
.count(DataOffset
))
457 ObjectFilesMap
[L
.getExecutionSession().intern(SymName
)] =
458 MemoryBuffers
[DataOffset
];
461 return Error::success();
464 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
465 ObjectLayer
&L
, std::unique_ptr
<MemoryBuffer
> ArchiveBuffer
,
466 std::unique_ptr
<object::Archive
> Archive
,
467 GetObjectFileInterface GetObjFileInterface
, Error
&Err
)
468 : L(L
), GetObjFileInterface(std::move(GetObjFileInterface
)),
469 ArchiveBuffer(std::move(ArchiveBuffer
)), Archive(std::move(Archive
)) {
470 ErrorAsOutParameter
_(&Err
);
471 if (!this->GetObjFileInterface
)
472 this->GetObjFileInterface
= getObjectFileInterface
;
474 Err
= buildObjectFilesMap();
477 std::unique_ptr
<DLLImportDefinitionGenerator
>
478 DLLImportDefinitionGenerator::Create(ExecutionSession
&ES
,
479 ObjectLinkingLayer
&L
) {
480 return std::unique_ptr
<DLLImportDefinitionGenerator
>(
481 new DLLImportDefinitionGenerator(ES
, L
));
484 Error
DLLImportDefinitionGenerator::tryToGenerate(
485 LookupState
&LS
, LookupKind K
, JITDylib
&JD
,
486 JITDylibLookupFlags JDLookupFlags
, const SymbolLookupSet
&Symbols
) {
487 JITDylibSearchOrder LinkOrder
;
488 JD
.withLinkOrderDo([&](const JITDylibSearchOrder
&LO
) {
489 LinkOrder
.reserve(LO
.size());
490 for (auto &KV
: LO
) {
493 LinkOrder
.push_back(KV
);
497 // FIXME: if regular symbol name start with __imp_ we have to issue lookup of
498 // both __imp_ and stripped name and use the lookup information to resolve the
500 SymbolLookupSet LookupSet
;
501 DenseMap
<StringRef
, SymbolLookupFlags
> ToLookUpSymbols
;
502 for (auto &KV
: Symbols
) {
503 StringRef Deinterned
= *KV
.first
;
504 if (Deinterned
.starts_with(getImpPrefix()))
505 Deinterned
= Deinterned
.drop_front(StringRef(getImpPrefix()).size());
506 // Don't degrade the required state
507 if (ToLookUpSymbols
.count(Deinterned
) &&
508 ToLookUpSymbols
[Deinterned
] == SymbolLookupFlags::RequiredSymbol
)
510 ToLookUpSymbols
[Deinterned
] = KV
.second
;
513 for (auto &KV
: ToLookUpSymbols
)
514 LookupSet
.add(ES
.intern(KV
.first
), KV
.second
);
517 ES
.lookup(LinkOrder
, LookupSet
, LookupKind::DLSym
, SymbolState::Resolved
);
519 return Resolved
.takeError();
521 auto G
= createStubsGraph(*Resolved
);
523 return G
.takeError();
524 return L
.add(JD
, std::move(*G
));
528 DLLImportDefinitionGenerator::getTargetPointerSize(const Triple
&TT
) {
529 switch (TT
.getArch()) {
533 return make_error
<StringError
>(
534 "architecture unsupported by DLLImportDefinitionGenerator",
535 inconvertibleErrorCode());
539 Expected
<llvm::endianness
>
540 DLLImportDefinitionGenerator::getEndianness(const Triple
&TT
) {
541 switch (TT
.getArch()) {
543 return llvm::endianness::little
;
545 return make_error
<StringError
>(
546 "architecture unsupported by DLLImportDefinitionGenerator",
547 inconvertibleErrorCode());
551 Expected
<std::unique_ptr
<jitlink::LinkGraph
>>
552 DLLImportDefinitionGenerator::createStubsGraph(const SymbolMap
&Resolved
) {
553 Triple TT
= ES
.getTargetTriple();
554 auto PointerSize
= getTargetPointerSize(TT
);
556 return PointerSize
.takeError();
557 auto Endianness
= getEndianness(TT
);
559 return Endianness
.takeError();
561 auto G
= std::make_unique
<jitlink::LinkGraph
>(
562 "<DLLIMPORT_STUBS>", TT
, *PointerSize
, *Endianness
,
563 jitlink::getGenericEdgeKindName
);
564 jitlink::Section
&Sec
=
565 G
->createSection(getSectionName(), MemProt::Read
| MemProt::Exec
);
567 for (auto &KV
: Resolved
) {
568 jitlink::Symbol
&Target
= G
->addAbsoluteSymbol(
569 *KV
.first
, KV
.second
.getAddress(), *PointerSize
,
570 jitlink::Linkage::Strong
, jitlink::Scope::Local
, false);
572 // Create __imp_ symbol
573 jitlink::Symbol
&Ptr
=
574 jitlink::x86_64::createAnonymousPointer(*G
, Sec
, &Target
);
575 auto NameCopy
= G
->allocateContent(Twine(getImpPrefix()) + *KV
.first
);
576 StringRef NameCopyRef
= StringRef(NameCopy
.data(), NameCopy
.size());
577 Ptr
.setName(NameCopyRef
);
578 Ptr
.setLinkage(jitlink::Linkage::Strong
);
579 Ptr
.setScope(jitlink::Scope::Default
);
582 // FIXME: check PLT stub of data symbol is not accessed
583 jitlink::Block
&StubBlock
=
584 jitlink::x86_64::createPointerJumpStubBlock(*G
, Sec
, Ptr
);
585 G
->addDefinedSymbol(StubBlock
, 0, *KV
.first
, StubBlock
.getSize(),
586 jitlink::Linkage::Strong
, jitlink::Scope::Default
, true,
593 } // End namespace orc.
594 } // End namespace llvm.