clang -cc1 -cc1 -triple amd64-unknown-openbsd7.0 -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name ExecutionUtils.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -mrelocation-model static -mframe-pointer=all -relaxed-aliasing -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fcoverage-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -resource-dir /usr/local/lib/clang/13.0.0 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/AMDGPU -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Analysis -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ASMParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/BinaryFormat -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitcode -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Bitstream -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /include/llvm/CodeGen -I /include/llvm/CodeGen/PBQP -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IR -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Coroutines -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData/Coverage -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/CodeView -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/DWARF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/MSF -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/PDB -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Demangle -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/JITLink -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ExecutionEngine/Orc -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenACC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Frontend/OpenMP -I /include/llvm/CodeGen/GlobalISel -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/IRReader -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/Transforms/InstCombine -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/LTO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Linker -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/MC/MCParser -I /include/llvm/CodeGen/MIRParser -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Object -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Option -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Passes -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ProfileData -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Scalar -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/ADT -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Support -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/DebugInfo/Symbolize -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Target -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Utils -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/Vectorize -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include/llvm/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/Target/X86 -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include/llvm/Transforms/IPO -I /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/include -I /usr/src/gnu/usr.bin/clang/libLLVM/../include -I /usr/src/gnu/usr.bin/clang/libLLVM/obj -I /usr/src/gnu/usr.bin/clang/libLLVM/obj/../include -D NDEBUG -D __STDC_LIMIT_MACROS -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D LLVM_PREFIX="/usr" -internal-isystem /usr/include/c++/v1 -internal-isystem /usr/local/lib/clang/13.0.0/include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/usr/src/gnu/usr.bin/clang/libLLVM/obj -ferror-limit 19 -fvisibility-inlines-hidden -fwrapv -stack-protector 2 -fno-rtti -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -fno-builtin-malloc -fno-builtin-calloc -fno-builtin-realloc -fno-builtin-valloc -fno-builtin-free -fno-builtin-strdup -fno-builtin-strndup -analyzer-output=html -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /home/ben/Projects/vmm/scan-build/2022-01-12-194120-40624-1 -x c++ /usr/src/gnu/usr.bin/clang/libLLVM/../../../llvm/llvm/lib/ExecutionEngine/Orc/ExecutionUtils.cpp
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h" |
| 10 | #include "llvm/ExecutionEngine/Orc/Layer.h" |
| 11 | #include "llvm/IR/Constants.h" |
| 12 | #include "llvm/IR/Function.h" |
| 13 | #include "llvm/IR/GlobalVariable.h" |
| 14 | #include "llvm/IR/Module.h" |
| 15 | #include "llvm/Object/MachOUniversal.h" |
| 16 | #include "llvm/Support/FormatVariadic.h" |
| 17 | #include "llvm/Support/TargetRegistry.h" |
| 18 | #include "llvm/Target/TargetMachine.h" |
| 19 | #include <string> |
| 20 | |
| 21 | namespace llvm { |
| 22 | namespace orc { |
| 23 | |
| 24 | CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End) |
| 25 | : InitList( |
| 26 | GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr), |
| 27 | I((InitList && End) ? InitList->getNumOperands() : 0) { |
| 28 | } |
| 29 | |
| 30 | bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const { |
| 31 | assert(InitList == Other.InitList && "Incomparable iterators."); |
| 32 | return I == Other.I; |
| 33 | } |
| 34 | |
| 35 | bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const { |
| 36 | return !(*this == Other); |
| 37 | } |
| 38 | |
| 39 | CtorDtorIterator& CtorDtorIterator::operator++() { |
| 40 | ++I; |
| 41 | return *this; |
| 42 | } |
| 43 | |
| 44 | CtorDtorIterator CtorDtorIterator::operator++(int) { |
| 45 | CtorDtorIterator Temp = *this; |
| 46 | ++I; |
| 47 | return Temp; |
| 48 | } |
| 49 | |
| 50 | CtorDtorIterator::Element CtorDtorIterator::operator*() const { |
| 51 | ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I)); |
| 4 | | Assuming the object is a 'ConstantStruct' | |
|
| 52 | assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors"); |
| 53 | |
| 54 | Constant *FuncC = CS->getOperand(1); |
| 55 | Function *Func = nullptr; |
| 5 | | 'Func' initialized to a null pointer value | |
|
| 56 | |
| 57 | |
| 58 | while (FuncC) { |
| 6 | | Loop condition is false. Execution continues on line 73 | |
|
| 59 | if (Function *F = dyn_cast_or_null<Function>(FuncC)) { |
| 60 | Func = F; |
| 61 | break; |
| 62 | } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) { |
| 63 | if (CE->isCast()) |
| 64 | FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0)); |
| 65 | else |
| 66 | break; |
| 67 | } else { |
| 68 | |
| 69 | break; |
| 70 | } |
| 71 | } |
| 72 | |
| 73 | auto *Priority = cast<ConstantInt>(CS->getOperand(0)); |
| 74 | Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr; |
| 7 | | Assuming the condition is false | |
|
| |
| 75 | if (Data && !isa<GlobalValue>(Data)) |
| 76 | Data = nullptr; |
| 77 | return Element(Priority->getZExtValue(), Func, Data); |
| 9 | | Passing null pointer value via 2nd parameter 'Func' | |
|
| 10 | | Calling constructor for 'Element' | |
|
| 12 | | Returning from constructor for 'Element' | |
|
| 78 | } |
| 79 | |
| 80 | iterator_range<CtorDtorIterator> getConstructors(const Module &M) { |
| 81 | const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors"); |
| 82 | return make_range(CtorDtorIterator(CtorsList, false), |
| 83 | CtorDtorIterator(CtorsList, true)); |
| 84 | } |
| 85 | |
| 86 | iterator_range<CtorDtorIterator> getDestructors(const Module &M) { |
| 87 | const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors"); |
| 88 | return make_range(CtorDtorIterator(DtorsList, false), |
| 89 | CtorDtorIterator(DtorsList, true)); |
| 90 | } |
| 91 | |
| 92 | bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) { |
| 93 | if (GV.isDeclaration()) |
| 94 | return false; |
| 95 | |
| 96 | if (GV.hasName() && (GV.getName() == "llvm.global_ctors" || |
| 97 | GV.getName() == "llvm.global_dtors")) |
| 98 | return true; |
| 99 | |
| 100 | if (ObjFmt == Triple::MachO) { |
| 101 | |
| 102 | |
| 103 | if (GV.hasSection() && |
| 104 | (GV.getSection().startswith("__DATA,__objc_classlist") || |
| 105 | GV.getSection().startswith("__DATA,__objc_selrefs"))) |
| 106 | return true; |
| 107 | } |
| 108 | |
| 109 | return false; |
| 110 | } |
| 111 | |
| 112 | void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) { |
| 113 | if (CtorDtors.empty()) |
| 1 | Assuming the condition is false | |
|
| |
| 114 | return; |
| 115 | |
| 116 | MangleAndInterner Mangle( |
| 117 | JD.getExecutionSession(), |
| 118 | (*CtorDtors.begin()).Func->getParent()->getDataLayout()); |
| 3 | | Calling 'CtorDtorIterator::operator*' | |
|
| 13 | | Returning from 'CtorDtorIterator::operator*' | |
|
| 14 | | Called C++ object pointer is null |
|
| 119 | |
| 120 | for (auto CtorDtor : CtorDtors) { |
| 121 | assert(CtorDtor.Func && CtorDtor.Func->hasName() && |
| 122 | "Ctor/Dtor function must be named to be runnable under the JIT"); |
| 123 | |
| 124 | |
| 125 | if (CtorDtor.Func->hasLocalLinkage()) { |
| 126 | CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage); |
| 127 | CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility); |
| 128 | } |
| 129 | |
| 130 | if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) { |
| 131 | dbgs() << " Skipping because why now?\n"; |
| 132 | continue; |
| 133 | } |
| 134 | |
| 135 | CtorDtorsByPriority[CtorDtor.Priority].push_back( |
| 136 | Mangle(CtorDtor.Func->getName())); |
| 137 | } |
| 138 | } |
| 139 | |
| 140 | Error CtorDtorRunner::run() { |
| 141 | using CtorDtorTy = void (*)(); |
| 142 | |
| 143 | SymbolLookupSet LookupSet; |
| 144 | for (auto &KV : CtorDtorsByPriority) |
| 145 | for (auto &Name : KV.second) |
| 146 | LookupSet.add(Name); |
| 147 | assert(!LookupSet.containsDuplicates() && |
| 148 | "Ctor/Dtor list contains duplicates"); |
| 149 | |
| 150 | auto &ES = JD.getExecutionSession(); |
| 151 | if (auto CtorDtorMap = ES.lookup( |
| 152 | makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols), |
| 153 | std::move(LookupSet))) { |
| 154 | for (auto &KV : CtorDtorsByPriority) { |
| 155 | for (auto &Name : KV.second) { |
| 156 | assert(CtorDtorMap->count(Name) && "No entry for Name"); |
| 157 | auto CtorDtor = reinterpret_cast<CtorDtorTy>( |
| 158 | static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress())); |
| 159 | CtorDtor(); |
| 160 | } |
| 161 | } |
| 162 | CtorDtorsByPriority.clear(); |
| 163 | return Error::success(); |
| 164 | } else |
| 165 | return CtorDtorMap.takeError(); |
| 166 | } |
| 167 | |
| 168 | void LocalCXXRuntimeOverridesBase::runDestructors() { |
| 169 | auto& CXXDestructorDataPairs = DSOHandleOverride; |
| 170 | for (auto &P : CXXDestructorDataPairs) |
| 171 | P.first(P.second); |
| 172 | CXXDestructorDataPairs.clear(); |
| 173 | } |
| 174 | |
| 175 | int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor, |
| 176 | void *Arg, |
| 177 | void *DSOHandle) { |
| 178 | auto& CXXDestructorDataPairs = |
| 179 | *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle); |
| 180 | CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg)); |
| 181 | return 0; |
| 182 | } |
| 183 | |
| 184 | Error LocalCXXRuntimeOverrides::enable(JITDylib &JD, |
| 185 | MangleAndInterner &Mangle) { |
| 186 | SymbolMap RuntimeInterposes; |
| 187 | RuntimeInterposes[Mangle("__dso_handle")] = |
| 188 | JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride), |
| 189 | JITSymbolFlags::Exported); |
| 190 | RuntimeInterposes[Mangle("__cxa_atexit")] = |
| 191 | JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride), |
| 192 | JITSymbolFlags::Exported); |
| 193 | |
| 194 | return JD.define(absoluteSymbols(std::move(RuntimeInterposes))); |
| 195 | } |
| 196 | |
| 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 | |
| 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 | |
| 221 | DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator( |
| 222 | sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow) |
| 223 | : Dylib(std::move(Dylib)), Allow(std::move(Allow)), |
| 224 | GlobalPrefix(GlobalPrefix) {} |
| 225 | |
| 226 | Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> |
| 227 | DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix, |
| 228 | SymbolPredicate Allow) { |
| 229 | std::string ErrMsg; |
| 230 | auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg); |
| 231 | if (!Lib.isValid()) |
| 232 | return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode()); |
| 233 | return std::make_unique<DynamicLibrarySearchGenerator>( |
| 234 | std::move(Lib), GlobalPrefix, std::move(Allow)); |
| 235 | } |
| 236 | |
| 237 | Error DynamicLibrarySearchGenerator::tryToGenerate( |
| 238 | LookupState &LS, LookupKind K, JITDylib &JD, |
| 239 | JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { |
| 240 | orc::SymbolMap NewSymbols; |
| 241 | |
| 242 | bool HasGlobalPrefix = (GlobalPrefix != '\0'); |
| 243 | |
| 244 | for (auto &KV : Symbols) { |
| 245 | auto &Name = KV.first; |
| 246 | |
| 247 | if ((*Name).empty()) |
| 248 | continue; |
| 249 | |
| 250 | if (Allow && !Allow(Name)) |
| 251 | continue; |
| 252 | |
| 253 | if (HasGlobalPrefix && (*Name).front() != GlobalPrefix) |
| 254 | continue; |
| 255 | |
| 256 | std::string Tmp((*Name).data() + HasGlobalPrefix, |
| 257 | (*Name).size() - HasGlobalPrefix); |
| 258 | if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) { |
| 259 | NewSymbols[Name] = JITEvaluatedSymbol( |
| 260 | static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)), |
| 261 | JITSymbolFlags::Exported); |
| 262 | } |
| 263 | } |
| 264 | |
| 265 | if (NewSymbols.empty()) |
| 266 | return Error::success(); |
| 267 | |
| 268 | return JD.define(absoluteSymbols(std::move(NewSymbols))); |
| 269 | } |
| 270 | |
| 271 | Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> |
| 272 | StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) { |
| 273 | auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName)); |
| 274 | |
| 275 | if (!ArchiveBuffer) |
| 276 | return ArchiveBuffer.takeError(); |
| 277 | |
| 278 | return Create(L, std::move(*ArchiveBuffer)); |
| 279 | } |
| 280 | |
| 281 | Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> |
| 282 | StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName, |
| 283 | const Triple &TT) { |
| 284 | auto B = object::createBinary(FileName); |
| 285 | if (!B) |
| 286 | return B.takeError(); |
| 287 | |
| 288 | |
| 289 | if (isa<object::Archive>(B->getBinary())) |
| 290 | return Create(L, std::move(B->takeBinary().second)); |
| 291 | |
| 292 | |
| 293 | |
| 294 | if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) { |
| 295 | for (const auto &Obj : UB->objects()) { |
| 296 | auto ObjTT = Obj.getTriple(); |
| 297 | if (ObjTT.getArch() == TT.getArch() && |
| 298 | ObjTT.getSubArch() == TT.getSubArch() && |
| 299 | (TT.getVendor() == Triple::UnknownVendor || |
| 300 | ObjTT.getVendor() == TT.getVendor())) { |
| 301 | |
| 302 | |
| 303 | auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(), |
| 304 | Obj.getOffset()); |
| 305 | if (!SliceBuffer) |
| 306 | return make_error<StringError>( |
| 307 | Twine("Could not create buffer for ") + TT.str() + " slice of " + |
| 308 | FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) + |
| 309 | " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) + |
| 310 | ": " + SliceBuffer.getError().message(), |
| 311 | SliceBuffer.getError()); |
| 312 | return Create(L, std::move(*SliceBuffer)); |
| 313 | } |
| 314 | } |
| 315 | |
| 316 | return make_error<StringError>(Twine("Universal binary ") + FileName + |
| 317 | " does not contain a slice for " + |
| 318 | TT.str(), |
| 319 | inconvertibleErrorCode()); |
| 320 | } |
| 321 | |
| 322 | return make_error<StringError>(Twine("Unrecognized file type for ") + |
| 323 | FileName, |
| 324 | inconvertibleErrorCode()); |
| 325 | } |
| 326 | |
| 327 | Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> |
| 328 | StaticLibraryDefinitionGenerator::Create( |
| 329 | ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) { |
| 330 | Error Err = Error::success(); |
| 331 | |
| 332 | std::unique_ptr<StaticLibraryDefinitionGenerator> ADG( |
| 333 | new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err)); |
| 334 | |
| 335 | if (Err) |
| 336 | return std::move(Err); |
| 337 | |
| 338 | return std::move(ADG); |
| 339 | } |
| 340 | |
| 341 | Error StaticLibraryDefinitionGenerator::tryToGenerate( |
| 342 | LookupState &LS, LookupKind K, JITDylib &JD, |
| 343 | JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) { |
| 344 | |
| 345 | |
| 346 | |
| 347 | if (K != LookupKind::Static) |
| 348 | return Error::success(); |
| 349 | |
| 350 | |
| 351 | if (!Archive) |
| 352 | return Error::success(); |
| 353 | |
| 354 | DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos; |
| 355 | |
| 356 | for (const auto &KV : Symbols) { |
| 357 | const auto &Name = KV.first; |
| 358 | auto Child = Archive->findSym(*Name); |
| 359 | if (!Child) |
| 360 | return Child.takeError(); |
| 361 | if (*Child == None) |
| 362 | continue; |
| 363 | auto ChildBuffer = (*Child)->getMemoryBufferRef(); |
| 364 | if (!ChildBuffer) |
| 365 | return ChildBuffer.takeError(); |
| 366 | ChildBufferInfos.insert( |
| 367 | {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()}); |
| 368 | } |
| 369 | |
| 370 | for (auto ChildBufferInfo : ChildBufferInfos) { |
| 371 | MemoryBufferRef ChildBufferRef(ChildBufferInfo.first, |
| 372 | ChildBufferInfo.second); |
| 373 | |
| 374 | if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false))) |
| 375 | return Err; |
| 376 | } |
| 377 | |
| 378 | return Error::success(); |
| 379 | } |
| 380 | |
| 381 | StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator( |
| 382 | ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err) |
| 383 | : L(L), ArchiveBuffer(std::move(ArchiveBuffer)), |
| 384 | Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {} |
| 385 | |
| 386 | } |
| 387 | } |
| 1 | |
| 2 | |
| 3 | |
| 4 | |
| 5 | |
| 6 | |
| 7 | |
| 8 | |
| 9 | |
| 10 | |
| 11 | |
| 12 | |
| 13 | #ifndef LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H |
| 14 | #define LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H |
| 15 | |
| 16 | #include "llvm/ADT/StringMap.h" |
| 17 | #include "llvm/ADT/iterator_range.h" |
| 18 | #include "llvm/ExecutionEngine/JITSymbol.h" |
| 19 | #include "llvm/ExecutionEngine/Orc/Core.h" |
| 20 | #include "llvm/ExecutionEngine/Orc/Mangling.h" |
| 21 | #include "llvm/ExecutionEngine/Orc/Shared/OrcError.h" |
| 22 | #include "llvm/ExecutionEngine/RuntimeDyld.h" |
| 23 | #include "llvm/Object/Archive.h" |
| 24 | #include "llvm/Support/DynamicLibrary.h" |
| 25 | #include <algorithm> |
| 26 | #include <cstdint> |
| 27 | #include <utility> |
| 28 | #include <vector> |
| 29 | |
| 30 | namespace llvm { |
| 31 | |
| 32 | class ConstantArray; |
| 33 | class GlobalVariable; |
| 34 | class Function; |
| 35 | class Module; |
| 36 | class TargetMachine; |
| 37 | class Value; |
| 38 | |
| 39 | namespace orc { |
| 40 | |
| 41 | class ObjectLayer; |
| 42 | |
| 43 | |
| 44 | |
| 45 | |
| 46 | |
| 47 | |
| 48 | class CtorDtorIterator { |
| 49 | public: |
| 50 | |
| 51 | |
| 52 | |
| 53 | |
| 54 | struct Element { |
| 55 | Element(unsigned Priority, Function *Func, Value *Data) |
| 56 | : Priority(Priority), Func(Func), Data(Data) {} |
| 11 | | Null pointer value stored to field 'Func' | |
|
| 57 | |
| 58 | unsigned Priority; |
| 59 | Function *Func; |
| 60 | Value *Data; |
| 61 | }; |
| 62 | |
| 63 | |
| 64 | |
| 65 | CtorDtorIterator(const GlobalVariable *GV, bool End); |
| 66 | |
| 67 | |
| 68 | bool operator==(const CtorDtorIterator &Other) const; |
| 69 | |
| 70 | |
| 71 | bool operator!=(const CtorDtorIterator &Other) const; |
| 72 | |
| 73 | |
| 74 | CtorDtorIterator& operator++(); |
| 75 | |
| 76 | |
| 77 | CtorDtorIterator operator++(int); |
| 78 | |
| 79 | |
| 80 | |
| 81 | Element operator*() const; |
| 82 | |
| 83 | private: |
| 84 | const ConstantArray *InitList; |
| 85 | unsigned I; |
| 86 | }; |
| 87 | |
| 88 | |
| 89 | |
| 90 | iterator_range<CtorDtorIterator> getConstructors(const Module &M); |
| 91 | |
| 92 | |
| 93 | |
| 94 | iterator_range<CtorDtorIterator> getDestructors(const Module &M); |
| 95 | |
| 96 | |
| 97 | |
| 98 | class StaticInitGVIterator { |
| 99 | public: |
| 100 | StaticInitGVIterator() = default; |
| 101 | |
| 102 | StaticInitGVIterator(Module &M) |
| 103 | : I(M.global_values().begin()), E(M.global_values().end()), |
| 104 | ObjFmt(Triple(M.getTargetTriple()).getObjectFormat()) { |
| 105 | if (I != E) { |
| 106 | if (!isStaticInitGlobal(*I)) |
| 107 | moveToNextStaticInitGlobal(); |
| 108 | } else |
| 109 | I = E = Module::global_value_iterator(); |
| 110 | } |
| 111 | |
| 112 | bool operator==(const StaticInitGVIterator &O) const { return I == O.I; } |
| 113 | bool operator!=(const StaticInitGVIterator &O) const { return I != O.I; } |
| 114 | |
| 115 | StaticInitGVIterator &operator++() { |
| 116 | assert(I != E && "Increment past end of range"); |
| 117 | moveToNextStaticInitGlobal(); |
| 118 | return *this; |
| 119 | } |
| 120 | |
| 121 | GlobalValue &operator*() { return *I; } |
| 122 | |
| 123 | private: |
| 124 | bool isStaticInitGlobal(GlobalValue &GV); |
| 125 | void moveToNextStaticInitGlobal() { |
| 126 | ++I; |
| 127 | while (I != E && !isStaticInitGlobal(*I)) |
| 128 | ++I; |
| 129 | if (I == E) |
| 130 | I = E = Module::global_value_iterator(); |
| 131 | } |
| 132 | |
| 133 | Module::global_value_iterator I, E; |
| 134 | Triple::ObjectFormatType ObjFmt; |
| 135 | }; |
| 136 | |
| 137 | |
| 138 | |
| 139 | inline iterator_range<StaticInitGVIterator> getStaticInitGVs(Module &M) { |
| 140 | return make_range(StaticInitGVIterator(M), StaticInitGVIterator()); |
| 141 | } |
| 142 | |
| 143 | class CtorDtorRunner { |
| 144 | public: |
| 145 | CtorDtorRunner(JITDylib &JD) : JD(JD) {} |
| 146 | void add(iterator_range<CtorDtorIterator> CtorDtors); |
| 147 | Error run(); |
| 148 | |
| 149 | private: |
| 150 | using CtorDtorList = std::vector<SymbolStringPtr>; |
| 151 | using CtorDtorPriorityMap = std::map<unsigned, CtorDtorList>; |
| 152 | |
| 153 | JITDylib &JD; |
| 154 | CtorDtorPriorityMap CtorDtorsByPriority; |
| 155 | }; |
| 156 | |
| 157 | |
| 158 | |
| 159 | |
| 160 | |
| 161 | |
| 162 | |
| 163 | |
| 164 | |
| 165 | |
| 166 | |
| 167 | |
| 168 | |
| 169 | |
| 170 | |
| 171 | |
| 172 | class LocalCXXRuntimeOverridesBase { |
| 173 | public: |
| 174 | |
| 175 | |
| 176 | void runDestructors(); |
| 177 | |
| 178 | protected: |
| 179 | template <typename PtrTy> JITTargetAddress toTargetAddress(PtrTy *P) { |
| 180 | return static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(P)); |
| 181 | } |
| 182 | |
| 183 | using DestructorPtr = void (*)(void *); |
| 184 | using CXXDestructorDataPair = std::pair<DestructorPtr, void *>; |
| 185 | using CXXDestructorDataPairList = std::vector<CXXDestructorDataPair>; |
| 186 | CXXDestructorDataPairList DSOHandleOverride; |
| 187 | static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, |
| 188 | void *DSOHandle); |
| 189 | }; |
| 190 | |
| 191 | class LocalCXXRuntimeOverrides : public LocalCXXRuntimeOverridesBase { |
| 192 | public: |
| 193 | Error enable(JITDylib &JD, MangleAndInterner &Mangler); |
| 194 | }; |
| 195 | |
| 196 | |
| 197 | class ItaniumCXAAtExitSupport { |
| 198 | public: |
| 199 | struct AtExitRecord { |
| 200 | void (*F)(void *); |
| 201 | void *Ctx; |
| 202 | }; |
| 203 | |
| 204 | void registerAtExit(void (*F)(void *), void *Ctx, void *DSOHandle); |
| 205 | void runAtExits(void *DSOHandle); |
| 206 | |
| 207 | private: |
| 208 | std::mutex AtExitsMutex; |
| 209 | DenseMap<void *, std::vector<AtExitRecord>> AtExitRecords; |
| 210 | }; |
| 211 | |
| 212 | |
| 213 | |
| 214 | |
| 215 | |
| 216 | |
| 217 | class DynamicLibrarySearchGenerator : public DefinitionGenerator { |
| 218 | public: |
| 219 | using SymbolPredicate = std::function<bool(const SymbolStringPtr &)>; |
| 220 | |
| 221 | |
| 222 | |
| 223 | |
| 224 | |
| 225 | |
| 226 | |
| 227 | DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix, |
| 228 | SymbolPredicate Allow = SymbolPredicate()); |
| 229 | |
| 230 | |
| 231 | |
| 232 | |
| 233 | static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> |
| 234 | Load(const char *FileName, char GlobalPrefix, |
| 235 | SymbolPredicate Allow = SymbolPredicate()); |
| 236 | |
| 237 | |
| 238 | |
| 239 | static Expected<std::unique_ptr<DynamicLibrarySearchGenerator>> |
| 240 | GetForCurrentProcess(char GlobalPrefix, |
| 241 | SymbolPredicate Allow = SymbolPredicate()) { |
| 242 | return Load(nullptr, GlobalPrefix, std::move(Allow)); |
| 243 | } |
| 244 | |
| 245 | Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, |
| 246 | JITDylibLookupFlags JDLookupFlags, |
| 247 | const SymbolLookupSet &Symbols) override; |
| 248 | |
| 249 | private: |
| 250 | sys::DynamicLibrary Dylib; |
| 251 | SymbolPredicate Allow; |
| 252 | char GlobalPrefix; |
| 253 | }; |
| 254 | |
| 255 | |
| 256 | |
| 257 | |
| 258 | |
| 259 | |
| 260 | class StaticLibraryDefinitionGenerator : public DefinitionGenerator { |
| 261 | public: |
| 262 | |
| 263 | |
| 264 | |
| 265 | |
| 266 | static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> |
| 267 | Load(ObjectLayer &L, const char *FileName); |
| 268 | |
| 269 | |
| 270 | |
| 271 | |
| 272 | |
| 273 | |
| 274 | static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> |
| 275 | Load(ObjectLayer &L, const char *FileName, const Triple &TT); |
| 276 | |
| 277 | |
| 278 | |
| 279 | |
| 280 | static Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> |
| 281 | Create(ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer); |
| 282 | |
| 283 | Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD, |
| 284 | JITDylibLookupFlags JDLookupFlags, |
| 285 | const SymbolLookupSet &Symbols) override; |
| 286 | |
| 287 | private: |
| 288 | StaticLibraryDefinitionGenerator(ObjectLayer &L, |
| 289 | std::unique_ptr<MemoryBuffer> ArchiveBuffer, |
| 290 | Error &Err); |
| 291 | |
| 292 | ObjectLayer &L; |
| 293 | std::unique_ptr<MemoryBuffer> ArchiveBuffer; |
| 294 | std::unique_ptr<object::Archive> Archive; |
| 295 | }; |
| 296 | |
| 297 | } |
| 298 | } |
| 299 | |
| 300 | #endif // LLVM_EXECUTIONENGINE_ORC_EXECUTIONUTILS_H |