llvm/llvm/tools/llvm-jitlink/llvm-jitlink.cpp

//===- llvm-jitlink.cpp -- Command line interface/tester for llvm-jitlink -===//
//
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
// See https://llvm.org/LICENSE.txt for license information.
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
//
//===----------------------------------------------------------------------===//
//
// This utility provides a simple command line interface to the llvm jitlink
// library, which makes relocatable object files executable in memory. Its
// primary function is as a testing utility for the jitlink library.
//
//===----------------------------------------------------------------------===//

#include "llvm-jitlink.h"
#include "llvm/BinaryFormat/Magic.h"
#include "llvm/Config/llvm-config.h" // for LLVM_ON_UNIX, LLVM_ENABLE_THREADS
#include "llvm/ExecutionEngine/Orc/COFFPlatform.h"
#include "llvm/ExecutionEngine/Orc/COFFVCRuntimeSupport.h"
#include "llvm/ExecutionEngine/Orc/DebugObjectManagerPlugin.h"
#include "llvm/ExecutionEngine/Orc/Debugging/DebugInfoSupport.h"
#include "llvm/ExecutionEngine/Orc/Debugging/DebuggerSupportPlugin.h"
#include "llvm/ExecutionEngine/Orc/Debugging/PerfSupportPlugin.h"
#include "llvm/ExecutionEngine/Orc/Debugging/VTuneSupportPlugin.h"
#include "llvm/ExecutionEngine/Orc/ELFNixPlatform.h"
#include "llvm/ExecutionEngine/Orc/EPCDebugObjectRegistrar.h"
#include "llvm/ExecutionEngine/Orc/EPCDynamicLibrarySearchGenerator.h"
#include "llvm/ExecutionEngine/Orc/EPCEHFrameRegistrar.h"
#include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
#include "llvm/ExecutionEngine/Orc/IndirectionUtils.h"
#include "llvm/ExecutionEngine/Orc/JITTargetMachineBuilder.h"
#include "llvm/ExecutionEngine/Orc/LoadLinkableFile.h"
#include "llvm/ExecutionEngine/Orc/MachOPlatform.h"
#include "llvm/ExecutionEngine/Orc/MapperJITLinkMemoryManager.h"
#include "llvm/ExecutionEngine/Orc/ObjectFileInterface.h"
#include "llvm/ExecutionEngine/Orc/SectCreate.h"
#include "llvm/ExecutionEngine/Orc/Shared/OrcRTBridge.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderPerf.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/JITLoaderVTune.h"
#include "llvm/ExecutionEngine/Orc/TargetProcess/RegisterEHFrames.h"
#include "llvm/MC/MCAsmInfo.h"
#include "llvm/MC/MCContext.h"
#include "llvm/MC/MCDisassembler/MCDisassembler.h"
#include "llvm/MC/MCInstPrinter.h"
#include "llvm/MC/MCInstrAnalysis.h"
#include "llvm/MC/MCInstrInfo.h"
#include "llvm/MC/MCRegisterInfo.h"
#include "llvm/MC/MCSubtargetInfo.h"
#include "llvm/MC/MCTargetOptions.h"
#include "llvm/MC/TargetRegistry.h"
#include "llvm/Object/COFF.h"
#include "llvm/Object/MachO.h"
#include "llvm/Object/ObjectFile.h"
#include "llvm/Support/CommandLine.h"
#include "llvm/Support/Debug.h"
#include "llvm/Support/InitLLVM.h"
#include "llvm/Support/MemoryBuffer.h"
#include "llvm/Support/Path.h"
#include "llvm/Support/Process.h"
#include "llvm/Support/TargetSelect.h"
#include "llvm/Support/Timer.h"
#include <cstring>
#include <deque>
#include <string>

#ifdef LLVM_ON_UNIX
#include <netdb.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <unistd.h>
#endif // LLVM_ON_UNIX

#define DEBUG_TYPE

usingnamespacellvm;
usingnamespacellvm::jitlink;
usingnamespacellvm::orc;

static cl::OptionCategory JITLinkCategory("JITLink Options");

static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
                                        cl::desc("input files"),
                                        cl::cat(JITLinkCategory));

static cl::list<std::string>
    LibrarySearchPaths("L",
                       cl::desc("Add dir to the list of library search paths"),
                       cl::Prefix, cl::cat(JITLinkCategory));

static cl::list<std::string>
    Libraries("l",
              cl::desc("Link against library X in the library search paths"),
              cl::Prefix, cl::cat(JITLinkCategory));

static cl::list<std::string>
    LibrariesHidden("hidden-l",
                    cl::desc("Link against library X in the library search "
                             "paths with hidden visibility"),
                    cl::Prefix, cl::cat(JITLinkCategory));

static cl::list<std::string>
    LoadHidden("load_hidden",
               cl::desc("Link against library X with hidden visibility"),
               cl::cat(JITLinkCategory));

static cl::opt<bool> SearchSystemLibrary(
    "search-sys-lib",
    cl::desc("Add system library paths to library search paths"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool> NoExec("noexec", cl::desc("Do not execute loaded code"),
                            cl::init(false), cl::cat(JITLinkCategory));

static cl::list<std::string>
    CheckFiles("check", cl::desc("File containing verifier checks"),
               cl::cat(JITLinkCategory));

static cl::opt<std::string>
    CheckName("check-name", cl::desc("Name of checks to match against"),
              cl::init("jitlink-check"), cl::cat(JITLinkCategory));

static cl::opt<std::string>
    EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
                   cl::init(""), cl::cat(JITLinkCategory));

static cl::list<std::string> JITDylibs(
    "jd",
    cl::desc("Specifies the JITDylib to be used for any subsequent "
             "input file, -L<seacrh-path>, and -l<library> arguments"),
    cl::cat(JITLinkCategory));

static cl::list<std::string>
    Dylibs("preload",
           cl::desc("Pre-load dynamic libraries (e.g. language runtimes "
                    "required by the ORC runtime)"),
           cl::cat(JITLinkCategory));

static cl::list<std::string> InputArgv("args", cl::Positional,
                                       cl::desc("<program arguments>..."),
                                       cl::PositionalEatsArgs,
                                       cl::cat(JITLinkCategory));

static cl::opt<bool>
    DebuggerSupport("debugger-support",
                    cl::desc("Enable debugger suppport (default = !-noexec)"),
                    cl::init(true), cl::Hidden, cl::cat(JITLinkCategory));

static cl::opt<bool> PerfSupport("perf-support",
                                 cl::desc("Enable perf profiling support"),
                                 cl::init(false), cl::Hidden,
                                 cl::cat(JITLinkCategory));

static cl::opt<bool> VTuneSupport("vtune-support",
                                  cl::desc("Enable vtune profiling support"),
                                  cl::init(false), cl::Hidden,
                                  cl::cat(JITLinkCategory));
static cl::opt<bool>
    NoProcessSymbols("no-process-syms",
                     cl::desc("Do not resolve to llvm-jitlink process symbols"),
                     cl::init(false), cl::cat(JITLinkCategory));

static cl::list<std::string> AbsoluteDefs(
    "abs",
    cl::desc("Inject absolute symbol definitions (syntax: <name>=<addr>)"),
    cl::cat(JITLinkCategory));

static cl::list<std::string>
    Aliases("alias",
            cl::desc("Inject symbol aliases (syntax: <alias-name>=<aliasee>)"),
            cl::cat(JITLinkCategory));

static cl::list<std::string>
    SectCreate("sectcreate",
               cl::desc("given <sectname>,<filename>[@<sym>=<offset>,...]  "
                        "add the content of <filename> to <sectname>"),
               cl::cat(JITLinkCategory));

static cl::list<std::string> TestHarnesses("harness", cl::Positional,
                                           cl::desc("Test harness files"),
                                           cl::PositionalEatsArgs,
                                           cl::cat(JITLinkCategory));

static cl::opt<bool> ShowInitialExecutionSessionState(
    "show-init-es",
    cl::desc("Print ExecutionSession state before resolving entry point"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool> ShowEntryExecutionSessionState(
    "show-entry-es",
    cl::desc("Print ExecutionSession state after resolving entry point"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool> ShowAddrs(
    "show-addrs",
    cl::desc("Print registered symbol, section, got and stub addresses"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<std::string> ShowLinkGraphs(
    "show-graphs",
    cl::desc("Takes a posix regex and prints the link graphs of all files "
             "matching that regex after fixups have been applied"),
    cl::Optional, cl::cat(JITLinkCategory));

static cl::opt<bool> ShowTimes("show-times",
                               cl::desc("Show times for llvm-jitlink phases"),
                               cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<std::string> SlabAllocateSizeString(
    "slab-allocate",
    cl::desc("Allocate from a slab of the given size "
             "(allowable suffixes: Kb, Mb, Gb. default = "
             "Kb)"),
    cl::init(""), cl::cat(JITLinkCategory));

static cl::opt<uint64_t> SlabAddress(
    "slab-address",
    cl::desc("Set slab target address (requires -slab-allocate and -noexec)"),
    cl::init(~0ULL), cl::cat(JITLinkCategory));

static cl::opt<uint64_t> SlabPageSize(
    "slab-page-size",
    cl::desc("Set page size for slab (requires -slab-allocate and -noexec)"),
    cl::init(0), cl::cat(JITLinkCategory));

static cl::opt<bool> ShowRelocatedSectionContents(
    "show-relocated-section-contents",
    cl::desc("show section contents after fixups have been applied"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool> PhonyExternals(
    "phony-externals",
    cl::desc("resolve all otherwise unresolved externals to null"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<std::string> OutOfProcessExecutor(
    "oop-executor", cl::desc("Launch an out-of-process executor to run code"),
    cl::ValueOptional, cl::cat(JITLinkCategory));

static cl::opt<std::string> OutOfProcessExecutorConnect(
    "oop-executor-connect",
    cl::desc("Connect to an out-of-process executor via TCP"),
    cl::cat(JITLinkCategory));

static cl::opt<std::string>
    OrcRuntime("orc-runtime", cl::desc("Use ORC runtime from given path"),
               cl::init(""), cl::cat(JITLinkCategory));

static cl::opt<bool> AddSelfRelocations(
    "add-self-relocations",
    cl::desc("Add relocations to function pointers to the current function"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool>
    ShowErrFailedToMaterialize("show-err-failed-to-materialize",
                               cl::desc("Show FailedToMaterialize errors"),
                               cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<bool> UseSharedMemory(
    "use-shared-memory",
    cl::desc("Use shared memory to transfer generated code and data"),
    cl::init(false), cl::cat(JITLinkCategory));

static cl::opt<std::string>
    OverrideTriple("triple", cl::desc("Override target triple detection"),
                   cl::init(""), cl::cat(JITLinkCategory));

static ExitOnError ExitOnErr;

static LLVM_ATTRIBUTE_USED void linkComponents() {}

static bool UseTestResultOverride =;
static int64_t TestResultOverride =;

extern "C" LLVM_ATTRIBUTE_USED void
llvm_jitlink_setTestResultOverride(int64_t Value) {}

static Error addSelfRelocations(LinkGraph &G);

namespace {

template <typename ErrT>

class ConditionalPrintErr {};

Expected<std::unique_ptr<MemoryBuffer>> getFile(const Twine &FileName) {}

void reportLLVMJITLinkError(Error Err) {}

} // end anonymous namespace

namespace llvm {

static raw_ostream &
operator<<(raw_ostream &OS, const Session::MemoryRegionInfo &MRI) {}

static raw_ostream &
operator<<(raw_ostream &OS, const Session::SymbolInfoMap &SIM) {}

static raw_ostream &
operator<<(raw_ostream &OS, const Session::FileInfo &FI) {}

static raw_ostream &
operator<<(raw_ostream &OS, const Session::FileInfoMap &FIM) {}

static Error applyHarnessPromotions(Session &S, LinkGraph &G) {}

static void dumpSectionContents(raw_ostream &OS, LinkGraph &G) {}

// A memory mapper with a fake offset applied only used for -noexec testing
class InProcessDeltaMapper final : public InProcessMemoryMapper {};

Expected<uint64_t> getSlabAllocSize(StringRef SizeString) {}

static std::unique_ptr<JITLinkMemoryManager> createInProcessMemoryManager() {}

Expected<std::unique_ptr<jitlink::JITLinkMemoryManager>>
createSharedMemoryManager(SimpleRemoteEPC &SREPC) {}


static Expected<MaterializationUnit::Interface>
getTestObjectFileInterface(Session &S, MemoryBufferRef O) {}

static Error loadProcessSymbols(Session &S) {}

static Error loadDylibs(Session &S) {}

static Expected<std::unique_ptr<ExecutorProcessControl>> launchExecutor() {}

#if LLVM_ON_UNIX && LLVM_ENABLE_THREADS
static Error createTCPSocketError(Twine Details) {}

static Expected<int> connectTCPSocket(std::string Host, std::string PortStr) {}
#endif

static Expected<std::unique_ptr<ExecutorProcessControl>> connectToExecutor() {}

class PhonyExternalsGenerator : public DefinitionGenerator {};

Expected<std::unique_ptr<Session>> Session::Create(Triple TT,
                                                   SubtargetFeatures Features) {}

Session::~Session() {}

Session::Session(std::unique_ptr<ExecutorProcessControl> EPC, Error &Err)
    :{}

void Session::dumpSessionInfo(raw_ostream &OS) {}

void Session::modifyPassConfig(const Triple &TT,
                               PassConfiguration &PassConfig) {}

Expected<JITDylib *> Session::getOrLoadDynamicLibrary(StringRef LibPath) {}

Error Session::loadAndLinkDynamicLibrary(JITDylib &JD, StringRef LibPath) {}

Error Session::FileInfo::registerGOTEntry(
    LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {}

Error Session::FileInfo::registerStubEntry(
    LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {}

Error Session::FileInfo::registerMultiStubEntry(
    LinkGraph &G, Symbol &Sym, GetSymbolTargetFunction GetSymbolTarget) {}

Expected<Session::FileInfo &> Session::findFileInfo(StringRef FileName) {}

Expected<Session::MemoryRegionInfo &>
Session::findSectionInfo(StringRef FileName, StringRef SectionName) {}

class MemoryMatcher {};

static StringRef detectStubKind(const Session::MemoryRegionInfo &Stub) {}

Expected<Session::MemoryRegionInfo &>
Session::findStubInfo(StringRef FileName, StringRef TargetName,
                      StringRef KindNameFilter) {}

Expected<Session::MemoryRegionInfo &>
Session::findGOTEntryInfo(StringRef FileName, StringRef TargetName) {}

bool Session::isSymbolRegistered(StringRef SymbolName) {}

Expected<Session::MemoryRegionInfo &>
Session::findSymbolInfo(StringRef SymbolName, Twine ErrorMsgStem) {}

} // end namespace llvm

static std::pair<Triple, SubtargetFeatures> getFirstFileTripleAndFeatures() {}

static Error sanitizeArguments(const Triple &TT, const char *ArgV0) {}

static void addPhonyExternalsGenerator(Session &S) {}

static Error createJITDylibs(Session &S,
                             std::map<unsigned, JITDylib *> &IdxToJD) {}

static Error addAbsoluteSymbols(Session &S,
                                const std::map<unsigned, JITDylib *> &IdxToJD) {}

static Error addAliases(Session &S,
                        const std::map<unsigned, JITDylib *> &IdxToJD) {}

static Error addSectCreates(Session &S,
                            const std::map<unsigned, JITDylib *> &IdxToJD) {}

static Error addTestHarnesses(Session &S) {}

static Error addObjects(Session &S,
                        const std::map<unsigned, JITDylib *> &IdxToJD) {}

static Expected<MaterializationUnit::Interface>
getObjectFileInterfaceHidden(ExecutionSession &ES, MemoryBufferRef ObjBuffer) {}

static SmallVector<StringRef, 5> getSearchPathsFromEnvVar(Session &S) {}

static Error addLibraries(Session &S,
                          const std::map<unsigned, JITDylib *> &IdxToJD) {}

static Error addSessionInputs(Session &S) {}

namespace {
struct TargetInfo {};
} // anonymous namespace

static TargetInfo
getTargetInfo(const Triple &TT,
              const SubtargetFeatures &TF = SubtargetFeatures()) {}
static Error runChecks(Session &S, Triple TT, SubtargetFeatures Features) {}

static Error addSelfRelocations(LinkGraph &G) {}

static Expected<ExecutorSymbolDef> getMainEntryPoint(Session &S) {}

static Expected<ExecutorSymbolDef> getOrcRuntimeEntryPoint(Session &S) {}

static Expected<ExecutorSymbolDef> getEntryPoint(Session &S) {}

static Expected<int> runWithRuntime(Session &S, ExecutorAddr EntryPointAddr) {}

static Expected<int> runWithoutRuntime(Session &S,
                                       ExecutorAddr EntryPointAddr) {}

namespace {
struct JITLinkTimers {};
} // namespace

int main(int argc, char *argv[]) {}