LLVM  12.0.0git
ExecutionUtils.cpp
Go to the documentation of this file.
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 
10 
12 #include "llvm/IR/Constants.h"
13 #include "llvm/IR/Function.h"
14 #include "llvm/IR/GlobalVariable.h"
15 #include "llvm/IR/Module.h"
20 
21 namespace llvm {
22 namespace orc {
23 
24 int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
25  Optional<StringRef> ProgramName) {
26  std::vector<std::unique_ptr<char[]>> ArgVStorage;
27  std::vector<char *> ArgV;
28 
29  ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
30  ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
31 
32  if (ProgramName) {
33  ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1));
34  llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
35  ArgVStorage.back()[ProgramName->size()] = '\0';
36  ArgV.push_back(ArgVStorage.back().get());
37  }
38 
39  for (auto &Arg : Args) {
40  ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
41  llvm::copy(Arg, &ArgVStorage.back()[0]);
42  ArgVStorage.back()[Arg.size()] = '\0';
43  ArgV.push_back(ArgVStorage.back().get());
44  }
45  ArgV.push_back(nullptr);
46 
47  return Main(Args.size() + !!ProgramName, ArgV.data());
48 }
49 
51  : InitList(
52  GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
53  I((InitList && End) ? InitList->getNumOperands() : 0) {
54 }
55 
57  assert(InitList == Other.InitList && "Incomparable iterators.");
58  return I == Other.I;
59 }
60 
62  return !(*this == Other);
63 }
64 
66  ++I;
67  return *this;
68 }
69 
71  CtorDtorIterator Temp = *this;
72  ++I;
73  return Temp;
74 }
75 
77  ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
78  assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
79 
80  Constant *FuncC = CS->getOperand(1);
81  Function *Func = nullptr;
82 
83  // Extract function pointer, pulling off any casts.
84  while (FuncC) {
85  if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
86  Func = F;
87  break;
88  } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
89  if (CE->isCast())
90  FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
91  else
92  break;
93  } else {
94  // This isn't anything we recognize. Bail out with Func left set to null.
95  break;
96  }
97  }
98 
99  auto *Priority = cast<ConstantInt>(CS->getOperand(0));
100  Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
101  if (Data && !isa<GlobalValue>(Data))
102  Data = nullptr;
103  return Element(Priority->getZExtValue(), Func, Data);
104 }
105 
107  const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
108  return make_range(CtorDtorIterator(CtorsList, false),
109  CtorDtorIterator(CtorsList, true));
110 }
111 
113  const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
114  return make_range(CtorDtorIterator(DtorsList, false),
115  CtorDtorIterator(DtorsList, true));
116 }
117 
118 bool StaticInitGVIterator::isStaticInitGlobal(GlobalValue &GV) {
119  if (GV.isDeclaration())
120  return false;
121 
122  if (GV.hasName() && (GV.getName() == "llvm.global_ctors" ||
123  GV.getName() == "llvm.global_dtors"))
124  return true;
125 
126  if (ObjFmt == Triple::MachO) {
127  // FIXME: These section checks are too strict: We should match first and
128  // second word split by comma.
129  if (GV.hasSection() &&
130  (GV.getSection().startswith("__DATA,__objc_classlist") ||
131  GV.getSection().startswith("__DATA,__objc_selrefs")))
132  return true;
133  }
134 
135  return false;
136 }
137 
139  if (CtorDtors.empty())
140  return;
141 
142  MangleAndInterner Mangle(
143  JD.getExecutionSession(),
144  (*CtorDtors.begin()).Func->getParent()->getDataLayout());
145 
146  for (auto CtorDtor : CtorDtors) {
147  assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
148  "Ctor/Dtor function must be named to be runnable under the JIT");
149 
150  // FIXME: Maybe use a symbol promoter here instead.
151  if (CtorDtor.Func->hasLocalLinkage()) {
152  CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
153  CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
154  }
155 
156  if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
157  dbgs() << " Skipping because why now?\n";
158  continue;
159  }
160 
161  CtorDtorsByPriority[CtorDtor.Priority].push_back(
162  Mangle(CtorDtor.Func->getName()));
163  }
164 }
165 
167  using CtorDtorTy = void (*)();
168 
169  SymbolLookupSet LookupSet;
170  for (auto &KV : CtorDtorsByPriority)
171  for (auto &Name : KV.second)
172  LookupSet.add(Name);
173  assert(!LookupSet.containsDuplicates() &&
174  "Ctor/Dtor list contains duplicates");
175 
176  auto &ES = JD.getExecutionSession();
177  if (auto CtorDtorMap = ES.lookup(
179  std::move(LookupSet))) {
180  for (auto &KV : CtorDtorsByPriority) {
181  for (auto &Name : KV.second) {
182  assert(CtorDtorMap->count(Name) && "No entry for Name");
183  auto CtorDtor = reinterpret_cast<CtorDtorTy>(
184  static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
185  CtorDtor();
186  }
187  }
188  CtorDtorsByPriority.clear();
189  return Error::success();
190  } else
191  return CtorDtorMap.takeError();
192 }
193 
195  auto& CXXDestructorDataPairs = DSOHandleOverride;
196  for (auto &P : CXXDestructorDataPairs)
197  P.first(P.second);
198  CXXDestructorDataPairs.clear();
199 }
200 
202  void *Arg,
203  void *DSOHandle) {
204  auto& CXXDestructorDataPairs =
205  *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
206  CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
207  return 0;
208 }
209 
211  MangleAndInterner &Mangle) {
212  SymbolMap RuntimeInterposes;
213  RuntimeInterposes[Mangle("__dso_handle")] =
214  JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
216  RuntimeInterposes[Mangle("__cxa_atexit")] =
217  JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
219 
220  return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
221 }
222 
223 void ItaniumCXAAtExitSupport::registerAtExit(void (*F)(void *), void *Ctx,
224  void *DSOHandle) {
225  std::lock_guard<std::mutex> Lock(AtExitsMutex);
226  AtExitRecords[DSOHandle].push_back({F, Ctx});
227 }
228 
229 void ItaniumCXAAtExitSupport::runAtExits(void *DSOHandle) {
230  std::vector<AtExitRecord> AtExitsToRun;
231 
232  {
233  std::lock_guard<std::mutex> Lock(AtExitsMutex);
234  auto I = AtExitRecords.find(DSOHandle);
235  if (I != AtExitRecords.end()) {
236  AtExitsToRun = std::move(I->second);
237  AtExitRecords.erase(I);
238  }
239  }
240 
241  while (!AtExitsToRun.empty()) {
242  AtExitsToRun.back().F(AtExitsToRun.back().Ctx);
243  AtExitsToRun.pop_back();
244  }
245 }
246 
249  : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
250  GlobalPrefix(GlobalPrefix) {}
251 
253 DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
254  SymbolPredicate Allow) {
255  std::string ErrMsg;
256  auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
257  if (!Lib.isValid())
258  return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
259  return std::make_unique<DynamicLibrarySearchGenerator>(
260  std::move(Lib), GlobalPrefix, std::move(Allow));
261 }
262 
264  LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
265  const SymbolLookupSet &Symbols) {
266  orc::SymbolMap NewSymbols;
267 
268  bool HasGlobalPrefix = (GlobalPrefix != '\0');
269 
270  for (auto &KV : Symbols) {
271  auto &Name = KV.first;
272 
273  if ((*Name).empty())
274  continue;
275 
276  if (Allow && !Allow(Name))
277  continue;
278 
279  if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
280  continue;
281 
282  std::string Tmp((*Name).data() + HasGlobalPrefix,
283  (*Name).size() - HasGlobalPrefix);
284  if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
285  NewSymbols[Name] = JITEvaluatedSymbol(
286  static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
288  }
289  }
290 
291  if (NewSymbols.empty())
292  return Error::success();
293 
294  return JD.define(absoluteSymbols(std::move(NewSymbols)));
295 }
296 
299  auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName));
300 
301  if (!ArchiveBuffer)
302  return ArchiveBuffer.takeError();
303 
304  return Create(L, std::move(*ArchiveBuffer));
305 }
306 
309  const Triple &TT) {
310  auto B = object::createBinary(FileName);
311  if (!B)
312  return B.takeError();
313 
314  // If this is a regular archive then create an instance from it.
315  if (isa<object::Archive>(B->getBinary()))
316  return Create(L, std::move(B->takeBinary().second));
317 
318  // If this is a universal binary then search for a slice matching the given
319  // Triple.
320  if (auto *UB = cast<object::MachOUniversalBinary>(B->getBinary())) {
321  for (const auto &Obj : UB->objects()) {
322  auto ObjTT = Obj.getTriple();
323  if (ObjTT.getArch() == TT.getArch() &&
324  ObjTT.getSubArch() == TT.getSubArch() &&
325  ObjTT.getVendor() == TT.getVendor()) {
326  // We found a match. Create an instance from a buffer covering this
327  // slice.
328  auto SliceBuffer = MemoryBuffer::getFileSlice(FileName, Obj.getSize(),
329  Obj.getOffset());
330  if (!SliceBuffer)
331  return make_error<StringError>(
332  Twine("Could not create buffer for ") + TT.str() + " slice of " +
333  FileName + ": [ " + formatv("{0:x}", Obj.getOffset()) +
334  " .. " + formatv("{0:x}", Obj.getOffset() + Obj.getSize()) +
335  ": " + SliceBuffer.getError().message(),
336  SliceBuffer.getError());
337  return Create(L, std::move(*SliceBuffer));
338  }
339  }
340 
341  return make_error<StringError>(Twine("Universal binary ") + FileName +
342  " does not contain a slice for " +
343  TT.str(),
345  }
346 
347  return make_error<StringError>(Twine("Unrecognized file type for ") +
348  FileName,
350 }
351 
354  ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
355  Error Err = Error::success();
356 
357  std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
358  new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err));
359 
360  if (Err)
361  return std::move(Err);
362 
363  return std::move(ADG);
364 }
365 
367  LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
368  const SymbolLookupSet &Symbols) {
369 
370  // Don't materialize symbols from static archives unless this is a static
371  // lookup.
372  if (K != LookupKind::Static)
373  return Error::success();
374 
375  // Bail out early if we've already freed the archive.
376  if (!Archive)
377  return Error::success();
378 
380 
381  for (const auto &KV : Symbols) {
382  const auto &Name = KV.first;
383  auto Child = Archive->findSym(*Name);
384  if (!Child)
385  return Child.takeError();
386  if (*Child == None)
387  continue;
388  auto ChildBuffer = (*Child)->getMemoryBufferRef();
389  if (!ChildBuffer)
390  return ChildBuffer.takeError();
391  ChildBufferInfos.insert(
392  {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
393  }
394 
395  for (auto ChildBufferInfo : ChildBufferInfos) {
396  MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
397  ChildBufferInfo.second);
398 
399  if (auto Err = L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef, false),
400  VModuleKey()))
401  return Err;
402  }
403 
404  return Error::success();
405 }
406 
407 StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
408  ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err)
409  : L(L), ArchiveBuffer(std::move(ArchiveBuffer)),
410  Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {}
411 
412 } // End namespace orc.
413 } // End namespace llvm.
static Expected< std::unique_ptr< DynamicLibrarySearchGenerator > > Load(const char *FileName, char GlobalPrefix, SymbolPredicate Allow=SymbolPredicate())
Permanently loads the library at the given path and, on success, returns a DynamicLibrarySearchGenera...
const NoneType None
Definition: None.h:23
LLVM_NODISCARD std::enable_if_t< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast(const Y &Val)
Definition: Casting.h:334
Accessor for an element of the global_ctors/global_dtors array.
LookupKind
Describes the kind of lookup being performed.
Definition: Core.h:87
This class represents lattice values for constants.
Definition: AllocatorList.h:23
void registerAtExit(void(*F)(void *), void *Ctx, void *DSOHandle)
bool operator==(const CtorDtorIterator &Other) const
Test iterators for equality.
A Module instance is used to store all the information related to an LLVM module. ...
Definition: Module.h:67
amdgpu Simplify well known AMD library false FunctionCallee Value const Twine & Name
std::function< bool(const SymbolStringPtr &)> SymbolPredicate
LLVM_NODISCARD bool startswith(StringRef Prefix) const
Check if this string starts with the given Prefix.
Definition: StringRef.h:289
Implements a dense probed hash-table based set.
Definition: DenseSet.h:255
static std::unique_ptr< MemoryBuffer > getMemBuffer(StringRef InputData, StringRef BufferName="", bool RequiresNullTerminator=true)
Open the specified memory range as a MemoryBuffer.
static sys::Mutex Lock
const GlobalVariable * getNamedGlobal(StringRef Name) const
Return the global variable in the module with the specified name, of arbitrary type.
Definition: Module.h:414
Externally visible function.
Definition: GlobalValue.h:48
auto formatv(const char *Fmt, Ts &&... Vals) -> formatv_object< decltype(std::make_tuple(detail::build_format_adapter(std::forward< Ts >(Vals))...))>
F(f)
std::vector< CXXDestructorDataPair > CXXDestructorDataPairList
Error enable(JITDylib &JD, MangleAndInterner &Mangler)
Expected< std::unique_ptr< Binary > > createBinary(MemoryBufferRef Source, LLVMContext *Context=nullptr)
Create a Binary from Source, autodetecting the file type.
Definition: Binary.cpp:46
CtorDtorIterator & operator++()
Pre-increment iterator.
bool hasSection() const
Definition: GlobalValue.h:267
std::unique_ptr< AbsoluteSymbolsMaterializationUnit > absoluteSymbols(SymbolMap Symbols, VModuleKey K=VModuleKey())
Create an AbsoluteSymbolsMaterializationUnit with the given symbols.
Definition: Core.h:642
Definition: BitVector.h:959
Twine - A lightweight data structure for efficiently representing the concatenation of temporary valu...
Definition: Twine.h:80
A utility class to expose symbols from a static library.
Error define(std::unique_ptr< MaterializationUnitType > &&MU)
Define all symbols provided by the materialization unit to be part of this JITDylib.
Definition: Core.h:1311
Mangles symbol names then uniques them in the context of an ExecutionSession.
Definition: Mangling.h:26
void * getAddressOfSymbol(const char *symbolName)
Searches through the library for the symbol symbolName.
Tagged union holding either a T or a Error.
Definition: APFloat.h:42
void add(iterator_range< CtorDtorIterator > CtorDtors)
This class provides a portable interface to dynamic libraries which also might be known as shared lib...
SubArchType getSubArch() const
getSubArch - get the parsed subarchitecture type for this triple.
Definition: Triple.h:303
A constant value that is initialized with an expression using other constant values.
Definition: Constants.h:899
iterator_range< CtorDtorIterator > getDestructors(const Module &M)
Create an iterator range over the entries of the llvm.global_ctors array.
ArchType getArch() const
getArch - Get the parsed architecture type of this triple.
Definition: Triple.h:300
CtorDtorIterator(const GlobalVariable *GV, bool End)
Construct an iterator instance.
ArrayRef - Represent a constant reference to an array (0 or more elements consecutively in memory)...
Definition: APInt.h:32
DynamicLibrarySearchGenerator(sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow=SymbolPredicate())
Create a DynamicLibrarySearchGenerator that searches for symbols in the given sys::DynamicLibrary.
const std::string & str() const
Definition: Triple.h:369
Value * getOperand(unsigned i) const
Definition: User.h:169
bool containsDuplicates()
Returns true if this set contains any duplicates.
Definition: Core.h:283
#define P(N)
static GCRegistry::Add< OcamlGC > B("ocaml", "ocaml 3.10-compatible GC")
bool hasName() const
Definition: Value.h:250
VendorType getVendor() const
getVendor - Get the parsed vendor type of this triple.
Definition: Triple.h:306
size_t size() const
size - Get the array size.
Definition: ArrayRef.h:156
This is an important base class in LLVM.
Definition: Constant.h:41
This file contains the declarations for the subclasses of Constant, which represent the different fla...
Expected< T > errorOrToExpected(ErrorOr< T > &&EO)
Convert an ErrorOr<T> to an Expected<T>.
Definition: Error.h:1142
void add(SymbolStringPtr Name, SymbolLookupFlags Flags=SymbolLookupFlags::RequiredSymbol)
Add an element to the set.
Definition: Core.h:161
amdgpu Simplify well known AMD library false FunctionCallee Value * Arg
JITDylibSearchOrder makeJITDylibSearchOrder(ArrayRef< JITDylib *> JDs, JITDylibLookupFlags Flags=JITDylibLookupFlags::MatchExportedSymbolsOnly)
Convenience function for creating a search order from an ArrayRef of JITDylib*, all with the same fla...
Definition: Core.h:96
Error tryToGenerate(LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) override
DefinitionGenerators should override this method to insert new definitions into the parent JITDylib...
StringRef getSection() const
Definition: Globals.cpp:161
static DynamicLibrary getPermanentLibrary(const char *filename, std::string *errMsg=nullptr)
This function permanently loads the dynamic library at the given path.
Triple - Helper class for working with autoconf configuration names.
Definition: Triple.h:45
iterator_range< T > make_range(T x, T y)
Convenience function for iterating over sub-ranges.
Error tryToGenerate(LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags, const SymbolLookupSet &Symbols) override
DefinitionGenerators should override this method to insert new definitions into the parent JITDylib...
static ErrorSuccess success()
Create a success value.
Definition: Error.h:332
unsigned getNumOperands() const
Definition: User.h:191
static int CXAAtExitOverride(DestructorPtr Destructor, void *Arg, void *DSOHandle)
This iterator provides a convenient way to iterate over the elements of an llvm.global_ctors/llvm.global_dtors instance.
Module.h This file contains the declarations for the Module class.
A set of symbols to look up, each associated with a SymbolLookupFlags value.
Definition: Core.h:113
static Constant * getInitializer(Constant *C)
Definition: Evaluator.cpp:203
raw_ostream & dbgs()
dbgs() - This returns a reference to a raw_ostream for debugging messages.
Definition: Debug.cpp:132
A range adaptor for a pair of iterators.
ConstantArray - Constant Array Declarations.
Definition: Constants.h:422
Represents a symbol that has been evaluated to an address already.
Definition: JITSymbol.h:229
void runDestructors()
Run any destructors recorded by the overriden __cxa_atexit function (CXAAtExitOverride).
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFileSlice(const Twine &Filename, uint64_t MapSize, uint64_t Offset, bool IsVolatile=false)
Map a subrange of the specified file as a MemoryBuffer.
LLVM_NODISCARD std::enable_if_t< !is_simple_type< Y >::value, typename cast_retty< X, const Y >::ret_type > dyn_cast_or_null(const Y &Val)
Definition: Casting.h:354
uint8_t uint64_t VModuleKey
VModuleKey provides a unique identifier (allocated and managed by ExecutionSessions) for a module add...
Definition: Core.h:40
static Expected< std::unique_ptr< StaticLibraryDefinitionGenerator > > Load(ObjectLayer &L, const char *FileName)
Try to create a StaticLibraryDefinitionGenerator from the given path.
StringRef getName() const
Return a constant reference to the value&#39;s name.
Definition: Value.cpp:270
iterator_range< CtorDtorIterator > getConstructors(const Module &M)
Create an iterator range over the entries of the llvm.global_ctors array.
#define I(x, y, z)
Definition: MD5.cpp:59
LLVM_NODISCARD bool empty() const
Definition: DenseMap.h:97
bool isDeclaration() const
Return true if the primary definition of this global value is outside of the current translation unit...
Definition: Globals.cpp:227
static ErrorOr< std::unique_ptr< MemoryBuffer > > getFile(const Twine &Filename, int64_t FileSize=-1, bool RequiresNullTerminator=true, bool IsVolatile=false)
Open the specified file as a MemoryBuffer, returning a new MemoryBuffer if successful, otherwise returning null.
int runAsMain(int(*Main)(int, char *[]), ArrayRef< std::string > Args, Optional< StringRef > ProgramName=None)
Run a main function, returning the result.
assert(ImpDefSCC.getReg()==AMDGPU::SCC &&ImpDefSCC.isDef())
LLVM Value Representation.
Definition: Value.h:74
Element operator*() const
Dereference iterator.
Lightweight error class with error context and mandatory checking.
Definition: Error.h:157
IteratorT begin() const
Interface for Layers that accept object files.
Definition: Layer.h:128
bool operator!=(const CtorDtorIterator &Other) const
Test iterators for inequality.
JITDylibLookupFlags
Lookup flags that apply to each dylib in the search order for a lookup.
Definition: Core.h:65
OutputIt copy(R &&Range, OutputIt Out)
Definition: STLExtras.h:1542
static Expected< std::unique_ptr< StaticLibraryDefinitionGenerator > > Create(ObjectLayer &L, std::unique_ptr< MemoryBuffer > ArchiveBuffer)
Try to create a StaticLibrarySearchGenerator from the given memory buffer.
constexpr char Args[]
Key for Kernel::Metadata::mArgs.
A symbol table that supports asynchoronous symbol queries.
Definition: Core.h:779
std::error_code inconvertibleErrorCode()
The value returned by this function can be returned from convertToErrorCode for Error values where no...
Definition: Error.cpp:77