2911 lines · cpp
1//===- llvm-jitlink.cpp -- Command line interface/tester for llvm-jitlink -===//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-exception6//7//===----------------------------------------------------------------------===//8//9// This utility provides a simple command line interface to the llvm jitlink10// library, which makes relocatable object files executable in memory. Its11// primary function is as a testing utility for the jitlink library.12//13//===----------------------------------------------------------------------===//14 15#include "llvm-jitlink.h"16#include "llvm/BinaryFormat/Magic.h"17#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX, LLVM_ENABLE_THREADS18#include "llvm/ExecutionEngine/Orc/AbsoluteSymbols.h"19#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"20#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"21#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"22#include "llvm/ExecutionEngine/Orc/Debugging/ELFDebugObjectPlugin.h"23#include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h"24#include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"25#include "llvm/ExecutionEngine/Orc/EHFrameRegistrationPlugin.h"26#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"27#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"28#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"29#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"30#include "llvm/ExecutionEngine/Orc/JITLinkRedirectableSymbolManager.h"31#include "llvm/ExecutionEngine/Orc/JITLinkReentryTrampolines.h"32#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"33#include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"34#include "llvm/ExecutionEngine/Orc/MachO.h"35#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"36#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"37#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"38#include "llvm/ExecutionEngine/Orc/SectCreate.h"39#include "llvm/ExecutionEngine/Orc/SelfExecutorProcessControl.h"40#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"41#include "llvm/ExecutionEngine/Orc/SimpleRemoteMemoryMapper.h"42#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"43#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"44#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"45#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"46#include "llvm/ExecutionEngine/Orc/UnwindInfoRegistrationPlugin.h"47#include "llvm/MC/MCAsmInfo.h"48#include "llvm/MC/MCContext.h"49#include "llvm/MC/MCDisassembler/MCDisassembler.h"50#include "llvm/MC/MCInstPrinter.h"51#include "llvm/MC/MCInstrAnalysis.h"52#include "llvm/MC/MCInstrInfo.h"53#include "llvm/MC/MCRegisterInfo.h"54#include "llvm/MC/MCSubtargetInfo.h"55#include "llvm/MC/MCTargetOptions.h"56#include "llvm/MC/TargetRegistry.h"57#include "llvm/Object/COFF.h"58#include "llvm/Object/MachO.h"59#include "llvm/Object/ObjectFile.h"60#include "llvm/Object/TapiUniversal.h"61#include "llvm/Support/CommandLine.h"62#include "llvm/Support/Debug.h"63#include "llvm/Support/InitLLVM.h"64#include "llvm/Support/MemoryBuffer.h"65#include "llvm/Support/Path.h"66#include "llvm/Support/Process.h"67#include "llvm/Support/TargetSelect.h"68#include "llvm/Support/Timer.h"69#include <cstring>70#include <deque>71#include <string>72 73#ifdef LLVM_ON_UNIX74#include <netdb.h>75#include <netinet/in.h>76#include <sys/socket.h>77#include <unistd.h>78#endif // LLVM_ON_UNIX79 80#define DEBUG_TYPE "llvm_jitlink"81 82using namespace llvm;83using namespace llvm::jitlink;84using namespace llvm::orc;85 86static cl::OptionCategory JITLinkCategory("JITLink Options");87 88static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,89 cl::desc("input files"),90 cl::cat(JITLinkCategory));91 92static cl::list<bool> LazyLink("lazy",93 cl::desc("Link the following file lazily"),94 cl::cat(JITLinkCategory));95 96enum class SpeculateKind { None, Simple };97 98static cl::opt<SpeculateKind> Speculate(99 "speculate", cl::desc("Choose speculation scheme"),100 cl::init(SpeculateKind::None),101 cl::values(clEnumValN(SpeculateKind::None, "none", "No speculation"),102 clEnumValN(SpeculateKind::Simple, "simple",103 "Simple speculation")),104 cl::cat(JITLinkCategory));105 106static cl::opt<std::string> SpeculateOrder(107 "speculate-order",108 cl::desc("A CSV file containing (JITDylib, Function) pairs to"109 "speculatively look up"),110 cl::cat(JITLinkCategory));111 112static cl::opt<std::string> RecordLazyExecs(113 "record-lazy-execs",114 cl::desc("Write lazy-function executions to a CSV file as (JITDylib, "115 "function) pairs"),116 cl::cat(JITLinkCategory));117 118static cl::opt<size_t> MaterializationThreads(119 "num-threads", cl::desc("Number of materialization threads to use"),120 cl::init(std::numeric_limits<size_t>::max()), cl::cat(JITLinkCategory));121 122static cl::list<std::string>123 LibrarySearchPaths("L",124 cl::desc("Add dir to the list of library search paths"),125 cl::Prefix, cl::cat(JITLinkCategory));126 127static cl::list<std::string>128 Libraries("l",129 cl::desc("Link against library X in the library search paths"),130 cl::Prefix, cl::cat(JITLinkCategory));131 132static cl::list<std::string>133 LibrariesHidden("hidden-l",134 cl::desc("Link against library X in the library search "135 "paths with hidden visibility"),136 cl::Prefix, cl::cat(JITLinkCategory));137 138static cl::list<std::string>139 LoadHidden("load_hidden",140 cl::desc("Link against library X with hidden visibility"),141 cl::cat(JITLinkCategory));142 143static cl::list<std::string>144 LibrariesWeak("weak-l",145 cl::desc("Emulate weak link against library X. Must resolve "146 "to a TextAPI file, and all symbols in the "147 "interface will resolve to null."),148 cl::Prefix, cl::cat(JITLinkCategory));149 150static cl::list<std::string> WeakLibraries(151 "weak_library",152 cl::desc("Emulate weak link against library X. X must point to a "153 "TextAPI file, and all symbols in the interface will "154 "resolve to null"),155 cl::cat(JITLinkCategory));156 157static cl::opt<bool> SearchSystemLibrary(158 "search-sys-lib",159 cl::desc("Add system library paths to library search paths"),160 cl::init(false), cl::cat(JITLinkCategory));161 162static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),163 cl::init(false), cl::cat(JITLinkCategory));164 165static cl::list<std::string>166 CheckFiles("check", cl::desc("File containing verifier checks"),167 cl::cat(JITLinkCategory));168 169static cl::opt<std::string>170 CheckName("check-name", cl::desc("Name of checks to match against"),171 cl::init("jitlink-check"), cl::cat(JITLinkCategory));172 173static cl::opt<std::string>174 EntryPointName("entry", cl::desc("Symbol to call as main entry point"),175 cl::init(""), cl::cat(JITLinkCategory));176 177static cl::list<std::string> JITDylibs(178 "jd",179 cl::desc("Specifies the JITDylib to be used for any subsequent "180 "input file, -L<seacrh-path>, and -l<library> arguments"),181 cl::cat(JITLinkCategory));182 183static cl::list<std::string>184 Dylibs("preload",185 cl::desc("Pre-load dynamic libraries (e.g. language runtimes "186 "required by the ORC runtime)"),187 cl::cat(JITLinkCategory));188 189static cl::list<std::string> InputArgv("args", cl::Positional,190 cl::desc("<program arguments>..."),191 cl::PositionalEatsArgs,192 cl::cat(JITLinkCategory));193 194static cl::opt<bool>195 DebuggerSupport("debugger-support",196 cl::desc("Enable debugger suppport (default = !-noexec)"),197 cl::init(true), cl::Hidden, cl::cat(JITLinkCategory));198 199static cl::opt<bool> PerfSupport("perf-support",200 cl::desc("Enable perf profiling support"),201 cl::init(false), cl::Hidden,202 cl::cat(JITLinkCategory));203 204static cl::opt<bool> VTuneSupport("vtune-support",205 cl::desc("Enable vtune profiling support"),206 cl::init(false), cl::Hidden,207 cl::cat(JITLinkCategory));208static cl::opt<bool>209 NoProcessSymbols("no-process-syms",210 cl::desc("Do not resolve to llvm-jitlink process symbols"),211 cl::init(false), cl::cat(JITLinkCategory));212 213static cl::list<std::string> AbsoluteDefs(214 "abs",215 cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),216 cl::cat(JITLinkCategory));217 218static cl::list<std::string>219 Aliases("alias",220 cl::desc("Inject symbol aliases (syntax: <alias-name>=<aliasee>)"),221 cl::cat(JITLinkCategory));222 223static cl::list<std::string>224 SectCreate("sectcreate",225 cl::desc("given <sectname>,<filename>[@<sym>=<offset>,...] "226 "add the content of <filename> to <sectname>"),227 cl::cat(JITLinkCategory));228 229static cl::list<std::string> TestHarnesses("harness", cl::Positional,230 cl::desc("Test harness files"),231 cl::PositionalEatsArgs,232 cl::cat(JITLinkCategory));233 234static cl::opt<bool>235 ShowLinkedFiles("show-linked-files",236 cl::desc("List each file/graph name if/when it is linked"),237 cl::init(false), cl::cat(JITLinkCategory));238 239static cl::opt<bool> ShowInitialExecutionSessionState(240 "show-init-es",241 cl::desc("Print ExecutionSession state before resolving entry point"),242 cl::init(false), cl::cat(JITLinkCategory));243 244static cl::opt<bool> ShowEntryExecutionSessionState(245 "show-entry-es",246 cl::desc("Print ExecutionSession state after resolving entry point"),247 cl::init(false), cl::cat(JITLinkCategory));248 249static cl::opt<bool> ShowAddrs(250 "show-addrs",251 cl::desc("Print registered symbol, section, got and stub addresses"),252 cl::init(false), cl::cat(JITLinkCategory));253 254static cl::opt<std::string> ShowLinkGraphs(255 "show-graphs",256 cl::desc("Takes a posix regex and prints the link graphs of all files "257 "matching that regex after fixups have been applied"),258 cl::Optional, cl::cat(JITLinkCategory));259 260static cl::opt<bool> ShowTimes("show-times",261 cl::desc("Show times for llvm-jitlink phases"),262 cl::init(false), cl::cat(JITLinkCategory));263 264static cl::opt<std::string> SlabAllocateSizeString(265 "slab-allocate",266 cl::desc("Allocate from a slab of the given size "267 "(allowable suffixes: Kb, Mb, Gb. default = "268 "Kb)"),269 cl::init(""), cl::cat(JITLinkCategory));270 271static cl::opt<uint64_t> SlabAddress(272 "slab-address",273 cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),274 cl::init(~0ULL), cl::cat(JITLinkCategory));275 276static cl::opt<uint64_t> SlabPageSize(277 "slab-page-size",278 cl::desc("Set page size for slab (requires -slab-allocate and -noexec)"),279 cl::init(0), cl::cat(JITLinkCategory));280 281static cl::opt<bool> ShowRelocatedSectionContents(282 "show-relocated-section-contents",283 cl::desc("show section contents after fixups have been applied"),284 cl::init(false), cl::cat(JITLinkCategory));285 286static cl::opt<bool> PhonyExternals(287 "phony-externals",288 cl::desc("resolve all otherwise unresolved externals to null"),289 cl::init(false), cl::cat(JITLinkCategory));290 291static cl::opt<std::string> OutOfProcessExecutor(292 "oop-executor", cl::desc("Launch an out-of-process executor to run code"),293 cl::ValueOptional, cl::cat(JITLinkCategory));294 295static cl::opt<std::string> OutOfProcessExecutorConnect(296 "oop-executor-connect",297 cl::desc("Connect to an out-of-process executor via TCP"),298 cl::cat(JITLinkCategory));299 300static cl::opt<std::string>301 OrcRuntime("orc-runtime", cl::desc("Use ORC runtime from given path"),302 cl::init(""), cl::cat(JITLinkCategory));303 304static cl::opt<bool> AddSelfRelocations(305 "add-self-relocations",306 cl::desc("Add relocations to function pointers to the current function"),307 cl::init(false), cl::cat(JITLinkCategory));308 309static cl::opt<bool>310 ShowErrFailedToMaterialize("show-err-failed-to-materialize",311 cl::desc("Show FailedToMaterialize errors"),312 cl::init(false), cl::cat(JITLinkCategory));313 314enum class MemMgr { Default, Generic, SimpleRemote, Shared };315 316static cl::opt<MemMgr> UseMemMgr(317 "use-memmgr", cl::desc("Choose memory manager"), cl::init(MemMgr::Generic),318 cl::values(clEnumValN(MemMgr::Default, "default",319 "Use setup default (InProcess or EPCGeneric)"),320 clEnumValN(MemMgr::Generic, "generic",321 "Generic remote memory manager"),322 clEnumValN(MemMgr::SimpleRemote, "simple-remote",323 "Mapper memory manager with simple-remote backend"),324 clEnumValN(MemMgr::Shared, "shared",325 "Mapper memory manager with shared-memory manager")),326 cl::cat(JITLinkCategory));327 328static cl::opt<std::string>329 OverrideTriple("triple", cl::desc("Override target triple detection"),330 cl::init(""), cl::cat(JITLinkCategory));331 332static cl::opt<bool> AllLoad("all_load",333 cl::desc("Load all members of static archives"),334 cl::init(false), cl::cat(JITLinkCategory));335 336static cl::opt<bool> ForceLoadObjC(337 "ObjC",338 cl::desc("Load all members of static archives that implement "339 "Objective-C classes or categories, or Swift structs, "340 "classes or extensions"),341 cl::init(false), cl::cat(JITLinkCategory));342 343static ExitOnError ExitOnErr;344 345static LLVM_ATTRIBUTE_USED void linkComponents() {346 errs() << "Linking in runtime functions\n"347 << (void *)&llvm_orc_registerEHFrameSectionAllocAction << '\n'348 << (void *)&llvm_orc_deregisterEHFrameSectionAllocAction << '\n'349 << (void *)&llvm_orc_registerJITLoaderGDBAllocAction << '\n'350 << (void *)&llvm_orc_registerJITLoaderPerfStart << '\n'351 << (void *)&llvm_orc_registerJITLoaderPerfEnd << '\n'352 << (void *)&llvm_orc_registerJITLoaderPerfImpl << '\n'353 << (void *)&llvm_orc_registerVTuneImpl << '\n'354 << (void *)&llvm_orc_unregisterVTuneImpl << '\n'355 << (void *)&llvm_orc_test_registerVTuneImpl << '\n';356}357 358static bool UseTestResultOverride = false;359static int64_t TestResultOverride = 0;360 361extern "C" LLVM_ATTRIBUTE_USED void362llvm_jitlink_setTestResultOverride(int64_t Value) {363 TestResultOverride = Value;364 UseTestResultOverride = true;365}366 367static Error addSelfRelocations(LinkGraph &G);368 369namespace {370 371template <typename ErrT>372 373class ConditionalPrintErr {374public:375 ConditionalPrintErr(bool C) : C(C) {}376 void operator()(ErrT &EI) {377 if (C) {378 errs() << "llvm-jitlink error: ";379 EI.log(errs());380 errs() << "\n";381 }382 }383 384private:385 bool C;386};387 388Expected<std::unique_ptr<MemoryBuffer>> getFile(const Twine &FileName) {389 if (auto F = MemoryBuffer::getFile(FileName))390 return std::move(*F);391 else392 return createFileError(FileName, F.getError());393}394 395void reportLLVMJITLinkError(Error Err) {396 handleAllErrors(397 std::move(Err),398 ConditionalPrintErr<orc::FailedToMaterialize>(ShowErrFailedToMaterialize),399 ConditionalPrintErr<ErrorInfoBase>(true));400}401 402} // end anonymous namespace403 404namespace llvm {405 406static raw_ostream &407operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {408 return OS << "target addr = "409 << format("0x%016" PRIx64, MRI.getTargetAddress())410 << ", content: " << (const void *)MRI.getContent().data() << " -- "411 << (const void *)(MRI.getContent().data() + MRI.getContent().size())412 << " (" << MRI.getContent().size() << " bytes)";413}414 415static raw_ostream &416operator<<(raw_ostream &OS, const Session::SymbolInfoMap &SIM) {417 OS << "Symbols:\n";418 for (auto &SKV : SIM)419 OS << " \"" << SKV.first << "\" " << SKV.second << "\n";420 return OS;421}422 423static raw_ostream &424operator<<(raw_ostream &OS, const Session::FileInfo &FI) {425 for (auto &SIKV : FI.SectionInfos)426 OS << " Section \"" << SIKV.first() << "\": " << SIKV.second << "\n";427 for (auto &GOTKV : FI.GOTEntryInfos)428 OS << " GOT \"" << GOTKV.first() << "\": " << GOTKV.second << "\n";429 for (auto &StubKVs : FI.StubInfos) {430 OS << " Stubs \"" << StubKVs.first() << "\":";431 for (auto MemRegion : StubKVs.second)432 OS << " " << MemRegion;433 OS << "\n";434 }435 return OS;436}437 438static raw_ostream &439operator<<(raw_ostream &OS, const Session::FileInfoMap &FIM) {440 for (auto &FIKV : FIM)441 OS << "File \"" << FIKV.first() << "\":\n" << FIKV.second;442 return OS;443}444 445bool lazyLinkingRequested() {446 for (auto LL : LazyLink)447 if (LL)448 return true;449 return false;450}451 452static Error applyLibraryLinkModifiers(Session &S, LinkGraph &G) {453 // If there are hidden archives and this graph is an archive454 // member then apply hidden modifier.455 if (!S.HiddenArchives.empty()) {456 StringRef ObjName(G.getName());457 if (ObjName.ends_with(')')) {458 auto LibName = ObjName.split('[').first;459 if (S.HiddenArchives.count(LibName)) {460 for (auto *Sym : G.defined_symbols())461 Sym->setScope(std::max(Sym->getScope(), Scope::Hidden));462 }463 }464 }465 466 return Error::success();467}468 469static Error applyHarnessPromotions(Session &S, LinkGraph &G) {470 std::lock_guard<std::mutex> Lock(S.M);471 472 // If this graph is part of the test harness there's nothing to do.473 if (S.HarnessFiles.empty() || S.HarnessFiles.count(G.getName()))474 return Error::success();475 476 LLVM_DEBUG(dbgs() << "Applying promotions to graph " << G.getName() << "\n");477 478 // If this graph is part of the test then promote any symbols referenced by479 // the harness to default scope, remove all symbols that clash with harness480 // definitions.481 std::vector<Symbol *> DefinitionsToRemove;482 for (auto *Sym : G.defined_symbols()) {483 484 if (!Sym->hasName())485 continue;486 487 if (Sym->getLinkage() == Linkage::Weak) {488 auto It = S.CanonicalWeakDefs.find(*Sym->getName());489 if (It == S.CanonicalWeakDefs.end() || It->second != G.getName()) {490 LLVM_DEBUG({491 dbgs() << " Externalizing weak symbol " << Sym->getName() << "\n";492 });493 DefinitionsToRemove.push_back(Sym);494 } else {495 LLVM_DEBUG({496 dbgs() << " Making weak symbol " << Sym->getName() << " strong\n";497 });498 if (S.HarnessExternals.count(*Sym->getName()))499 Sym->setScope(Scope::Default);500 else501 Sym->setScope(Scope::Hidden);502 Sym->setLinkage(Linkage::Strong);503 }504 } else if (S.HarnessExternals.count(*Sym->getName())) {505 LLVM_DEBUG(dbgs() << " Promoting " << Sym->getName() << "\n");506 Sym->setScope(Scope::Default);507 Sym->setLive(true);508 continue;509 } else if (S.HarnessDefinitions.count(*Sym->getName())) {510 LLVM_DEBUG(dbgs() << " Externalizing " << Sym->getName() << "\n");511 DefinitionsToRemove.push_back(Sym);512 }513 }514 515 for (auto *Sym : DefinitionsToRemove)516 G.makeExternal(*Sym);517 518 return Error::success();519}520 521static void dumpSectionContents(raw_ostream &OS, Session &S, LinkGraph &G) {522 std::lock_guard<std::mutex> Lock(S.M);523 524 outs() << "Relocated section contents for " << G.getName() << ":\n";525 526 constexpr orc::ExecutorAddrDiff DumpWidth = 16;527 static_assert(isPowerOf2_64(DumpWidth), "DumpWidth must be a power of two");528 529 // Put sections in address order.530 std::vector<Section *> Sections;531 for (auto &S : G.sections())532 Sections.push_back(&S);533 534 llvm::sort(Sections, [](const Section *LHS, const Section *RHS) {535 if (LHS->symbols().empty() && RHS->symbols().empty())536 return false;537 if (LHS->symbols().empty())538 return false;539 if (RHS->symbols().empty())540 return true;541 SectionRange LHSRange(*LHS);542 SectionRange RHSRange(*RHS);543 return LHSRange.getStart() < RHSRange.getStart();544 });545 546 for (auto *S : Sections) {547 OS << S->getName() << " content:";548 if (S->symbols().empty()) {549 OS << "\n section empty\n";550 continue;551 }552 553 // Sort symbols into order, then render.554 std::vector<Symbol *> Syms(S->symbols().begin(), S->symbols().end());555 llvm::sort(Syms, [](const Symbol *LHS, const Symbol *RHS) {556 return LHS->getAddress() < RHS->getAddress();557 });558 559 orc::ExecutorAddr NextAddr(Syms.front()->getAddress().getValue() &560 ~(DumpWidth - 1));561 for (auto *Sym : Syms) {562 bool IsZeroFill = Sym->getBlock().isZeroFill();563 auto SymStart = Sym->getAddress();564 auto SymSize = Sym->getSize();565 auto SymEnd = SymStart + SymSize;566 const uint8_t *SymData = IsZeroFill ? nullptr567 : reinterpret_cast<const uint8_t *>(568 Sym->getSymbolContent().data());569 570 // Pad any space before the symbol starts.571 while (NextAddr != SymStart) {572 if (NextAddr % DumpWidth == 0)573 OS << formatv("\n{0:x16}:", NextAddr);574 OS << " ";575 ++NextAddr;576 }577 578 // Render the symbol content.579 while (NextAddr != SymEnd) {580 if (NextAddr % DumpWidth == 0)581 OS << formatv("\n{0:x16}:", NextAddr);582 if (IsZeroFill)583 OS << " 00";584 else585 OS << formatv(" {0:x-2}", SymData[NextAddr - SymStart]);586 ++NextAddr;587 }588 }589 OS << "\n";590 }591}592 593// A memory mapper with a fake offset applied only used for -noexec testing594class InProcessDeltaMapper final : public InProcessMemoryMapper {595public:596 InProcessDeltaMapper(size_t PageSize, uint64_t TargetAddr)597 : InProcessMemoryMapper(PageSize), TargetMapAddr(TargetAddr),598 DeltaAddr(0) {}599 600 static Expected<std::unique_ptr<InProcessDeltaMapper>> Create() {601 size_t PageSize = SlabPageSize;602 if (!PageSize) {603 if (auto PageSizeOrErr = sys::Process::getPageSize())604 PageSize = *PageSizeOrErr;605 else606 return PageSizeOrErr.takeError();607 }608 609 if (PageSize == 0)610 return make_error<StringError>("Page size is zero",611 inconvertibleErrorCode());612 613 return std::make_unique<InProcessDeltaMapper>(PageSize, SlabAddress);614 }615 616 void reserve(size_t NumBytes, OnReservedFunction OnReserved) override {617 InProcessMemoryMapper::reserve(618 NumBytes, [this, OnReserved = std::move(OnReserved)](619 Expected<ExecutorAddrRange> Result) mutable {620 if (!Result)621 return OnReserved(Result.takeError());622 623 assert(DeltaAddr == 0 && "Overwriting previous offset");624 if (TargetMapAddr != ~0ULL)625 DeltaAddr = TargetMapAddr - Result->Start.getValue();626 auto OffsetRange = ExecutorAddrRange(Result->Start + DeltaAddr,627 Result->End + DeltaAddr);628 629 OnReserved(OffsetRange);630 });631 }632 633 char *prepare(jitlink::LinkGraph &G, ExecutorAddr Addr,634 size_t ContentSize) override {635 return InProcessMemoryMapper::prepare(G, Addr - DeltaAddr, ContentSize);636 }637 638 void initialize(AllocInfo &AI, OnInitializedFunction OnInitialized) override {639 // Slide mapping based on delta, make all segments read-writable, and640 // discard allocation actions.641 auto FixedAI = std::move(AI);642 FixedAI.MappingBase -= DeltaAddr;643 for (auto &Seg : FixedAI.Segments)644 Seg.AG = {MemProt::Read | MemProt::Write, Seg.AG.getMemLifetime()};645 FixedAI.Actions.clear();646 InProcessMemoryMapper::initialize(647 FixedAI, [this, OnInitialized = std::move(OnInitialized)](648 Expected<ExecutorAddr> Result) mutable {649 if (!Result)650 return OnInitialized(Result.takeError());651 652 OnInitialized(ExecutorAddr(Result->getValue() + DeltaAddr));653 });654 }655 656 void deinitialize(ArrayRef<ExecutorAddr> Allocations,657 OnDeinitializedFunction OnDeInitialized) override {658 std::vector<ExecutorAddr> Addrs(Allocations.size());659 for (const auto Base : Allocations) {660 Addrs.push_back(Base - DeltaAddr);661 }662 663 InProcessMemoryMapper::deinitialize(Addrs, std::move(OnDeInitialized));664 }665 666 void release(ArrayRef<ExecutorAddr> Reservations,667 OnReleasedFunction OnRelease) override {668 std::vector<ExecutorAddr> Addrs(Reservations.size());669 for (const auto Base : Reservations) {670 Addrs.push_back(Base - DeltaAddr);671 }672 InProcessMemoryMapper::release(Addrs, std::move(OnRelease));673 }674 675private:676 uint64_t TargetMapAddr;677 uint64_t DeltaAddr;678};679 680Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {681 SizeString = SizeString.trim();682 683 uint64_t Units = 1024;684 685 if (SizeString.ends_with_insensitive("kb"))686 SizeString = SizeString.drop_back(2).rtrim();687 else if (SizeString.ends_with_insensitive("mb")) {688 Units = 1024 * 1024;689 SizeString = SizeString.drop_back(2).rtrim();690 } else if (SizeString.ends_with_insensitive("gb")) {691 Units = 1024 * 1024 * 1024;692 SizeString = SizeString.drop_back(2).rtrim();693 }694 695 uint64_t SlabSize = 0;696 if (SizeString.getAsInteger(10, SlabSize))697 return make_error<StringError>("Invalid numeric format for slab size",698 inconvertibleErrorCode());699 700 return SlabSize * Units;701}702 703static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {704 uint64_t SlabSize;705#ifdef _WIN32706 SlabSize = 1024 * 1024;707#else708 SlabSize = 1024 * 1024 * 1024;709#endif710 711 if (!SlabAllocateSizeString.empty())712 SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));713 714 // If this is a -no-exec case and we're tweaking the slab address or size then715 // use the delta mapper.716 if (NoExec && (SlabAddress || SlabPageSize))717 return ExitOnErr(718 MapperJITLinkMemoryManager::CreateWithMapper<InProcessDeltaMapper>(719 SlabSize));720 721 // Otherwise use the standard in-process mapper.722 return ExitOnErr(723 MapperJITLinkMemoryManager::CreateWithMapper<InProcessMemoryMapper>(724 SlabSize));725}726 727Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>728createSimpleRemoteMemoryManager(SimpleRemoteEPC &SREPC) {729 SimpleRemoteMemoryMapper::SymbolAddrs SAs;730 if (auto Err = SREPC.getBootstrapSymbols(731 {{SAs.Instance, rt::SimpleExecutorMemoryManagerInstanceName},732 {SAs.Reserve, rt::SimpleExecutorMemoryManagerReserveWrapperName},733 {SAs.Initialize,734 rt::SimpleExecutorMemoryManagerInitializeWrapperName},735 {SAs.Deinitialize,736 rt::SimpleExecutorMemoryManagerDeinitializeWrapperName},737 {SAs.Release, rt::SimpleExecutorMemoryManagerReleaseWrapperName}}))738 return std::move(Err);739#ifdef _WIN32740 size_t SlabSize = 1024 * 1024;741#else742 size_t SlabSize = 1024 * 1024 * 1024;743#endif744 return MapperJITLinkMemoryManager::CreateWithMapper<SimpleRemoteMemoryMapper>(745 SlabSize, SREPC, SAs);746}747 748Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>749createSharedMemoryManager(SimpleRemoteEPC &SREPC) {750 SharedMemoryMapper::SymbolAddrs SAs;751 if (auto Err = SREPC.getBootstrapSymbols(752 {{SAs.Instance, rt::ExecutorSharedMemoryMapperServiceInstanceName},753 {SAs.Reserve,754 rt::ExecutorSharedMemoryMapperServiceReserveWrapperName},755 {SAs.Initialize,756 rt::ExecutorSharedMemoryMapperServiceInitializeWrapperName},757 {SAs.Deinitialize,758 rt::ExecutorSharedMemoryMapperServiceDeinitializeWrapperName},759 {SAs.Release,760 rt::ExecutorSharedMemoryMapperServiceReleaseWrapperName}}))761 return std::move(Err);762 763#ifdef _WIN32764 size_t SlabSize = 1024 * 1024;765#else766 size_t SlabSize = 1024 * 1024 * 1024;767#endif768 769 if (!SlabAllocateSizeString.empty())770 SlabSize = ExitOnErr(getSlabAllocSize(SlabAllocateSizeString));771 772 return MapperJITLinkMemoryManager::CreateWithMapper<SharedMemoryMapper>(773 SlabSize, SREPC, SAs);774}775 776#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS777static void setupEPCRemoteMemoryManager(SimpleRemoteEPC::Setup &S) {778 switch (UseMemMgr) {779 case MemMgr::Default:780 case MemMgr::Generic:781 break;782 case MemMgr::SimpleRemote:783 S.CreateMemoryManager = createSimpleRemoteMemoryManager;784 break;785 case MemMgr::Shared:786 S.CreateMemoryManager = createSharedMemoryManager;787 break;788 }789}790#endif791 792static Expected<MaterializationUnit::Interface>793getTestObjectFileInterface(Session &S, MemoryBufferRef O) {794 795 // Get the standard interface for this object, but ignore the symbols field.796 // We'll handle that manually to include promotion.797 auto I = getObjectFileInterface(S.ES, O);798 if (!I)799 return I.takeError();800 I->SymbolFlags.clear();801 802 // If creating an object file was going to fail it would have happened above,803 // so we can 'cantFail' this.804 auto Obj = cantFail(object::ObjectFile::createObjectFile(O));805 806 // The init symbol must be included in the SymbolFlags map if present.807 if (I->InitSymbol)808 I->SymbolFlags[I->InitSymbol] =809 JITSymbolFlags::MaterializationSideEffectsOnly;810 811 for (auto &Sym : Obj->symbols()) {812 Expected<uint32_t> SymFlagsOrErr = Sym.getFlags();813 if (!SymFlagsOrErr)814 // TODO: Test this error.815 return SymFlagsOrErr.takeError();816 817 // Skip symbols not defined in this object file.818 if ((*SymFlagsOrErr & object::BasicSymbolRef::SF_Undefined))819 continue;820 821 auto Name = Sym.getName();822 if (!Name)823 return Name.takeError();824 825 // Skip symbols that have type SF_File.826 if (auto SymType = Sym.getType()) {827 if (*SymType == object::SymbolRef::ST_File)828 continue;829 } else830 return SymType.takeError();831 832 auto SymFlags = JITSymbolFlags::fromObjectSymbol(Sym);833 if (!SymFlags)834 return SymFlags.takeError();835 836 if (SymFlags->isWeak()) {837 // If this is a weak symbol that's not defined in the harness then we838 // need to either mark it as strong (if this is the first definition839 // that we've seen) or discard it.840 if (S.HarnessDefinitions.count(*Name) || S.CanonicalWeakDefs.count(*Name))841 continue;842 S.CanonicalWeakDefs[*Name] = O.getBufferIdentifier();843 *SymFlags &= ~JITSymbolFlags::Weak;844 if (!S.HarnessExternals.count(*Name))845 *SymFlags &= ~JITSymbolFlags::Exported;846 } else if (S.HarnessExternals.count(*Name)) {847 *SymFlags |= JITSymbolFlags::Exported;848 } else if (S.HarnessDefinitions.count(*Name) ||849 !(*SymFlagsOrErr & object::BasicSymbolRef::SF_Global))850 continue;851 852 I->SymbolFlags[S.ES.intern(*Name)] = std::move(*SymFlags);853 }854 855 return I;856}857 858static Error loadProcessSymbols(Session &S) {859 S.ProcessSymsJD = &S.ES.createBareJITDylib("Process");860 auto FilterMainEntryPoint =861 [EPName = S.ES.intern(EntryPointName)](SymbolStringPtr Name) {862 return Name != EPName;863 };864 S.ProcessSymsJD->addGenerator(865 ExitOnErr(orc::EPCDynamicLibrarySearchGenerator::GetForTargetProcess(866 S.ES, std::move(FilterMainEntryPoint))));867 868 return Error::success();869}870 871static Error loadDylibs(Session &S) {872 LLVM_DEBUG(dbgs() << "Loading dylibs...\n");873 for (const auto &Dylib : Dylibs) {874 LLVM_DEBUG(dbgs() << " " << Dylib << "\n");875 auto DL = S.getOrLoadDynamicLibrary(Dylib);876 if (!DL)877 return DL.takeError();878 }879 880 return Error::success();881}882 883static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {884#ifndef LLVM_ON_UNIX885 // FIXME: Add support for Windows.886 return make_error<StringError>("-" + OutOfProcessExecutor.ArgStr +887 " not supported on non-unix platforms",888 inconvertibleErrorCode());889#elif !LLVM_ENABLE_THREADS890 // Out of process mode using SimpleRemoteEPC depends on threads.891 return make_error<StringError>(892 "-" + OutOfProcessExecutor.ArgStr +893 " requires threads, but LLVM was built with "894 "LLVM_ENABLE_THREADS=Off",895 inconvertibleErrorCode());896#else897 898 constexpr int ReadEnd = 0;899 constexpr int WriteEnd = 1;900 901 // Pipe FDs.902 int ToExecutor[2];903 int FromExecutor[2];904 905 pid_t ChildPID;906 907 // Create pipes to/from the executor..908 if (pipe(ToExecutor) != 0 || pipe(FromExecutor) != 0)909 return make_error<StringError>("Unable to create pipe for executor",910 inconvertibleErrorCode());911 912 ChildPID = fork();913 914 if (ChildPID == 0) {915 // In the child...916 917 // Close the parent ends of the pipes918 close(ToExecutor[WriteEnd]);919 close(FromExecutor[ReadEnd]);920 921 // Execute the child process.922 std::unique_ptr<char[]> ExecutorPath, FDSpecifier;923 {924 ExecutorPath = std::make_unique<char[]>(OutOfProcessExecutor.size() + 1);925 strcpy(ExecutorPath.get(), OutOfProcessExecutor.data());926 927 std::string FDSpecifierStr("filedescs=");928 FDSpecifierStr += utostr(ToExecutor[ReadEnd]);929 FDSpecifierStr += ',';930 FDSpecifierStr += utostr(FromExecutor[WriteEnd]);931 FDSpecifier = std::make_unique<char[]>(FDSpecifierStr.size() + 1);932 strcpy(FDSpecifier.get(), FDSpecifierStr.c_str());933 }934 935 char *const Args[] = {ExecutorPath.get(), FDSpecifier.get(), nullptr};936 int RC = execvp(ExecutorPath.get(), Args);937 if (RC != 0) {938 errs() << "unable to launch out-of-process executor \""939 << ExecutorPath.get() << "\"\n";940 exit(1);941 }942 }943 // else we're the parent...944 945 // Close the child ends of the pipes946 close(ToExecutor[ReadEnd]);947 close(FromExecutor[WriteEnd]);948 949 auto S = SimpleRemoteEPC::Setup();950 setupEPCRemoteMemoryManager(S);951 952 return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(953 std::make_unique<DynamicThreadPoolTaskDispatcher>(MaterializationThreads),954 std::move(S), FromExecutor[ReadEnd], ToExecutor[WriteEnd]);955#endif956}957 958#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS959static Error createTCPSocketError(Twine Details) {960 return make_error<StringError>(961 formatv("Failed to connect TCP socket '{0}': {1}",962 OutOfProcessExecutorConnect, Details),963 inconvertibleErrorCode());964}965 966static Expected<int> connectTCPSocket(std::string Host, std::string PortStr) {967 addrinfo *AI;968 addrinfo Hints{};969 Hints.ai_family = AF_INET;970 Hints.ai_socktype = SOCK_STREAM;971 Hints.ai_flags = AI_NUMERICSERV;972 973 if (int EC = getaddrinfo(Host.c_str(), PortStr.c_str(), &Hints, &AI))974 return createTCPSocketError("Address resolution failed (" +975 StringRef(gai_strerror(EC)) + ")");976 977 // Cycle through the returned addrinfo structures and connect to the first978 // reachable endpoint.979 int SockFD;980 addrinfo *Server;981 for (Server = AI; Server != nullptr; Server = Server->ai_next) {982 // socket might fail, e.g. if the address family is not supported. Skip to983 // the next addrinfo structure in such a case.984 if ((SockFD = socket(AI->ai_family, AI->ai_socktype, AI->ai_protocol)) < 0)985 continue;986 987 // If connect returns null, we exit the loop with a working socket.988 if (connect(SockFD, Server->ai_addr, Server->ai_addrlen) == 0)989 break;990 991 close(SockFD);992 }993 freeaddrinfo(AI);994 995 // If we reached the end of the loop without connecting to a valid endpoint,996 // dump the last error that was logged in socket() or connect().997 if (Server == nullptr)998 return createTCPSocketError(std::strerror(errno));999 1000 return SockFD;1001}1002#endif1003 1004static Expected<std::unique_ptr<ExecutorProcessControl>> connectToExecutor() {1005#ifndef LLVM_ON_UNIX1006 // FIXME: Add TCP support for Windows.1007 return make_error<StringError>("-" + OutOfProcessExecutorConnect.ArgStr +1008 " not supported on non-unix platforms",1009 inconvertibleErrorCode());1010#elif !LLVM_ENABLE_THREADS1011 // Out of process mode using SimpleRemoteEPC depends on threads.1012 return make_error<StringError>(1013 "-" + OutOfProcessExecutorConnect.ArgStr +1014 " requires threads, but LLVM was built with "1015 "LLVM_ENABLE_THREADS=Off",1016 inconvertibleErrorCode());1017#else1018 1019 StringRef Host, PortStr;1020 std::tie(Host, PortStr) = StringRef(OutOfProcessExecutorConnect).split(':');1021 if (Host.empty())1022 return createTCPSocketError("Host name for -" +1023 OutOfProcessExecutorConnect.ArgStr +1024 " can not be empty");1025 if (PortStr.empty())1026 return createTCPSocketError("Port number in -" +1027 OutOfProcessExecutorConnect.ArgStr +1028 " can not be empty");1029 int Port = 0;1030 if (PortStr.getAsInteger(10, Port))1031 return createTCPSocketError("Port number '" + PortStr +1032 "' is not a valid integer");1033 1034 Expected<int> SockFD = connectTCPSocket(Host.str(), PortStr.str());1035 if (!SockFD)1036 return SockFD.takeError();1037 1038 auto S = SimpleRemoteEPC::Setup();1039 setupEPCRemoteMemoryManager(S);1040 1041 return SimpleRemoteEPC::Create<FDSimpleRemoteEPCTransport>(1042 std::make_unique<DynamicThreadPoolTaskDispatcher>(std::nullopt),1043 std::move(S), *SockFD, *SockFD);1044#endif1045}1046 1047class PhonyExternalsGenerator : public DefinitionGenerator {1048public:1049 Error tryToGenerate(LookupState &LS, LookupKind K, JITDylib &JD,1050 JITDylibLookupFlags JDLookupFlags,1051 const SymbolLookupSet &LookupSet) override {1052 SymbolMap PhonySymbols;1053 for (auto &KV : LookupSet)1054 PhonySymbols[KV.first] = {ExecutorAddr(), JITSymbolFlags::Exported};1055 return JD.define(absoluteSymbols(std::move(PhonySymbols)));1056 }1057};1058 1059Expected<std::unique_ptr<Session::LazyLinkingSupport>>1060createLazyLinkingSupport(Session &S) {1061 auto RSMgr = JITLinkRedirectableSymbolManager::Create(S.ObjLayer);1062 if (!RSMgr)1063 return RSMgr.takeError();1064 1065 std::shared_ptr<SimpleLazyReexportsSpeculator> Speculator;1066 switch (Speculate) {1067 case SpeculateKind::None:1068 break;1069 case SpeculateKind::Simple:1070 SimpleLazyReexportsSpeculator::RecordExecutionFunction RecordExecs;1071 1072 if (!RecordLazyExecs.empty())1073 RecordExecs = [&S](const LazyReexportsManager::CallThroughInfo &CTI) {1074 S.LazyFnExecOrder.push_back({CTI.JD->getName(), CTI.BodyName});1075 };1076 1077 Speculator =1078 SimpleLazyReexportsSpeculator::Create(S.ES, std::move(RecordExecs));1079 break;1080 }1081 1082 auto LRMgr = createJITLinkLazyReexportsManager(1083 S.ObjLayer, **RSMgr, *S.PlatformJD, Speculator.get());1084 if (!LRMgr)1085 return LRMgr.takeError();1086 1087 return std::make_unique<Session::LazyLinkingSupport>(1088 std::move(*RSMgr), std::move(Speculator), std::move(*LRMgr), S.ObjLayer);1089}1090 1091static Error writeLazyExecOrder(Session &S) {1092 if (RecordLazyExecs.empty())1093 return Error::success();1094 1095 std::error_code EC;1096 raw_fd_ostream ExecOrderOut(RecordLazyExecs, EC);1097 if (EC)1098 return createFileError(RecordLazyExecs, EC);1099 1100 for (auto &[JDName, FunctionName] : S.LazyFnExecOrder)1101 ExecOrderOut << JDName << ", " << FunctionName << "\n";1102 1103 return Error::success();1104}1105 1106Expected<std::unique_ptr<Session>> Session::Create(Triple TT,1107 SubtargetFeatures Features) {1108 1109 std::unique_ptr<ExecutorProcessControl> EPC;1110 if (OutOfProcessExecutor.getNumOccurrences()) {1111 /// If -oop-executor is passed then launch the executor.1112 if (auto REPC = launchExecutor())1113 EPC = std::move(*REPC);1114 else1115 return REPC.takeError();1116 } else if (OutOfProcessExecutorConnect.getNumOccurrences()) {1117 /// If -oop-executor-connect is passed then connect to the executor.1118 if (auto REPC = connectToExecutor())1119 EPC = std::move(*REPC);1120 else1121 return REPC.takeError();1122 } else {1123 /// Otherwise use SelfExecutorProcessControl to target the current process.1124 auto PageSize = sys::Process::getPageSize();1125 if (!PageSize)1126 return PageSize.takeError();1127 std::unique_ptr<TaskDispatcher> Dispatcher;1128 if (MaterializationThreads == 0)1129 Dispatcher = std::make_unique<InPlaceTaskDispatcher>();1130 else {1131#if LLVM_ENABLE_THREADS1132 Dispatcher = std::make_unique<DynamicThreadPoolTaskDispatcher>(1133 MaterializationThreads);1134#else1135 llvm_unreachable("MaterializationThreads should be 0");1136#endif1137 }1138 1139 EPC = std::make_unique<SelfExecutorProcessControl>(1140 std::make_shared<SymbolStringPool>(), std::move(Dispatcher),1141 std::move(TT), *PageSize, createInProcessMemoryManager());1142 }1143 1144 Error Err = Error::success();1145 std::unique_ptr<Session> S(new Session(std::move(EPC), Err));1146 if (Err)1147 return std::move(Err);1148 S->Features = std::move(Features);1149 1150 if (lazyLinkingRequested()) {1151 if (auto LazyLinking = createLazyLinkingSupport(*S))1152 S->LazyLinking = std::move(*LazyLinking);1153 else1154 return LazyLinking.takeError();1155 }1156 1157 return std::move(S);1158}1159 1160Session::~Session() {1161 if (auto Err = writeLazyExecOrder(*this))1162 ES.reportError(std::move(Err));1163 1164 if (auto Err = ES.endSession())1165 ES.reportError(std::move(Err));1166}1167 1168Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)1169 : ES(std::move(EPC)),1170 ObjLayer(ES, ES.getExecutorProcessControl().getMemMgr()) {1171 1172 /// Local ObjectLinkingLayer::Plugin class to forward modifyPassConfig to the1173 /// Session.1174 class JITLinkSessionPlugin : public ObjectLinkingLayer::Plugin {1175 public:1176 JITLinkSessionPlugin(Session &S) : S(S) {}1177 void modifyPassConfig(MaterializationResponsibility &MR, LinkGraph &G,1178 PassConfiguration &PassConfig) override {1179 S.modifyPassConfig(G, PassConfig);1180 }1181 1182 Error notifyFailed(MaterializationResponsibility &MR) override {1183 return Error::success();1184 }1185 Error notifyRemovingResources(JITDylib &JD, ResourceKey K) override {1186 return Error::success();1187 }1188 void notifyTransferringResources(JITDylib &JD, ResourceKey DstKey,1189 ResourceKey SrcKey) override {}1190 1191 private:1192 Session &S;1193 };1194 1195 ErrorAsOutParameter _(&Err);1196 1197 ES.setErrorReporter(reportLLVMJITLinkError);1198 1199 if (!NoProcessSymbols)1200 ExitOnErr(loadProcessSymbols(*this));1201 1202 ExitOnErr(loadDylibs(*this));1203 1204 auto &TT = ES.getTargetTriple();1205 1206 if (DebuggerSupport && TT.isOSBinFormatMachO()) {1207 if (!ProcessSymsJD) {1208 Err = make_error<StringError>("MachO debugging requires process symbols",1209 inconvertibleErrorCode());1210 return;1211 }1212 ObjLayer.addPlugin(ExitOnErr(GDBJITDebugInfoRegistrationPlugin::Create(1213 this->ES, *ProcessSymsJD, TT)));1214 }1215 1216 if (PerfSupport && TT.isOSBinFormatELF()) {1217 if (!ProcessSymsJD) {1218 Err = make_error<StringError>("MachO debugging requires process symbols",1219 inconvertibleErrorCode());1220 return;1221 }1222 ObjLayer.addPlugin(ExitOnErr(DebugInfoPreservationPlugin::Create()));1223 ObjLayer.addPlugin(ExitOnErr(PerfSupportPlugin::Create(1224 this->ES.getExecutorProcessControl(), *ProcessSymsJD, true, true)));1225 }1226 1227 if (VTuneSupport && TT.isOSBinFormatELF()) {1228 ObjLayer.addPlugin(ExitOnErr(DebugInfoPreservationPlugin::Create()));1229 ObjLayer.addPlugin(ExitOnErr(1230 VTuneSupportPlugin::Create(this->ES.getExecutorProcessControl(),1231 *ProcessSymsJD, /*EmitDebugInfo=*/true,1232 /*TestMode=*/true)));1233 }1234 1235 // Set up the platform.1236 if (!OrcRuntime.empty()) {1237 assert(ProcessSymsJD && "ProcessSymsJD should have been set");1238 PlatformJD = &ES.createBareJITDylib("Platform");1239 PlatformJD->addToLinkOrder(*ProcessSymsJD);1240 1241 if (TT.isOSBinFormatMachO()) {1242 if (auto P =1243 MachOPlatform::Create(ObjLayer, *PlatformJD, OrcRuntime.c_str()))1244 ES.setPlatform(std::move(*P));1245 else {1246 Err = P.takeError();1247 return;1248 }1249 } else if (TT.isOSBinFormatELF()) {1250 if (auto P =1251 ELFNixPlatform::Create(ObjLayer, *PlatformJD, OrcRuntime.c_str()))1252 ES.setPlatform(std::move(*P));1253 else {1254 Err = P.takeError();1255 return;1256 }1257 } else if (TT.isOSBinFormatCOFF()) {1258 auto LoadDynLibrary = [&, this](JITDylib &JD,1259 StringRef DLLName) -> Error {1260 if (!DLLName.ends_with_insensitive(".dll"))1261 return make_error<StringError>("DLLName not ending with .dll",1262 inconvertibleErrorCode());1263 return loadAndLinkDynamicLibrary(JD, DLLName);1264 };1265 1266 if (auto P =1267 COFFPlatform::Create(ObjLayer, *PlatformJD, OrcRuntime.c_str(),1268 std::move(LoadDynLibrary)))1269 ES.setPlatform(std::move(*P));1270 else {1271 Err = P.takeError();1272 return;1273 }1274 } else {1275 Err = make_error<StringError>(1276 "-" + OrcRuntime.ArgStr + " specified, but format " +1277 Triple::getObjectFormatTypeName(TT.getObjectFormat()) +1278 " not supported",1279 inconvertibleErrorCode());1280 return;1281 }1282 } else if (TT.isOSBinFormatMachO()) {1283 if (!NoExec) {1284 std::optional<bool> ForceEHFrames;1285 if ((Err = ES.getBootstrapMapValue<bool, bool>("darwin-use-ehframes-only",1286 ForceEHFrames)))1287 return;1288 bool UseEHFrames = ForceEHFrames.value_or(false);1289 if (!UseEHFrames)1290 ObjLayer.addPlugin(ExitOnErr(UnwindInfoRegistrationPlugin::Create(ES)));1291 else1292 ObjLayer.addPlugin(ExitOnErr(EHFrameRegistrationPlugin::Create(ES)));1293 }1294 } else if (TT.isOSBinFormatELF()) {1295 if (!NoExec)1296 ObjLayer.addPlugin(ExitOnErr(EHFrameRegistrationPlugin::Create(ES)));1297 if (DebuggerSupport) {1298 Error TargetSymErr = Error::success();1299 auto Plugin =1300 std::make_unique<ELFDebugObjectPlugin>(ES, true, true, TargetSymErr);1301 if (!TargetSymErr)1302 ObjLayer.addPlugin(std::move(Plugin));1303 else1304 logAllUnhandledErrors(std::move(TargetSymErr), errs(),1305 "Debugger support not available: ");1306 }1307 }1308 1309 if (auto MainJDOrErr = ES.createJITDylib("main"))1310 MainJD = &*MainJDOrErr;1311 else {1312 Err = MainJDOrErr.takeError();1313 return;1314 }1315 1316 if (NoProcessSymbols) {1317 // This symbol is used in testcases, but we're not reflecting process1318 // symbols so we'll need to make it available some other way.1319 auto &TestResultJD = ES.createBareJITDylib("<TestResultJD>");1320 ExitOnErr(TestResultJD.define(absoluteSymbols(1321 {{ES.intern("llvm_jitlink_setTestResultOverride"),1322 {ExecutorAddr::fromPtr(llvm_jitlink_setTestResultOverride),1323 JITSymbolFlags::Exported}}})));1324 MainJD->addToLinkOrder(TestResultJD);1325 }1326 1327 ObjLayer.addPlugin(std::make_unique<JITLinkSessionPlugin>(*this));1328 1329 // Process any harness files.1330 for (auto &HarnessFile : TestHarnesses) {1331 HarnessFiles.insert(HarnessFile);1332 1333 auto ObjBuffer =1334 ExitOnErr(loadLinkableFile(HarnessFile, ES.getTargetTriple(),1335 LoadArchives::Never))1336 .first;1337 1338 auto ObjInterface =1339 ExitOnErr(getObjectFileInterface(ES, ObjBuffer->getMemBufferRef()));1340 1341 for (auto &KV : ObjInterface.SymbolFlags)1342 HarnessDefinitions.insert(*KV.first);1343 1344 auto Obj = ExitOnErr(1345 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));1346 1347 for (auto &Sym : Obj->symbols()) {1348 uint32_t SymFlags = ExitOnErr(Sym.getFlags());1349 auto Name = ExitOnErr(Sym.getName());1350 1351 if (Name.empty())1352 continue;1353 1354 if (SymFlags & object::BasicSymbolRef::SF_Undefined)1355 HarnessExternals.insert(Name);1356 }1357 }1358 1359 // If a name is defined by some harness file then it's a definition, not an1360 // external.1361 for (auto &DefName : HarnessDefinitions)1362 HarnessExternals.erase(DefName.getKey());1363 1364 if (!ShowLinkGraphs.empty())1365 ShowGraphsRegex = Regex(ShowLinkGraphs);1366}1367 1368void Session::dumpSessionInfo(raw_ostream &OS) {1369 OS << "Registered addresses:\n" << SymbolInfos << FileInfos;1370}1371 1372void Session::modifyPassConfig(LinkGraph &G, PassConfiguration &PassConfig) {1373 1374 if (ShowLinkedFiles)1375 outs() << "Linking " << G.getName() << "\n";1376 1377 if (!CheckFiles.empty())1378 PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) {1379 if (ES.getTargetTriple().getObjectFormat() == Triple::ELF)1380 return registerELFGraphInfo(*this, G);1381 1382 if (ES.getTargetTriple().getObjectFormat() == Triple::MachO)1383 return registerMachOGraphInfo(*this, G);1384 1385 if (ES.getTargetTriple().getObjectFormat() == Triple::COFF)1386 return registerCOFFGraphInfo(*this, G);1387 1388 return make_error<StringError>("Unsupported object format for GOT/stub "1389 "registration",1390 inconvertibleErrorCode());1391 });1392 1393 if (ShowGraphsRegex)1394 PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {1395 std::lock_guard<std::mutex> Lock(M);1396 // Print graph if ShowLinkGraphs is specified-but-empty, or if1397 // it contains the given graph.1398 if (ShowGraphsRegex->match(G.getName())) {1399 outs() << "Link graph \"" << G.getName() << "\" post-fixup:\n";1400 G.dump(outs());1401 }1402 return Error::success();1403 });1404 1405 PassConfig.PrePrunePasses.push_back([this](LinkGraph &G) {1406 std::lock_guard<std::mutex> Lock(M);1407 ++ActiveLinks;1408 return Error::success();1409 });1410 PassConfig.PrePrunePasses.push_back(1411 [this](LinkGraph &G) { return applyLibraryLinkModifiers(*this, G); });1412 PassConfig.PrePrunePasses.push_back(1413 [this](LinkGraph &G) { return applyHarnessPromotions(*this, G); });1414 1415 if (ShowRelocatedSectionContents)1416 PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) -> Error {1417 dumpSectionContents(outs(), *this, G);1418 return Error::success();1419 });1420 1421 if (AddSelfRelocations)1422 PassConfig.PostPrunePasses.push_back(addSelfRelocations);1423 1424 PassConfig.PostFixupPasses.push_back([this](LinkGraph &G) {1425 std::lock_guard<std::mutex> Lock(M);1426 if (--ActiveLinks == 0)1427 ActiveLinksCV.notify_all();1428 return Error::success();1429 });1430}1431 1432Expected<JITDylib *> Session::getOrLoadDynamicLibrary(StringRef LibPath) {1433 auto It = DynLibJDs.find(LibPath);1434 if (It != DynLibJDs.end()) {1435 return It->second;1436 }1437 auto G = EPCDynamicLibrarySearchGenerator::Load(ES, LibPath.data());1438 if (!G)1439 return G.takeError();1440 auto JD = &ES.createBareJITDylib(LibPath.str());1441 1442 JD->addGenerator(std::move(*G));1443 DynLibJDs.emplace(LibPath.str(), JD);1444 LLVM_DEBUG({1445 dbgs() << "Loaded dynamic library " << LibPath.data() << " for " << LibPath1446 << "\n";1447 });1448 return JD;1449}1450 1451Error Session::loadAndLinkDynamicLibrary(JITDylib &JD, StringRef LibPath) {1452 auto DL = getOrLoadDynamicLibrary(LibPath);1453 if (!DL)1454 return DL.takeError();1455 JD.addToLinkOrder(**DL);1456 LLVM_DEBUG({1457 dbgs() << "Linking dynamic library " << LibPath << " to " << JD.getName()1458 << "\n";1459 });1460 return Error::success();1461}1462 1463Error Session::FileInfo::registerGOTEntry(1464 LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {1465 if (Sym.isSymbolZeroFill())1466 return make_error<StringError>("Unexpected zero-fill symbol in section " +1467 Sym.getBlock().getSection().getName(),1468 inconvertibleErrorCode());1469 auto TS = GetSymbolTarget(G, Sym.getBlock());1470 if (!TS)1471 return TS.takeError();1472 GOTEntryInfos[*TS->getName()] = {Sym.getSymbolContent(),1473 Sym.getAddress().getValue(),1474 Sym.getTargetFlags()};1475 return Error::success();1476}1477 1478Error Session::FileInfo::registerStubEntry(1479 LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {1480 if (Sym.isSymbolZeroFill())1481 return make_error<StringError>("Unexpected zero-fill symbol in section " +1482 Sym.getBlock().getSection().getName(),1483 inconvertibleErrorCode());1484 auto TS = GetSymbolTarget(G, Sym.getBlock());1485 if (!TS)1486 return TS.takeError();1487 1488 SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[*TS->getName()];1489 Entry.insert(Entry.begin(),1490 {Sym.getSymbolContent(), Sym.getAddress().getValue(),1491 Sym.getTargetFlags()});1492 return Error::success();1493}1494 1495Error Session::FileInfo::registerMultiStubEntry(1496 LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {1497 if (Sym.isSymbolZeroFill())1498 return make_error<StringError>("Unexpected zero-fill symbol in section " +1499 Sym.getBlock().getSection().getName(),1500 inconvertibleErrorCode());1501 1502 auto Target = GetSymbolTarget(G, Sym.getBlock());1503 if (!Target)1504 return Target.takeError();1505 1506 SmallVectorImpl<MemoryRegionInfo> &Entry = StubInfos[*Target->getName()];1507 Entry.emplace_back(Sym.getSymbolContent(), Sym.getAddress().getValue(),1508 Sym.getTargetFlags());1509 1510 // Let's keep stubs ordered by ascending address.1511 std::sort(Entry.begin(), Entry.end(),1512 [](const MemoryRegionInfo &L, const MemoryRegionInfo &R) {1513 return L.getTargetAddress() < R.getTargetAddress();1514 });1515 1516 return Error::success();1517}1518 1519Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {1520 auto FileInfoItr = FileInfos.find(FileName);1521 if (FileInfoItr == FileInfos.end())1522 return make_error<StringError>("file \"" + FileName + "\" not recognized",1523 inconvertibleErrorCode());1524 return FileInfoItr->second;1525}1526 1527Expected<Session::MemoryRegionInfo &>1528Session::findSectionInfo(StringRef FileName, StringRef SectionName) {1529 auto FI = findFileInfo(FileName);1530 if (!FI)1531 return FI.takeError();1532 auto SecInfoItr = FI->SectionInfos.find(SectionName);1533 if (SecInfoItr == FI->SectionInfos.end())1534 return make_error<StringError>("no section \"" + SectionName +1535 "\" registered for file \"" + FileName +1536 "\"",1537 inconvertibleErrorCode());1538 return SecInfoItr->second;1539}1540 1541class MemoryMatcher {1542public:1543 MemoryMatcher(ArrayRef<char> Content)1544 : Pos(Content.data()), End(Pos + Content.size()) {}1545 1546 template <typename MaskType> bool matchMask(MaskType Mask) {1547 if (Mask == (Mask & *reinterpret_cast<const MaskType *>(Pos))) {1548 Pos += sizeof(MaskType);1549 return true;1550 }1551 return false;1552 }1553 1554 template <typename ValueType> bool matchEqual(ValueType Value) {1555 if (Value == *reinterpret_cast<const ValueType *>(Pos)) {1556 Pos += sizeof(ValueType);1557 return true;1558 }1559 return false;1560 }1561 1562 bool done() const { return Pos == End; }1563 1564private:1565 const char *Pos;1566 const char *End;1567};1568 1569static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) {1570 using namespace support::endian;1571 auto Armv7MovWTle = byte_swap<uint32_t>(0xe300c000, endianness::little);1572 auto Armv7BxR12le = byte_swap<uint32_t>(0xe12fff1c, endianness::little);1573 auto Thumbv7MovWTle = byte_swap<uint32_t>(0x0c00f240, endianness::little);1574 auto Thumbv7BxR12le = byte_swap<uint16_t>(0x4760, endianness::little);1575 1576 MemoryMatcher M(Stub.getContent());1577 if (M.matchMask(Thumbv7MovWTle)) {1578 if (M.matchMask(Thumbv7MovWTle))1579 if (M.matchEqual(Thumbv7BxR12le))1580 if (M.done())1581 return "thumbv7_abs_le";1582 } else if (M.matchMask(Armv7MovWTle)) {1583 if (M.matchMask(Armv7MovWTle))1584 if (M.matchEqual(Armv7BxR12le))1585 if (M.done())1586 return "armv7_abs_le";1587 }1588 return "";1589}1590 1591Expected<Session::MemoryRegionInfo &>1592Session::findStubInfo(StringRef FileName, StringRef TargetName,1593 StringRef KindNameFilter) {1594 auto FI = findFileInfo(FileName);1595 if (!FI)1596 return FI.takeError();1597 auto StubInfoItr = FI->StubInfos.find(TargetName);1598 if (StubInfoItr == FI->StubInfos.end())1599 return make_error<StringError>("no stub for \"" + TargetName +1600 "\" registered for file \"" + FileName +1601 "\"",1602 inconvertibleErrorCode());1603 auto &StubsForTarget = StubInfoItr->second;1604 assert(!StubsForTarget.empty() && "At least 1 stub in each entry");1605 if (KindNameFilter.empty() && StubsForTarget.size() == 1)1606 return StubsForTarget[0]; // Regular single-stub match1607 1608 std::string KindsStr;1609 SmallVector<MemoryRegionInfo *, 1> Matches;1610 Regex KindNameMatcher(KindNameFilter.empty() ? ".*" : KindNameFilter);1611 for (MemoryRegionInfo &Stub : StubsForTarget) {1612 StringRef Kind = detectStubKind(Stub);1613 if (KindNameMatcher.match(Kind))1614 Matches.push_back(&Stub);1615 KindsStr += "\"" + (Kind.empty() ? "<unknown>" : Kind.str()) + "\", ";1616 }1617 if (Matches.empty())1618 return make_error<StringError>(1619 "\"" + TargetName + "\" has " + Twine(StubsForTarget.size()) +1620 " stubs in file \"" + FileName +1621 "\", but none of them matches the stub-kind filter \"" +1622 KindNameFilter + "\" (all encountered kinds are " +1623 StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",1624 inconvertibleErrorCode());1625 if (Matches.size() > 1)1626 return make_error<StringError>(1627 "\"" + TargetName + "\" has " + Twine(Matches.size()) +1628 " candidate stubs in file \"" + FileName +1629 "\". Please refine stub-kind filter \"" + KindNameFilter +1630 "\" for disambiguation (encountered kinds are " +1631 StringRef(KindsStr.data(), KindsStr.size() - 2) + ").",1632 inconvertibleErrorCode());1633 1634 return *Matches[0];1635}1636 1637Expected<Session::MemoryRegionInfo &>1638Session::findGOTEntryInfo(StringRef FileName, StringRef TargetName) {1639 auto FI = findFileInfo(FileName);1640 if (!FI)1641 return FI.takeError();1642 auto GOTInfoItr = FI->GOTEntryInfos.find(TargetName);1643 if (GOTInfoItr == FI->GOTEntryInfos.end())1644 return make_error<StringError>("no GOT entry for \"" + TargetName +1645 "\" registered for file \"" + FileName +1646 "\"",1647 inconvertibleErrorCode());1648 return GOTInfoItr->second;1649}1650 1651bool Session::isSymbolRegistered(const orc::SymbolStringPtr &SymbolName) {1652 return SymbolInfos.count(SymbolName);1653}1654 1655Expected<Session::MemoryRegionInfo &>1656Session::findSymbolInfo(const orc::SymbolStringPtr &SymbolName,1657 Twine ErrorMsgStem) {1658 auto SymInfoItr = SymbolInfos.find(SymbolName);1659 if (SymInfoItr == SymbolInfos.end())1660 return make_error<StringError>(ErrorMsgStem + ": symbol " + *SymbolName +1661 " not found",1662 inconvertibleErrorCode());1663 return SymInfoItr->second;1664}1665 1666} // end namespace llvm1667 1668static std::pair<Triple, SubtargetFeatures> getFirstFileTripleAndFeatures() {1669 static std::pair<Triple, SubtargetFeatures> FirstTTAndFeatures = []() {1670 assert(!InputFiles.empty() && "InputFiles can not be empty");1671 1672 if (!OverrideTriple.empty()) {1673 LLVM_DEBUG({1674 dbgs() << "Triple from -triple override: " << OverrideTriple << "\n";1675 });1676 return std::make_pair(Triple(OverrideTriple), SubtargetFeatures());1677 }1678 1679 for (auto InputFile : InputFiles) {1680 auto ObjBuffer = ExitOnErr(getFile(InputFile));1681 file_magic Magic = identify_magic(ObjBuffer->getBuffer());1682 switch (Magic) {1683 case file_magic::coff_object:1684 case file_magic::elf_relocatable:1685 case file_magic::macho_object: {1686 auto Obj = ExitOnErr(1687 object::ObjectFile::createObjectFile(ObjBuffer->getMemBufferRef()));1688 Triple TT;1689 if (auto *MachOObj = dyn_cast<object::MachOObjectFile>(Obj.get()))1690 TT = MachOObj->getArchTriple();1691 else1692 TT = Obj->makeTriple();1693 if (Magic == file_magic::coff_object) {1694 // TODO: Move this to makeTriple() if possible.1695 TT.setObjectFormat(Triple::COFF);1696 TT.setOS(Triple::OSType::Win32);1697 }1698 SubtargetFeatures Features;1699 if (auto ObjFeatures = Obj->getFeatures())1700 Features = std::move(*ObjFeatures);1701 1702 LLVM_DEBUG({1703 dbgs() << "Triple from " << InputFile << ": " << TT.str() << "\n";1704 });1705 return std::make_pair(TT, Features);1706 }1707 default:1708 break;1709 }1710 }1711 1712 // If no plain object file inputs exist to pin down the triple then detect1713 // the host triple and default to that.1714 auto JTMB = ExitOnErr(JITTargetMachineBuilder::detectHost());1715 LLVM_DEBUG({1716 dbgs() << "Triple from host-detection: " << JTMB.getTargetTriple().str()1717 << "\n";1718 });1719 return std::make_pair(JTMB.getTargetTriple(), JTMB.getFeatures());1720 }();1721 1722 return FirstTTAndFeatures;1723}1724 1725static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {1726 1727 // -noexec and --args should not be used together.1728 if (NoExec && !InputArgv.empty())1729 errs() << "Warning: --args passed to -noexec run will be ignored.\n";1730 1731 // Set the entry point name if not specified.1732 if (EntryPointName.empty())1733 EntryPointName = TT.getObjectFormat() == Triple::MachO ? "_main" : "main";1734 1735 // Disable debugger support by default in noexec tests.1736 if (DebuggerSupport.getNumOccurrences() == 0 && NoExec)1737 DebuggerSupport = false;1738 1739 if (!OrcRuntime.empty() && NoProcessSymbols)1740 return make_error<StringError>("-orc-runtime requires process symbols",1741 inconvertibleErrorCode());1742 1743 // If -slab-allocate is passed, check that we're not trying to use it in1744 // -oop-executor or -oop-executor-connect mode.1745 //1746 // FIXME: Remove once we enable remote slab allocation.1747 if (SlabAllocateSizeString != "") {1748 if (OutOfProcessExecutor.getNumOccurrences() ||1749 OutOfProcessExecutorConnect.getNumOccurrences())1750 return make_error<StringError>(1751 "-slab-allocate cannot be used with -oop-executor or "1752 "-oop-executor-connect",1753 inconvertibleErrorCode());1754 }1755 1756 // If -slab-address is passed, require -slab-allocate and -noexec1757 if (SlabAddress != ~0ULL) {1758 if (SlabAllocateSizeString == "" || !NoExec)1759 return make_error<StringError>(1760 "-slab-address requires -slab-allocate and -noexec",1761 inconvertibleErrorCode());1762 1763 if (SlabPageSize == 0)1764 errs() << "Warning: -slab-address used without -slab-page-size.\n";1765 }1766 1767 if (SlabPageSize != 0) {1768 // -slab-page-size requires slab alloc.1769 if (SlabAllocateSizeString == "")1770 return make_error<StringError>("-slab-page-size requires -slab-allocate",1771 inconvertibleErrorCode());1772 1773 // Check -slab-page-size / -noexec interactions.1774 if (!NoExec) {1775 if (auto RealPageSize = sys::Process::getPageSize()) {1776 if (SlabPageSize % *RealPageSize)1777 return make_error<StringError>(1778 "-slab-page-size must be a multiple of real page size for exec "1779 "tests (did you mean to use -noexec ?)\n",1780 inconvertibleErrorCode());1781 } else {1782 errs() << "Could not retrieve process page size:\n";1783 logAllUnhandledErrors(RealPageSize.takeError(), errs(), "");1784 errs() << "Executing with slab page size = "1785 << formatv("{0:x}", SlabPageSize) << ".\n"1786 << "Tool may crash if " << formatv("{0:x}", SlabPageSize)1787 << " is not a multiple of the real process page size.\n"1788 << "(did you mean to use -noexec ?)";1789 }1790 }1791 }1792 1793#if LLVM_ENABLE_THREADS1794 if (MaterializationThreads == std::numeric_limits<size_t>::max()) {1795 if (auto HC = std::thread::hardware_concurrency())1796 MaterializationThreads = HC;1797 else {1798 errs() << "Warning: std::thread::hardware_concurrency() returned 0, "1799 "defaulting to -num-threads=1.\n";1800 MaterializationThreads = 1;1801 }1802 }1803#else1804 if (MaterializationThreads.getNumOccurrences() &&1805 MaterializationThreads != 0) {1806 errs() << "Warning: -num-threads was set, but LLVM was built with threads "1807 "disabled. Resetting to -num-threads=0\n";1808 }1809 MaterializationThreads = 0;1810#endif1811 1812 if (!!OutOfProcessExecutor.getNumOccurrences() ||1813 !!OutOfProcessExecutorConnect.getNumOccurrences()) {1814 if (NoExec)1815 return make_error<StringError>("-noexec cannot be used with " +1816 OutOfProcessExecutor.ArgStr + " or " +1817 OutOfProcessExecutorConnect.ArgStr,1818 inconvertibleErrorCode());1819 1820 if (MaterializationThreads == 0)1821 return make_error<StringError>("-threads=0 cannot be used with " +1822 OutOfProcessExecutor.ArgStr + " or " +1823 OutOfProcessExecutorConnect.ArgStr,1824 inconvertibleErrorCode());1825 }1826 1827#ifndef NDEBUG1828 if (DebugFlag && MaterializationThreads != 0)1829 errs() << "Warning: debugging output is not thread safe. "1830 "Use -num-threads=0 to stabilize output.\n";1831#endif // NDEBUG1832 1833 // Only one of -oop-executor and -oop-executor-connect can be used.1834 if (!!OutOfProcessExecutor.getNumOccurrences() &&1835 !!OutOfProcessExecutorConnect.getNumOccurrences())1836 return make_error<StringError>(1837 "Only one of -" + OutOfProcessExecutor.ArgStr + " and -" +1838 OutOfProcessExecutorConnect.ArgStr + " can be specified",1839 inconvertibleErrorCode());1840 1841 // If -oop-executor was used but no value was specified then use a sensible1842 // default.1843 if (!!OutOfProcessExecutor.getNumOccurrences() &&1844 OutOfProcessExecutor.empty()) {1845 SmallString<256> OOPExecutorPath(sys::fs::getMainExecutable(1846 ArgV0, reinterpret_cast<void *>(&sanitizeArguments)));1847 sys::path::remove_filename(OOPExecutorPath);1848 sys::path::append(OOPExecutorPath, "llvm-jitlink-executor");1849 OutOfProcessExecutor = OOPExecutorPath.str().str();1850 }1851 1852 // If lazy linking is requested then check compatibility with other options.1853 if (lazyLinkingRequested()) {1854 if (OrcRuntime.empty())1855 return make_error<StringError>("Lazy linking requries the ORC runtime",1856 inconvertibleErrorCode());1857 1858 if (!TestHarnesses.empty())1859 return make_error<StringError>(1860 "Lazy linking cannot be used with -harness mode",1861 inconvertibleErrorCode());1862 } else if (Speculate != SpeculateKind::None) {1863 errs() << "Warning: -speculate ignored as there are no -lazy inputs\n";1864 Speculate = SpeculateKind::None;1865 }1866 1867 if (Speculate == SpeculateKind::None) {1868 if (!SpeculateOrder.empty()) {1869 errs() << "Warning: -speculate-order ignored because speculation is "1870 "disabled\n";1871 SpeculateOrder = "";1872 }1873 1874 if (!RecordLazyExecs.empty()) {1875 errs() << "Warning: -record-lazy-execs ignored because speculation is "1876 "disabled\n";1877 RecordLazyExecs = "";1878 }1879 }1880 1881 return Error::success();1882}1883 1884static void addPhonyExternalsGenerator(Session &S) {1885 S.MainJD->addGenerator(std::make_unique<PhonyExternalsGenerator>());1886}1887 1888static Error createJITDylibs(Session &S,1889 std::map<unsigned, JITDylib *> &IdxToJD) {1890 // First, set up JITDylibs.1891 LLVM_DEBUG(dbgs() << "Creating JITDylibs...\n");1892 {1893 // Create a "main" JITLinkDylib.1894 IdxToJD[0] = S.MainJD;1895 S.JDSearchOrder.push_back({S.MainJD, JITDylibLookupFlags::MatchAllSymbols});1896 LLVM_DEBUG(dbgs() << " 0: " << S.MainJD->getName() << "\n");1897 1898 // Add any extra JITDylibs from the command line.1899 for (auto JDItr = JITDylibs.begin(), JDEnd = JITDylibs.end();1900 JDItr != JDEnd; ++JDItr) {1901 auto JD = S.ES.createJITDylib(*JDItr);1902 if (!JD)1903 return JD.takeError();1904 unsigned JDIdx = JITDylibs.getPosition(JDItr - JITDylibs.begin());1905 IdxToJD[JDIdx] = &*JD;1906 S.JDSearchOrder.push_back({&*JD, JITDylibLookupFlags::MatchAllSymbols});1907 LLVM_DEBUG(dbgs() << " " << JDIdx << ": " << JD->getName() << "\n");1908 }1909 }1910 1911 if (S.PlatformJD)1912 S.JDSearchOrder.push_back(1913 {S.PlatformJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});1914 if (S.ProcessSymsJD)1915 S.JDSearchOrder.push_back(1916 {S.ProcessSymsJD, JITDylibLookupFlags::MatchExportedSymbolsOnly});1917 1918 LLVM_DEBUG({1919 dbgs() << "Dylib search order is [ ";1920 for (auto &KV : S.JDSearchOrder)1921 dbgs() << KV.first->getName() << " ";1922 dbgs() << "]\n";1923 });1924 1925 return Error::success();1926}1927 1928static Error addAbsoluteSymbols(Session &S,1929 const std::map<unsigned, JITDylib *> &IdxToJD) {1930 // Define absolute symbols.1931 LLVM_DEBUG(dbgs() << "Defining absolute symbols...\n");1932 for (auto AbsDefItr = AbsoluteDefs.begin(), AbsDefEnd = AbsoluteDefs.end();1933 AbsDefItr != AbsDefEnd; ++AbsDefItr) {1934 unsigned AbsDefArgIdx =1935 AbsoluteDefs.getPosition(AbsDefItr - AbsoluteDefs.begin());1936 auto &JD = *std::prev(IdxToJD.lower_bound(AbsDefArgIdx))->second;1937 1938 StringRef AbsDefStmt = *AbsDefItr;1939 size_t EqIdx = AbsDefStmt.find_first_of('=');1940 if (EqIdx == StringRef::npos)1941 return make_error<StringError>("Invalid absolute define \"" + AbsDefStmt +1942 "\". Syntax: <name>=<addr>",1943 inconvertibleErrorCode());1944 StringRef Name = AbsDefStmt.substr(0, EqIdx).trim();1945 StringRef AddrStr = AbsDefStmt.substr(EqIdx + 1).trim();1946 1947 uint64_t Addr;1948 if (AddrStr.getAsInteger(0, Addr))1949 return make_error<StringError>("Invalid address expression \"" + AddrStr +1950 "\" in absolute symbol definition \"" +1951 AbsDefStmt + "\"",1952 inconvertibleErrorCode());1953 ExecutorSymbolDef AbsDef(ExecutorAddr(Addr), JITSymbolFlags::Exported);1954 auto InternedName = S.ES.intern(Name);1955 if (auto Err = JD.define(absoluteSymbols({{InternedName, AbsDef}})))1956 return Err;1957 1958 // Register the absolute symbol with the session symbol infos.1959 S.SymbolInfos[std::move(InternedName)] =1960 {ArrayRef<char>(), Addr, AbsDef.getFlags().getTargetFlags()};1961 }1962 1963 return Error::success();1964}1965 1966static Error addAliases(Session &S,1967 const std::map<unsigned, JITDylib *> &IdxToJD) {1968 // Define absolute symbols.1969 LLVM_DEBUG(dbgs() << "Defining aliases...\n");1970 1971 DenseMap<std::pair<JITDylib *, JITDylib *>, SymbolAliasMap> Reexports;1972 for (auto AliasItr = Aliases.begin(), AliasEnd = Aliases.end();1973 AliasItr != AliasEnd; ++AliasItr) {1974 1975 auto BadExpr = [&]() {1976 return make_error<StringError>(1977 "Invalid alias definition \"" + *AliasItr +1978 "\". Syntax: [<dst-jd>:]<alias>=[<src-jd>:]<aliasee>",1979 inconvertibleErrorCode());1980 };1981 1982 auto GetJD = [&](StringRef JDName) -> Expected<JITDylib *> {1983 if (JDName.empty()) {1984 unsigned AliasArgIdx = Aliases.getPosition(AliasItr - Aliases.begin());1985 return std::prev(IdxToJD.lower_bound(AliasArgIdx))->second;1986 }1987 1988 auto *JD = S.ES.getJITDylibByName(JDName);1989 if (!JD)1990 return make_error<StringError>(StringRef("In alias definition \"") +1991 *AliasItr + "\" no dylib named " +1992 JDName,1993 inconvertibleErrorCode());1994 1995 return JD;1996 };1997 1998 {1999 // First split on '=' to get alias and aliasee.2000 StringRef AliasStmt = *AliasItr;2001 auto [AliasExpr, AliaseeExpr] = AliasStmt.split('=');2002 if (AliaseeExpr.empty())2003 return BadExpr();2004 2005 auto [AliasJDName, Alias] = AliasExpr.split(':');2006 if (Alias.empty())2007 std::swap(AliasJDName, Alias);2008 2009 auto AliasJD = GetJD(AliasJDName);2010 if (!AliasJD)2011 return AliasJD.takeError();2012 2013 auto [AliaseeJDName, Aliasee] = AliaseeExpr.split(':');2014 if (Aliasee.empty())2015 std::swap(AliaseeJDName, Aliasee);2016 2017 if (AliaseeJDName.empty() && !AliasJDName.empty())2018 AliaseeJDName = AliasJDName;2019 auto AliaseeJD = GetJD(AliaseeJDName);2020 if (!AliaseeJD)2021 return AliaseeJD.takeError();2022 2023 Reexports[{*AliasJD, *AliaseeJD}][S.ES.intern(Alias)] = {2024 S.ES.intern(Aliasee), JITSymbolFlags::Exported};2025 }2026 }2027 2028 for (auto &[JDs, AliasMap] : Reexports) {2029 auto [DstJD, SrcJD] = JDs;2030 if (auto Err = DstJD->define(reexports(*SrcJD, std::move(AliasMap))))2031 return Err;2032 }2033 2034 return Error::success();2035}2036 2037static Error addSectCreates(Session &S,2038 const std::map<unsigned, JITDylib *> &IdxToJD) {2039 for (auto SCItr = SectCreate.begin(), SCEnd = SectCreate.end();2040 SCItr != SCEnd; ++SCItr) {2041 2042 unsigned SCArgIdx = SectCreate.getPosition(SCItr - SectCreate.begin());2043 auto &JD = *std::prev(IdxToJD.lower_bound(SCArgIdx))->second;2044 2045 StringRef SCArg(*SCItr);2046 2047 auto [SectAndFileName, ExtraSymbolsString] = SCArg.rsplit('@');2048 auto [SectName, FileName] = SectAndFileName.rsplit(',');2049 if (SectName.empty())2050 return make_error<StringError>("In -sectcreate=" + SCArg +2051 ", filename component cannot be empty",2052 inconvertibleErrorCode());2053 if (FileName.empty())2054 return make_error<StringError>("In -sectcreate=" + SCArg +2055 ", filename component cannot be empty",2056 inconvertibleErrorCode());2057 2058 auto Content = getFile(FileName);2059 if (!Content)2060 return Content.takeError();2061 2062 SectCreateMaterializationUnit::ExtraSymbolsMap ExtraSymbols;2063 while (!ExtraSymbolsString.empty()) {2064 StringRef NextSymPair;2065 std::tie(NextSymPair, ExtraSymbolsString) = ExtraSymbolsString.split(',');2066 2067 auto [Sym, OffsetString] = NextSymPair.split('=');2068 size_t Offset;2069 2070 if (OffsetString.getAsInteger(0, Offset))2071 return make_error<StringError>("In -sectcreate=" + SCArg + ", " +2072 OffsetString +2073 " is not a valid integer",2074 inconvertibleErrorCode());2075 2076 ExtraSymbols[S.ES.intern(Sym)] = {JITSymbolFlags::Exported, Offset};2077 }2078 2079 if (auto Err = JD.define(std::make_unique<SectCreateMaterializationUnit>(2080 S.ObjLayer, SectName.str(), MemProt::Read, 16, std::move(*Content),2081 std::move(ExtraSymbols))))2082 return Err;2083 }2084 2085 return Error::success();2086}2087 2088static Error addTestHarnesses(Session &S) {2089 LLVM_DEBUG(dbgs() << "Adding test harness objects...\n");2090 for (auto HarnessFile : TestHarnesses) {2091 LLVM_DEBUG(dbgs() << " " << HarnessFile << "\n");2092 auto Linkable = loadLinkableFile(HarnessFile, S.ES.getTargetTriple(),2093 LoadArchives::Never);2094 if (!Linkable)2095 return Linkable.takeError();2096 if (auto Err = S.ObjLayer.add(*S.MainJD, std::move(Linkable->first)))2097 return Err;2098 }2099 return Error::success();2100}2101 2102static Error addObjects(Session &S,2103 const std::map<unsigned, JITDylib *> &IdxToJD,2104 const DenseSet<unsigned> &LazyLinkIdxs) {2105 2106 // Load each object into the corresponding JITDylib..2107 LLVM_DEBUG(dbgs() << "Adding objects...\n");2108 for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();2109 InputFileItr != InputFileEnd; ++InputFileItr) {2110 unsigned InputFileArgIdx =2111 InputFiles.getPosition(InputFileItr - InputFiles.begin());2112 const std::string &InputFile = *InputFileItr;2113 if (StringRef(InputFile).ends_with(".a") ||2114 StringRef(InputFile).ends_with(".lib"))2115 continue;2116 auto &JD = *std::prev(IdxToJD.lower_bound(InputFileArgIdx))->second;2117 bool AddLazy = LazyLinkIdxs.count(InputFileArgIdx);2118 LLVM_DEBUG(dbgs() << " " << InputFileArgIdx << ": \"" << InputFile << "\" "2119 << (AddLazy ? " (lazy-linked)" : "") << " to "2120 << JD.getName() << "\n";);2121 auto ObjBuffer = loadLinkableFile(InputFile, S.ES.getTargetTriple(),2122 LoadArchives::Never);2123 if (!ObjBuffer)2124 return ObjBuffer.takeError();2125 2126 if (S.HarnessFiles.empty()) {2127 if (auto Err =2128 S.getLinkLayer(AddLazy).add(JD, std::move(ObjBuffer->first)))2129 return Err;2130 } else {2131 // We're in -harness mode. Use a custom interface for this2132 // test object.2133 auto ObjInterface =2134 getTestObjectFileInterface(S, ObjBuffer->first->getMemBufferRef());2135 if (!ObjInterface)2136 return ObjInterface.takeError();2137 2138 if (auto Err = S.ObjLayer.add(JD, std::move(ObjBuffer->first),2139 std::move(*ObjInterface)))2140 return Err;2141 }2142 }2143 2144 return Error::success();2145}2146 2147static Expected<MaterializationUnit::Interface>2148getObjectFileInterfaceHidden(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {2149 auto I = getObjectFileInterface(ES, ObjBuffer);2150 if (I) {2151 for (auto &KV : I->SymbolFlags)2152 KV.second &= ~JITSymbolFlags::Exported;2153 }2154 return I;2155}2156 2157static SmallVector<StringRef, 5> getSearchPathsFromEnvVar(Session &S) {2158 // FIXME: Handle EPC environment.2159 SmallVector<StringRef, 5> PathVec;2160 auto TT = S.ES.getTargetTriple();2161 if (TT.isOSBinFormatCOFF())2162 StringRef(getenv("PATH")).split(PathVec, ";");2163 else if (TT.isOSBinFormatELF())2164 StringRef(getenv("LD_LIBRARY_PATH")).split(PathVec, ":");2165 2166 return PathVec;2167}2168 2169static Expected<std::unique_ptr<DefinitionGenerator>>2170LoadLibraryWeak(Session &S, StringRef Path) {2171 auto Symbols = getDylibInterface(S.ES, Path);2172 if (!Symbols)2173 return Symbols.takeError();2174 2175 return std::make_unique<EPCDynamicLibrarySearchGenerator>(2176 S.ES, [Symbols = std::move(*Symbols)](const SymbolStringPtr &Sym) {2177 return Symbols.count(Sym);2178 });2179}2180 2181static Error addLibraries(Session &S,2182 const std::map<unsigned, JITDylib *> &IdxToJD,2183 const DenseSet<unsigned> &LazyLinkIdxs) {2184 2185 // 1. Collect search paths for each JITDylib.2186 DenseMap<const JITDylib *, SmallVector<StringRef, 2>> JDSearchPaths;2187 2188 for (auto LSPItr = LibrarySearchPaths.begin(),2189 LSPEnd = LibrarySearchPaths.end();2190 LSPItr != LSPEnd; ++LSPItr) {2191 unsigned LibrarySearchPathIdx =2192 LibrarySearchPaths.getPosition(LSPItr - LibrarySearchPaths.begin());2193 auto &JD = *std::prev(IdxToJD.lower_bound(LibrarySearchPathIdx))->second;2194 2195 StringRef LibrarySearchPath = *LSPItr;2196 if (sys::fs::get_file_type(LibrarySearchPath) !=2197 sys::fs::file_type::directory_file)2198 return make_error<StringError>("While linking " + JD.getName() + ", -L" +2199 LibrarySearchPath +2200 " does not point to a directory",2201 inconvertibleErrorCode());2202 2203 JDSearchPaths[&JD].push_back(*LSPItr);2204 }2205 2206 LLVM_DEBUG({2207 if (!JDSearchPaths.empty())2208 dbgs() << "Search paths:\n";2209 for (auto &KV : JDSearchPaths) {2210 dbgs() << " " << KV.first->getName() << ": [";2211 for (auto &LibSearchPath : KV.second)2212 dbgs() << " \"" << LibSearchPath << "\"";2213 dbgs() << " ]\n";2214 }2215 });2216 2217 // 2. Collect library loads2218 struct LibraryLoad {2219 std::string LibName;2220 bool IsPath = false;2221 unsigned Position;2222 ArrayRef<StringRef> CandidateExtensions;2223 enum { Standard, Hidden, Weak } Modifier;2224 };2225 2226 // Queue to load library as in the order as it appears in the argument list.2227 std::deque<LibraryLoad> LibraryLoadQueue;2228 2229 // Add archive files from the inputs to LibraryLoads.2230 for (auto InputFileItr = InputFiles.begin(), InputFileEnd = InputFiles.end();2231 InputFileItr != InputFileEnd; ++InputFileItr) {2232 StringRef InputFile = *InputFileItr;2233 if (!InputFile.ends_with(".a") && !InputFile.ends_with(".lib"))2234 continue;2235 LibraryLoad LL;2236 LL.LibName = InputFile.str();2237 LL.IsPath = true;2238 LL.Position = InputFiles.getPosition(InputFileItr - InputFiles.begin());2239 LL.CandidateExtensions = {};2240 LL.Modifier = LibraryLoad::Standard;2241 LibraryLoadQueue.push_back(std::move(LL));2242 }2243 2244 // Add -load_hidden arguments to LibraryLoads.2245 for (auto LibItr = LoadHidden.begin(), LibEnd = LoadHidden.end();2246 LibItr != LibEnd; ++LibItr) {2247 LibraryLoad LL;2248 LL.LibName = *LibItr;2249 LL.IsPath = true;2250 LL.Position = LoadHidden.getPosition(LibItr - LoadHidden.begin());2251 LL.CandidateExtensions = {};2252 LL.Modifier = LibraryLoad::Hidden;2253 LibraryLoadQueue.push_back(std::move(LL));2254 }2255 2256 // Add -weak_library arguments to LibraryLoads.2257 for (auto LibItr = WeakLibraries.begin(), LibEnd = WeakLibraries.end();2258 LibItr != LibEnd; ++LibItr) {2259 LibraryLoad LL;2260 LL.LibName = *LibItr;2261 LL.IsPath = true;2262 LL.Position = WeakLibraries.getPosition(LibItr - WeakLibraries.begin());2263 LL.CandidateExtensions = {};2264 LL.Modifier = LibraryLoad::Weak;2265 LibraryLoadQueue.push_back(std::move(LL));2266 }2267 2268 StringRef StandardExtensions[] = {".so", ".dylib", ".dll", ".a", ".lib"};2269 StringRef DynLibExtensionsOnly[] = {".so", ".dylib", ".dll"};2270 StringRef ArchiveExtensionsOnly[] = {".a", ".lib"};2271 StringRef WeakLinkExtensionsOnly[] = {".dylib", ".tbd"};2272 2273 // Add -lx arguments to LibraryLoads.2274 for (auto LibItr = Libraries.begin(), LibEnd = Libraries.end();2275 LibItr != LibEnd; ++LibItr) {2276 LibraryLoad LL;2277 LL.LibName = *LibItr;2278 LL.Position = Libraries.getPosition(LibItr - Libraries.begin());2279 LL.CandidateExtensions = StandardExtensions;2280 LL.Modifier = LibraryLoad::Standard;2281 LibraryLoadQueue.push_back(std::move(LL));2282 }2283 2284 // Add -hidden-lx arguments to LibraryLoads.2285 for (auto LibHiddenItr = LibrariesHidden.begin(),2286 LibHiddenEnd = LibrariesHidden.end();2287 LibHiddenItr != LibHiddenEnd; ++LibHiddenItr) {2288 LibraryLoad LL;2289 LL.LibName = *LibHiddenItr;2290 LL.Position =2291 LibrariesHidden.getPosition(LibHiddenItr - LibrariesHidden.begin());2292 LL.CandidateExtensions = ArchiveExtensionsOnly;2293 LL.Modifier = LibraryLoad::Hidden;2294 LibraryLoadQueue.push_back(std::move(LL));2295 }2296 2297 // Add -weak-lx arguments to LibraryLoads.2298 for (auto LibWeakItr = LibrariesWeak.begin(),2299 LibWeakEnd = LibrariesWeak.end();2300 LibWeakItr != LibWeakEnd; ++LibWeakItr) {2301 LibraryLoad LL;2302 LL.LibName = *LibWeakItr;2303 LL.Position = LibrariesWeak.getPosition(LibWeakItr - LibrariesWeak.begin());2304 LL.CandidateExtensions = WeakLinkExtensionsOnly;2305 LL.Modifier = LibraryLoad::Weak;2306 LibraryLoadQueue.push_back(std::move(LL));2307 }2308 2309 // Sort library loads by position in the argument list.2310 llvm::sort(LibraryLoadQueue,2311 [](const LibraryLoad &LHS, const LibraryLoad &RHS) {2312 return LHS.Position < RHS.Position;2313 });2314 2315 // 3. Process library loads.2316 auto AddArchive = [&](JITDylib &JD, const char *Path, const LibraryLoad &LL)2317 -> Expected<std::unique_ptr<StaticLibraryDefinitionGenerator>> {2318 StaticLibraryDefinitionGenerator::GetObjectFileInterface2319 GetObjFileInterface;2320 switch (LL.Modifier) {2321 case LibraryLoad::Standard:2322 GetObjFileInterface = getObjectFileInterface;2323 break;2324 case LibraryLoad::Hidden:2325 GetObjFileInterface = getObjectFileInterfaceHidden;2326 S.HiddenArchives.insert(Path);2327 break;2328 case LibraryLoad::Weak:2329 llvm_unreachable("Unsupported");2330 break;2331 }2332 2333 auto &LinkLayer = S.getLinkLayer(LazyLinkIdxs.count(LL.Position));2334 2335 std::set<std::string> ImportedDynamicLibraries;2336 StaticLibraryDefinitionGenerator::VisitMembersFunction VisitMembers;2337 2338 // COFF gets special handling due to import libraries.2339 if (S.ES.getTargetTriple().isOSBinFormatCOFF()) {2340 if (AllLoad) {2341 VisitMembers =2342 [ImportScanner = COFFImportFileScanner(ImportedDynamicLibraries),2343 LoadAll =2344 StaticLibraryDefinitionGenerator::loadAllObjectFileMembers(2345 LinkLayer, JD)](object::Archive &A,2346 MemoryBufferRef MemberBuf,2347 size_t Index) mutable -> Expected<bool> {2348 if (!ImportScanner(A, MemberBuf, Index))2349 return false;2350 return LoadAll(A, MemberBuf, Index);2351 };2352 } else2353 VisitMembers = COFFImportFileScanner(ImportedDynamicLibraries);2354 } else if (AllLoad)2355 VisitMembers = StaticLibraryDefinitionGenerator::loadAllObjectFileMembers(2356 LinkLayer, JD);2357 else if (S.ES.getTargetTriple().isOSBinFormatMachO() && ForceLoadObjC)2358 VisitMembers = ForceLoadMachOArchiveMembers(LinkLayer, JD, true);2359 2360 auto G = StaticLibraryDefinitionGenerator::Load(2361 LinkLayer, Path, std::move(VisitMembers),2362 std::move(GetObjFileInterface));2363 if (!G)2364 return G.takeError();2365 2366 // Push additional dynamic libraries to search.2367 // Note that this mechanism only happens in COFF.2368 for (auto FileName : ImportedDynamicLibraries) {2369 LibraryLoad NewLL;2370 auto FileNameRef = StringRef(FileName);2371 if (!FileNameRef.ends_with_insensitive(".dll"))2372 return make_error<StringError>(2373 "COFF Imported library not ending with dll extension?",2374 inconvertibleErrorCode());2375 NewLL.LibName = FileNameRef.drop_back(strlen(".dll")).str();2376 NewLL.Position = LL.Position;2377 NewLL.CandidateExtensions = DynLibExtensionsOnly;2378 NewLL.Modifier = LibraryLoad::Standard;2379 LibraryLoadQueue.push_front(std::move(NewLL));2380 }2381 return G;2382 };2383 2384 SmallVector<StringRef, 5> SystemSearchPaths;2385 if (SearchSystemLibrary.getValue())2386 SystemSearchPaths = getSearchPathsFromEnvVar(S);2387 while (!LibraryLoadQueue.empty()) {2388 bool LibFound = false;2389 auto LL = LibraryLoadQueue.front();2390 LibraryLoadQueue.pop_front();2391 auto &JD = *std::prev(IdxToJD.lower_bound(LL.Position))->second;2392 2393 // If this is the name of a JITDylib then link against that.2394 if (auto *LJD = S.ES.getJITDylibByName(LL.LibName)) {2395 if (LL.Modifier == LibraryLoad::Weak)2396 return make_error<StringError>(2397 "Can't use -weak-lx or -weak_library to load JITDylib " +2398 LL.LibName,2399 inconvertibleErrorCode());2400 JD.addToLinkOrder(*LJD);2401 continue;2402 }2403 2404 if (LL.IsPath) {2405 // Must be -weak_library.2406 if (LL.Modifier == LibraryLoad::Weak) {2407 if (auto G = LoadLibraryWeak(S, LL.LibName)) {2408 JD.addGenerator(std::move(*G));2409 continue;2410 } else2411 return G.takeError();2412 }2413 2414 // Otherwise handle archive.2415 auto G = AddArchive(JD, LL.LibName.c_str(), LL);2416 if (!G)2417 return createFileError(LL.LibName, G.takeError());2418 JD.addGenerator(std::move(*G));2419 LLVM_DEBUG({2420 dbgs() << "Adding generator for static library " << LL.LibName << " to "2421 << JD.getName() << "\n";2422 });2423 continue;2424 }2425 2426 // Otherwise look through the search paths.2427 auto CurJDSearchPaths = JDSearchPaths[&JD];2428 for (StringRef SearchPath :2429 concat<StringRef>(CurJDSearchPaths, SystemSearchPaths)) {2430 for (auto LibExt : LL.CandidateExtensions) {2431 SmallVector<char, 256> LibPath;2432 LibPath.reserve(SearchPath.size() + strlen("lib") + LL.LibName.size() +2433 LibExt.size() + 2); // +2 for pathsep, null term.2434 llvm::append_range(LibPath, SearchPath);2435 if (LibExt != ".lib" && LibExt != ".dll")2436 sys::path::append(LibPath, "lib" + LL.LibName + LibExt);2437 else2438 sys::path::append(LibPath, LL.LibName + LibExt);2439 LibPath.push_back('\0');2440 2441 // Skip missing or non-regular paths.2442 if (sys::fs::get_file_type(LibPath.data()) !=2443 sys::fs::file_type::regular_file) {2444 continue;2445 }2446 2447 file_magic Magic;2448 if (auto EC = identify_magic(LibPath, Magic)) {2449 // If there was an error loading the file then skip it.2450 LLVM_DEBUG({2451 dbgs() << "Library search found \"" << LibPath2452 << "\", but could not identify file type (" << EC.message()2453 << "). Skipping.\n";2454 });2455 continue;2456 }2457 2458 // We identified the magic. Assume that we can load it -- we'll reset2459 // in the default case.2460 LibFound = true;2461 switch (Magic) {2462 case file_magic::pecoff_executable:2463 case file_magic::elf_shared_object:2464 case file_magic::macho_dynamically_linked_shared_lib: {2465 if (LL.Modifier == LibraryLoad::Weak) {2466 if (auto G = LoadLibraryWeak(S, LibPath.data()))2467 JD.addGenerator(std::move(*G));2468 else2469 return G.takeError();2470 } else {2471 if (auto Err = S.loadAndLinkDynamicLibrary(JD, LibPath.data()))2472 return Err;2473 }2474 break;2475 }2476 case file_magic::archive:2477 case file_magic::macho_universal_binary: {2478 auto G = AddArchive(JD, LibPath.data(), LL);2479 if (!G)2480 return G.takeError();2481 JD.addGenerator(std::move(*G));2482 LLVM_DEBUG({2483 dbgs() << "Adding generator for static library " << LibPath.data()2484 << " to " << JD.getName() << "\n";2485 });2486 break;2487 }2488 case file_magic::tapi_file:2489 assert(LL.Modifier == LibraryLoad::Weak &&2490 "TextAPI file not being loaded as weak?");2491 if (auto G = LoadLibraryWeak(S, LibPath.data()))2492 JD.addGenerator(std::move(*G));2493 else2494 return G.takeError();2495 break;2496 default:2497 // This file isn't a recognized library kind.2498 LLVM_DEBUG({2499 dbgs() << "Library search found \"" << LibPath2500 << "\", but file type is not supported. Skipping.\n";2501 });2502 LibFound = false;2503 break;2504 }2505 if (LibFound)2506 break;2507 }2508 if (LibFound)2509 break;2510 }2511 2512 if (!LibFound)2513 return make_error<StringError>("While linking " + JD.getName() +2514 ", could not find library for -l" +2515 LL.LibName,2516 inconvertibleErrorCode());2517 }2518 2519 // Add platform and process symbols if available.2520 for (auto &[Idx, JD] : IdxToJD) {2521 if (S.PlatformJD)2522 JD->addToLinkOrder(*S.PlatformJD);2523 if (S.ProcessSymsJD)2524 JD->addToLinkOrder(*S.ProcessSymsJD);2525 }2526 2527 return Error::success();2528}2529 2530static Error addSpeculationOrder(Session &S) {2531 2532 if (SpeculateOrder.empty())2533 return Error::success();2534 2535 assert(S.LazyLinking && "SpeculateOrder set, but lazy linking not enabled");2536 assert(S.LazyLinking->Speculator && "SpeculatoOrder set, but no speculator");2537 2538 auto SpecOrderBuffer = getFile(SpeculateOrder);2539 if (!SpecOrderBuffer)2540 return SpecOrderBuffer.takeError();2541 2542 StringRef LineStream((*SpecOrderBuffer)->getBuffer());2543 std::vector<std::pair<std::string, SymbolStringPtr>> SpecOrder;2544 2545 size_t LineNumber = 0;2546 while (!LineStream.empty()) {2547 ++LineNumber;2548 2549 auto MakeSpecOrderErr = [&](StringRef Reason) {2550 return make_error<StringError>("Error in speculation order file \"" +2551 SpeculateOrder + "\" on line " +2552 Twine(LineNumber) + ": " + Reason,2553 inconvertibleErrorCode());2554 };2555 2556 StringRef CurLine;2557 std::tie(CurLine, LineStream) = LineStream.split('\n');2558 CurLine = CurLine.trim();2559 if (CurLine.empty())2560 continue;2561 2562 auto [JDName, FuncName] = CurLine.split(',');2563 2564 if (FuncName.empty())2565 return MakeSpecOrderErr("missing ',' separator");2566 2567 JDName = JDName.trim();2568 if (JDName.empty())2569 return MakeSpecOrderErr("no value for column 1 (JIT Dylib name)");2570 2571 FuncName = FuncName.trim();2572 if (FuncName.empty())2573 return MakeSpecOrderErr("no value for column 2 (function name)");2574 2575 SpecOrder.push_back({JDName.str(), S.ES.intern(FuncName)});2576 }2577 2578 S.LazyLinking->Speculator->addSpeculationSuggestions(std::move(SpecOrder));2579 2580 return Error::success();2581}2582 2583static Error addSessionInputs(Session &S) {2584 std::map<unsigned, JITDylib *> IdxToJD;2585 DenseSet<unsigned> LazyLinkIdxs;2586 2587 for (auto LLItr = LazyLink.begin(), LLEnd = LazyLink.end(); LLItr != LLEnd;2588 ++LLItr) {2589 if (*LLItr)2590 LazyLinkIdxs.insert(LazyLink.getPosition(LLItr - LazyLink.begin()) + 1);2591 }2592 2593 if (auto Err = createJITDylibs(S, IdxToJD))2594 return Err;2595 2596 if (auto Err = addAbsoluteSymbols(S, IdxToJD))2597 return Err;2598 2599 if (auto Err = addAliases(S, IdxToJD))2600 return Err;2601 2602 if (auto Err = addSectCreates(S, IdxToJD))2603 return Err;2604 2605 if (!TestHarnesses.empty())2606 if (auto Err = addTestHarnesses(S))2607 return Err;2608 2609 if (auto Err = addObjects(S, IdxToJD, LazyLinkIdxs))2610 return Err;2611 2612 if (auto Err = addLibraries(S, IdxToJD, LazyLinkIdxs))2613 return Err;2614 2615 if (auto Err = addSpeculationOrder(S))2616 return Err;2617 2618 return Error::success();2619}2620 2621namespace {2622struct TargetInfo {2623 const Target *TheTarget;2624 std::unique_ptr<MCSubtargetInfo> STI;2625 std::unique_ptr<MCRegisterInfo> MRI;2626 std::unique_ptr<MCAsmInfo> MAI;2627 std::unique_ptr<MCContext> Ctx;2628 std::unique_ptr<MCDisassembler> Disassembler;2629 std::unique_ptr<MCInstrInfo> MII;2630 std::unique_ptr<MCInstrAnalysis> MIA;2631 std::unique_ptr<MCInstPrinter> InstPrinter;2632};2633} // anonymous namespace2634 2635static TargetInfo2636getTargetInfo(const Triple &TT,2637 const SubtargetFeatures &TF = SubtargetFeatures()) {2638 std::string ErrorStr;2639 const Target *TheTarget = TargetRegistry::lookupTarget(TT, ErrorStr);2640 if (!TheTarget)2641 ExitOnErr(make_error<StringError>("Error accessing target '" + TT.str() +2642 "': " + ErrorStr,2643 inconvertibleErrorCode()));2644 2645 std::unique_ptr<MCSubtargetInfo> STI(2646 TheTarget->createMCSubtargetInfo(TT, "", TF.getString()));2647 if (!STI)2648 ExitOnErr(2649 make_error<StringError>("Unable to create subtarget for " + TT.str(),2650 inconvertibleErrorCode()));2651 2652 std::unique_ptr<MCRegisterInfo> MRI(TheTarget->createMCRegInfo(TT));2653 if (!MRI)2654 ExitOnErr(make_error<StringError>("Unable to create target register info "2655 "for " +2656 TT.str(),2657 inconvertibleErrorCode()));2658 2659 MCTargetOptions MCOptions;2660 std::unique_ptr<MCAsmInfo> MAI(2661 TheTarget->createMCAsmInfo(*MRI, TT, MCOptions));2662 if (!MAI)2663 ExitOnErr(2664 make_error<StringError>("Unable to create target asm info " + TT.str(),2665 inconvertibleErrorCode()));2666 2667 auto Ctx = std::make_unique<MCContext>(Triple(TT.str()), MAI.get(), MRI.get(),2668 STI.get());2669 2670 std::unique_ptr<MCDisassembler> Disassembler(2671 TheTarget->createMCDisassembler(*STI, *Ctx));2672 if (!Disassembler)2673 ExitOnErr(2674 make_error<StringError>("Unable to create disassembler for " + TT.str(),2675 inconvertibleErrorCode()));2676 2677 std::unique_ptr<MCInstrInfo> MII(TheTarget->createMCInstrInfo());2678 if (!MII)2679 ExitOnErr(make_error<StringError>("Unable to create instruction info for" +2680 TT.str(),2681 inconvertibleErrorCode()));2682 2683 std::unique_ptr<MCInstrAnalysis> MIA(2684 TheTarget->createMCInstrAnalysis(MII.get()));2685 if (!MIA)2686 ExitOnErr(make_error<StringError>(2687 "Unable to create instruction analysis for" + TT.str(),2688 inconvertibleErrorCode()));2689 2690 std::unique_ptr<MCInstPrinter> InstPrinter(2691 TheTarget->createMCInstPrinter(Triple(TT.str()), 0, *MAI, *MII, *MRI));2692 if (!InstPrinter)2693 ExitOnErr(make_error<StringError>(2694 "Unable to create instruction printer for" + TT.str(),2695 inconvertibleErrorCode()));2696 return {TheTarget, std::move(STI), std::move(MRI),2697 std::move(MAI), std::move(Ctx), std::move(Disassembler),2698 std::move(MII), std::move(MIA), std::move(InstPrinter)};2699}2700static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) {2701 if (CheckFiles.empty())2702 return Error::success();2703 2704 S.waitForFilesLinkedFromEntryPointFile();2705 2706 LLVM_DEBUG(dbgs() << "Running checks...\n");2707 2708 auto IsSymbolValid = [&S](StringRef Symbol) {2709 auto InternedSymbol = S.ES.getSymbolStringPool()->intern(Symbol);2710 return S.isSymbolRegistered(InternedSymbol);2711 };2712 2713 auto GetSymbolInfo = [&S](StringRef Symbol) {2714 auto InternedSymbol = S.ES.getSymbolStringPool()->intern(Symbol);2715 return S.findSymbolInfo(InternedSymbol, "Can not get symbol info");2716 };2717 2718 auto GetSectionInfo = [&S](StringRef FileName, StringRef SectionName) {2719 return S.findSectionInfo(FileName, SectionName);2720 };2721 2722 auto GetStubInfo = [&S](StringRef FileName, StringRef SectionName,2723 StringRef KindNameFilter) {2724 return S.findStubInfo(FileName, SectionName, KindNameFilter);2725 };2726 2727 auto GetGOTInfo = [&S](StringRef FileName, StringRef SectionName) {2728 return S.findGOTEntryInfo(FileName, SectionName);2729 };2730 2731 RuntimeDyldChecker Checker(2732 IsSymbolValid, GetSymbolInfo, GetSectionInfo, GetStubInfo, GetGOTInfo,2733 S.ES.getTargetTriple().isLittleEndian() ? llvm::endianness::little2734 : llvm::endianness::big,2735 TT, StringRef(), Features, dbgs());2736 2737 std::string CheckLineStart = "# " + CheckName + ":";2738 for (auto &CheckFile : CheckFiles) {2739 auto CheckerFileBuf = ExitOnErr(getFile(CheckFile));2740 if (!Checker.checkAllRulesInBuffer(CheckLineStart, &*CheckerFileBuf))2741 ExitOnErr(make_error<StringError>(2742 "Some checks in " + CheckFile + " failed", inconvertibleErrorCode()));2743 }2744 2745 return Error::success();2746}2747 2748static Error addSelfRelocations(LinkGraph &G) {2749 auto TI = getTargetInfo(G.getTargetTriple());2750 for (auto *Sym : G.defined_symbols())2751 if (Sym->isCallable())2752 if (auto Err = addFunctionPointerRelocationsToCurrentSymbol(2753 *Sym, G, *TI.Disassembler, *TI.MIA))2754 return Err;2755 return Error::success();2756}2757 2758static Expected<ExecutorSymbolDef> getMainEntryPoint(Session &S) {2759 return S.ES.lookup(S.JDSearchOrder, S.ES.intern(EntryPointName));2760}2761 2762static Expected<ExecutorSymbolDef> getOrcRuntimeEntryPoint(Session &S) {2763 std::string RuntimeEntryPoint = "__orc_rt_run_program_wrapper";2764 if (S.ES.getTargetTriple().getObjectFormat() == Triple::MachO)2765 RuntimeEntryPoint = '_' + RuntimeEntryPoint;2766 return S.ES.lookup(S.JDSearchOrder, S.ES.intern(RuntimeEntryPoint));2767}2768 2769static Expected<ExecutorSymbolDef> getEntryPoint(Session &S) {2770 ExecutorSymbolDef EntryPoint;2771 2772 // Find the entry-point function unconditionally, since we want to force2773 // it to be materialized to collect stats.2774 if (auto EP = getMainEntryPoint(S))2775 EntryPoint = *EP;2776 else2777 return EP.takeError();2778 LLVM_DEBUG({2779 dbgs() << "Using entry point \"" << EntryPointName2780 << "\": " << formatv("{0:x16}", EntryPoint.getAddress()) << "\n";2781 });2782 2783 // If we're running with the ORC runtime then replace the entry-point2784 // with the __orc_rt_run_program symbol.2785 if (!OrcRuntime.empty()) {2786 if (auto EP = getOrcRuntimeEntryPoint(S))2787 EntryPoint = *EP;2788 else2789 return EP.takeError();2790 LLVM_DEBUG({2791 dbgs() << "(called via __orc_rt_run_program_wrapper at "2792 << formatv("{0:x16}", EntryPoint.getAddress()) << ")\n";2793 });2794 }2795 2796 return EntryPoint;2797}2798 2799static Expected<int> runWithRuntime(Session &S, ExecutorAddr EntryPointAddr) {2800 StringRef DemangledEntryPoint = EntryPointName;2801 if (S.ES.getTargetTriple().getObjectFormat() == Triple::MachO &&2802 DemangledEntryPoint.front() == '_')2803 DemangledEntryPoint = DemangledEntryPoint.drop_front();2804 using llvm::orc::shared::SPSString;2805 using SPSRunProgramSig =2806 int64_t(SPSString, SPSString, shared::SPSSequence<SPSString>);2807 int64_t Result;2808 if (auto Err = S.ES.callSPSWrapper<SPSRunProgramSig>(2809 EntryPointAddr, Result, S.MainJD->getName(), DemangledEntryPoint,2810 static_cast<std::vector<std::string> &>(InputArgv)))2811 return std::move(Err);2812 return Result;2813}2814 2815static Expected<int> runWithoutRuntime(Session &S,2816 ExecutorAddr EntryPointAddr) {2817 return S.ES.getExecutorProcessControl().runAsMain(EntryPointAddr, InputArgv);2818}2819 2820namespace {2821struct JITLinkTimers {2822 TimerGroup JITLinkTG{"llvm-jitlink timers", "timers for llvm-jitlink phases"};2823 Timer LoadObjectsTimer{"load", "time to load/add object files", JITLinkTG};2824 Timer LinkTimer{"link", "time to link object files", JITLinkTG};2825 Timer RunTimer{"run", "time to execute jitlink'd code", JITLinkTG};2826};2827} // namespace2828 2829int main(int argc, char *argv[]) {2830 InitLLVM X(argc, argv);2831 2832 InitializeAllTargetInfos();2833 InitializeAllTargetMCs();2834 InitializeAllDisassemblers();2835 2836 cl::HideUnrelatedOptions({&JITLinkCategory, &getColorCategory()});2837 cl::ParseCommandLineOptions(argc, argv, "llvm jitlink tool");2838 ExitOnErr.setBanner(std::string(argv[0]) + ": ");2839 2840 /// If timers are enabled, create a JITLinkTimers instance.2841 std::unique_ptr<JITLinkTimers> Timers =2842 ShowTimes ? std::make_unique<JITLinkTimers>() : nullptr;2843 2844 auto [TT, Features] = getFirstFileTripleAndFeatures();2845 ExitOnErr(sanitizeArguments(TT, argv[0]));2846 2847 auto S = ExitOnErr(Session::Create(TT, Features));2848 2849 enableStatistics(*S, !OrcRuntime.empty());2850 2851 {2852 TimeRegion TR(Timers ? &Timers->LoadObjectsTimer : nullptr);2853 ExitOnErr(addSessionInputs(*S));2854 }2855 2856 if (PhonyExternals)2857 addPhonyExternalsGenerator(*S);2858 2859 if (ShowInitialExecutionSessionState)2860 S->ES.dump(outs());2861 2862 Expected<ExecutorSymbolDef> EntryPoint((ExecutorSymbolDef()));2863 {2864 ExpectedAsOutParameter<ExecutorSymbolDef> _(&EntryPoint);2865 TimeRegion TR(Timers ? &Timers->LinkTimer : nullptr);2866 EntryPoint = getEntryPoint(*S);2867 }2868 2869 // Print any reports regardless of whether we succeeded or failed.2870 if (ShowEntryExecutionSessionState)2871 S->ES.dump(outs());2872 2873 if (ShowAddrs)2874 S->dumpSessionInfo(outs());2875 2876 if (!EntryPoint) {2877 if (Timers)2878 Timers->JITLinkTG.printAll(errs());2879 reportLLVMJITLinkError(EntryPoint.takeError());2880 ExitOnErr(S->ES.endSession());2881 exit(1);2882 }2883 2884 ExitOnErr(runChecks(*S, std::move(TT), std::move(Features)));2885 2886 int Result = 0;2887 if (!NoExec) {2888 LLVM_DEBUG(dbgs() << "Running \"" << EntryPointName << "\"...\n");2889 TimeRegion TR(Timers ? &Timers->RunTimer : nullptr);2890 if (!OrcRuntime.empty())2891 Result =2892 ExitOnErr(runWithRuntime(*S, ExecutorAddr(EntryPoint->getAddress())));2893 else2894 Result = ExitOnErr(2895 runWithoutRuntime(*S, ExecutorAddr(EntryPoint->getAddress())));2896 }2897 2898 // Destroy the session.2899 ExitOnErr(S->ES.endSession());2900 S.reset();2901 2902 if (Timers)2903 Timers->JITLinkTG.printAll(errs());2904 2905 // If the executing code set a test result override then use that.2906 if (UseTestResultOverride)2907 Result = TestResultOverride;2908 2909 return Result;2910}2911