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
11#include "llvm/ExecutionEngine/Orc/Layer.h"
12#include "llvm/IR/Constants.h"
13#include "llvm/IR/Function.h"
14#include "llvm/IR/GlobalVariable.h"
15#include "llvm/IR/Module.h"
16#include "llvm/Support/TargetRegistry.h"
17#include "llvm/Target/TargetMachine.h"
18
19namespace llvm {
20namespace orc {
21
22int runAsMain(int (*Main)(int, char *[]), ArrayRef<std::string> Args,
23              Optional<StringRef> ProgramName) {
24  std::vector<std::unique_ptr<char[]>> ArgVStorage;
25  std::vector<char *> ArgV;
26
27  ArgVStorage.reserve(Args.size() + (ProgramName ? 1 : 0));
28  ArgV.reserve(Args.size() + 1 + (ProgramName ? 1 : 0));
29
30  if (ProgramName) {
31    ArgVStorage.push_back(std::make_unique<char[]>(ProgramName->size() + 1));
32    llvm::copy(*ProgramName, &ArgVStorage.back()[0]);
33    ArgVStorage.back()[ProgramName->size()] = '\0';
34    ArgV.push_back(ArgVStorage.back().get());
35  }
36
37  for (auto &Arg : Args) {
38    ArgVStorage.push_back(std::make_unique<char[]>(Arg.size() + 1));
39    llvm::copy(Arg, &ArgVStorage.back()[0]);
40    ArgVStorage.back()[Arg.size()] = '\0';
41    ArgV.push_back(ArgVStorage.back().get());
42  }
43  ArgV.push_back(nullptr);
44
45  return Main(Args.size() + !!ProgramName, ArgV.data());
46}
47
48CtorDtorIterator::CtorDtorIterator(const GlobalVariable *GV, bool End)
49  : InitList(
50      GV ? dyn_cast_or_null<ConstantArray>(GV->getInitializer()) : nullptr),
51    I((InitList && End) ? InitList->getNumOperands() : 0) {
52}
53
54bool CtorDtorIterator::operator==(const CtorDtorIterator &Other) const {
55  assert(InitList == Other.InitList && "Incomparable iterators.");
56  return I == Other.I;
57}
58
59bool CtorDtorIterator::operator!=(const CtorDtorIterator &Other) const {
60  return !(*this == Other);
61}
62
63CtorDtorIterator& CtorDtorIterator::operator++() {
64  ++I;
65  return *this;
66}
67
68CtorDtorIterator CtorDtorIterator::operator++(int) {
69  CtorDtorIterator Temp = *this;
70  ++I;
71  return Temp;
72}
73
74CtorDtorIterator::Element CtorDtorIterator::operator*() const {
75  ConstantStruct *CS = dyn_cast<ConstantStruct>(InitList->getOperand(I));
76  assert(CS && "Unrecognized type in llvm.global_ctors/llvm.global_dtors");
77
78  Constant *FuncC = CS->getOperand(1);
79  Function *Func = nullptr;
80
81  // Extract function pointer, pulling off any casts.
82  while (FuncC) {
83    if (Function *F = dyn_cast_or_null<Function>(FuncC)) {
84      Func = F;
85      break;
86    } else if (ConstantExpr *CE = dyn_cast_or_null<ConstantExpr>(FuncC)) {
87      if (CE->isCast())
88        FuncC = dyn_cast_or_null<ConstantExpr>(CE->getOperand(0));
89      else
90        break;
91    } else {
92      // This isn't anything we recognize. Bail out with Func left set to null.
93      break;
94    }
95  }
96
97  auto *Priority = cast<ConstantInt>(CS->getOperand(0));
98  Value *Data = CS->getNumOperands() == 3 ? CS->getOperand(2) : nullptr;
99  if (Data && !isa<GlobalValue>(Data))
100    Data = nullptr;
101  return Element(Priority->getZExtValue(), Func, Data);
102}
103
104iterator_range<CtorDtorIterator> getConstructors(const Module &M) {
105  const GlobalVariable *CtorsList = M.getNamedGlobal("llvm.global_ctors");
106  return make_range(CtorDtorIterator(CtorsList, false),
107                    CtorDtorIterator(CtorsList, true));
108}
109
110iterator_range<CtorDtorIterator> getDestructors(const Module &M) {
111  const GlobalVariable *DtorsList = M.getNamedGlobal("llvm.global_dtors");
112  return make_range(CtorDtorIterator(DtorsList, false),
113                    CtorDtorIterator(DtorsList, true));
114}
115
116void CtorDtorRunner::add(iterator_range<CtorDtorIterator> CtorDtors) {
117  if (CtorDtors.empty())
118    return;
119
120  MangleAndInterner Mangle(
121      JD.getExecutionSession(),
122      (*CtorDtors.begin()).Func->getParent()->getDataLayout());
123
124  for (auto CtorDtor : CtorDtors) {
125    assert(CtorDtor.Func && CtorDtor.Func->hasName() &&
126           "Ctor/Dtor function must be named to be runnable under the JIT");
127
128    // FIXME: Maybe use a symbol promoter here instead.
129    if (CtorDtor.Func->hasLocalLinkage()) {
130      CtorDtor.Func->setLinkage(GlobalValue::ExternalLinkage);
131      CtorDtor.Func->setVisibility(GlobalValue::HiddenVisibility);
132    }
133
134    if (CtorDtor.Data && cast<GlobalValue>(CtorDtor.Data)->isDeclaration()) {
135      dbgs() << "  Skipping because why now?\n";
136      continue;
137    }
138
139    CtorDtorsByPriority[CtorDtor.Priority].push_back(
140        Mangle(CtorDtor.Func->getName()));
141  }
142}
143
144Error CtorDtorRunner::run() {
145  using CtorDtorTy = void (*)();
146
147  SymbolLookupSet LookupSet;
148  for (auto &KV : CtorDtorsByPriority)
149    for (auto &Name : KV.second)
150      LookupSet.add(Name);
151  assert(!LookupSet.containsDuplicates() &&
152         "Ctor/Dtor list contains duplicates");
153
154  auto &ES = JD.getExecutionSession();
155  if (auto CtorDtorMap = ES.lookup(
156          makeJITDylibSearchOrder(&JD, JITDylibLookupFlags::MatchAllSymbols),
157          std::move(LookupSet))) {
158    for (auto &KV : CtorDtorsByPriority) {
159      for (auto &Name : KV.second) {
160        assert(CtorDtorMap->count(Name) && "No entry for Name");
161        auto CtorDtor = reinterpret_cast<CtorDtorTy>(
162            static_cast<uintptr_t>((*CtorDtorMap)[Name].getAddress()));
163        CtorDtor();
164      }
165    }
166    CtorDtorsByPriority.clear();
167    return Error::success();
168  } else
169    return CtorDtorMap.takeError();
170}
171
172void LocalCXXRuntimeOverridesBase::runDestructors() {
173  auto& CXXDestructorDataPairs = DSOHandleOverride;
174  for (auto &P : CXXDestructorDataPairs)
175    P.first(P.second);
176  CXXDestructorDataPairs.clear();
177}
178
179int LocalCXXRuntimeOverridesBase::CXAAtExitOverride(DestructorPtr Destructor,
180                                                    void *Arg,
181                                                    void *DSOHandle) {
182  auto& CXXDestructorDataPairs =
183    *reinterpret_cast<CXXDestructorDataPairList*>(DSOHandle);
184  CXXDestructorDataPairs.push_back(std::make_pair(Destructor, Arg));
185  return 0;
186}
187
188Error LocalCXXRuntimeOverrides::enable(JITDylib &JD,
189                                        MangleAndInterner &Mangle) {
190  SymbolMap RuntimeInterposes;
191  RuntimeInterposes[Mangle("__dso_handle")] =
192    JITEvaluatedSymbol(toTargetAddress(&DSOHandleOverride),
193                       JITSymbolFlags::Exported);
194  RuntimeInterposes[Mangle("__cxa_atexit")] =
195    JITEvaluatedSymbol(toTargetAddress(&CXAAtExitOverride),
196                       JITSymbolFlags::Exported);
197
198  return JD.define(absoluteSymbols(std::move(RuntimeInterposes)));
199}
200
201DynamicLibrarySearchGenerator::DynamicLibrarySearchGenerator(
202    sys::DynamicLibrary Dylib, char GlobalPrefix, SymbolPredicate Allow)
203    : Dylib(std::move(Dylib)), Allow(std::move(Allow)),
204      GlobalPrefix(GlobalPrefix) {}
205
206Expected<std::unique_ptr<DynamicLibrarySearchGenerator>>
207DynamicLibrarySearchGenerator::Load(const char *FileName, char GlobalPrefix,
208                                    SymbolPredicate Allow) {
209  std::string ErrMsg;
210  auto Lib = sys::DynamicLibrary::getPermanentLibrary(FileName, &ErrMsg);
211  if (!Lib.isValid())
212    return make_error<StringError>(std::move(ErrMsg), inconvertibleErrorCode());
213  return std::make_unique<DynamicLibrarySearchGenerator>(
214      std::move(Lib), GlobalPrefix, std::move(Allow));
215}
216
217Error DynamicLibrarySearchGenerator::tryToGenerate(
218    LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
219    const SymbolLookupSet &Symbols) {
220  orc::SymbolMap NewSymbols;
221
222  bool HasGlobalPrefix = (GlobalPrefix != '\0');
223
224  for (auto &KV : Symbols) {
225    auto &Name = KV.first;
226
227    if ((*Name).empty())
228      continue;
229
230    if (Allow && !Allow(Name))
231      continue;
232
233    if (HasGlobalPrefix && (*Name).front() != GlobalPrefix)
234      continue;
235
236    std::string Tmp((*Name).data() + HasGlobalPrefix,
237                    (*Name).size() - HasGlobalPrefix);
238    if (void *Addr = Dylib.getAddressOfSymbol(Tmp.c_str())) {
239      NewSymbols[Name] = JITEvaluatedSymbol(
240          static_cast<JITTargetAddress>(reinterpret_cast<uintptr_t>(Addr)),
241          JITSymbolFlags::Exported);
242    }
243  }
244
245  if (NewSymbols.empty())
246    return Error::success();
247
248  return JD.define(absoluteSymbols(std::move(NewSymbols)));
249}
250
251Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
252StaticLibraryDefinitionGenerator::Load(ObjectLayer &L, const char *FileName) {
253  auto ArchiveBuffer = errorOrToExpected(MemoryBuffer::getFile(FileName));
254
255  if (!ArchiveBuffer)
256    return ArchiveBuffer.takeError();
257
258  return Create(L, std::move(*ArchiveBuffer));
259}
260
261Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>>
262StaticLibraryDefinitionGenerator::Create(
263    ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer) {
264  Error Err = Error::success();
265
266  std::unique_ptr<StaticLibraryDefinitionGenerator> ADG(
267      new StaticLibraryDefinitionGenerator(L, std::move(ArchiveBuffer), Err));
268
269  if (Err)
270    return std::move(Err);
271
272  return std::move(ADG);
273}
274
275Error StaticLibraryDefinitionGenerator::tryToGenerate(
276    LookupKind K, JITDylib &JD, JITDylibLookupFlags JDLookupFlags,
277    const SymbolLookupSet &Symbols) {
278
279  // Don't materialize symbols from static archives unless this is a static
280  // lookup.
281  if (K != LookupKind::Static)
282    return Error::success();
283
284  // Bail out early if we've already freed the archive.
285  if (!Archive)
286    return Error::success();
287
288  DenseSet<std::pair<StringRef, StringRef>> ChildBufferInfos;
289
290  for (const auto &KV : Symbols) {
291    const auto &Name = KV.first;
292    auto Child = Archive->findSym(*Name);
293    if (!Child)
294      return Child.takeError();
295    if (*Child == None)
296      continue;
297    auto ChildBuffer = (*Child)->getMemoryBufferRef();
298    if (!ChildBuffer)
299      return ChildBuffer.takeError();
300    ChildBufferInfos.insert(
301        {ChildBuffer->getBuffer(), ChildBuffer->getBufferIdentifier()});
302  }
303
304  for (auto ChildBufferInfo : ChildBufferInfos) {
305    MemoryBufferRef ChildBufferRef(ChildBufferInfo.first,
306                                   ChildBufferInfo.second);
307
308    if (auto Err =
309            L.add(JD, MemoryBuffer::getMemBuffer(ChildBufferRef), VModuleKey()))
310      return Err;
311  }
312
313  return Error::success();
314}
315
316StaticLibraryDefinitionGenerator::StaticLibraryDefinitionGenerator(
317    ObjectLayer &L, std::unique_ptr<MemoryBuffer> ArchiveBuffer, Error &Err)
318    : L(L), ArchiveBuffer(std::move(ArchiveBuffer)),
319      Archive(std::make_unique<object::Archive>(*this->ArchiveBuffer, Err)) {}
320
321} // End namespace orc.
322} // End namespace llvm.
323