1 //===--------------- LLJITWithGDBRegistrationListener.cpp -----------------===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 //
9 // This file shows how to switch LLJIT to use a custom object linking layer (we
10 // use ObjectLinkingLayer, which is backed by JITLink, as an example).
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "llvm/ADT/StringMap.h"
15 #include "llvm/ExecutionEngine/JITEventListener.h"
16 #include "llvm/ExecutionEngine/JITLink/JITLinkMemoryManager.h"
17 #include "llvm/ExecutionEngine/Orc/ExecutionUtils.h"
18 #include "llvm/ExecutionEngine/Orc/LLJIT.h"
19 #include "llvm/ExecutionEngine/Orc/RTDyldObjectLinkingLayer.h"
20 #include "llvm/ExecutionEngine/Orc/TargetProcess/TargetExecutionUtils.h"
21 #include "llvm/ExecutionEngine/SectionMemoryManager.h"
22 #include "llvm/Support/InitLLVM.h"
23 #include "llvm/Support/TargetSelect.h"
24 #include "llvm/Support/raw_ostream.h"
25
26 #include "../ExampleModules.h"
27
28 using namespace llvm;
29 using namespace llvm::orc;
30
31 ExitOnError ExitOnErr;
32
33 static cl::opt<std::string>
34 EntryPointName("entry", cl::desc("Symbol to call as main entry point"),
35 cl::init("main"));
36
37 static cl::list<std::string> InputFiles(cl::Positional, cl::OneOrMore,
38 cl::desc("input files"));
39
40 static cl::list<std::string> InputArgv("args", cl::Positional,
41 cl::desc("<program arguments>..."),
42 cl::PositionalEatsArgs);
43
main(int argc,char * argv[])44 int main(int argc, char *argv[]) {
45 // Initialize LLVM.
46 InitLLVM X(argc, argv);
47
48 InitializeNativeTarget();
49 InitializeNativeTargetAsmPrinter();
50
51 cl::ParseCommandLineOptions(argc, argv, "LLJITWithGDBRegistrationListener");
52 ExitOnErr.setBanner(std::string(argv[0]) + ": ");
53
54 // Detect the host and set code model to small.
55 auto JTMB = ExitOnErr(JITTargetMachineBuilder::detectHost());
56 if (!JTMB.getTargetTriple().isOSLinux())
57 errs()
58 << "Warning: This demo may not work for platforms other than Linux.\n";
59
60 // Create an LLJIT instance and use a custom object linking layer creator to
61 // register the GDBRegistrationListener with our RTDyldObjectLinkingLayer.
62 auto J =
63 ExitOnErr(LLJITBuilder()
64 .setJITTargetMachineBuilder(std::move(JTMB))
65 .setObjectLinkingLayerCreator([&](ExecutionSession &ES,
66 const Triple &TT) {
67 auto GetMemMgr = []() {
68 return std::make_unique<SectionMemoryManager>();
69 };
70 auto ObjLinkingLayer =
71 std::make_unique<RTDyldObjectLinkingLayer>(
72 ES, std::move(GetMemMgr));
73
74 // Register the event listener.
75 ObjLinkingLayer->registerJITEventListener(
76 *JITEventListener::createGDBRegistrationListener());
77
78 // Make sure the debug info sections aren't stripped.
79 ObjLinkingLayer->setProcessAllSections(true);
80
81 return ObjLinkingLayer;
82 })
83 .create());
84
85 // Make sure that our process symbols are visible to JIT'd code.
86 {
87 MangleAndInterner Mangle(J->getExecutionSession(), J->getDataLayout());
88 J->getMainJITDylib().addGenerator(
89 ExitOnErr(orc::DynamicLibrarySearchGenerator::GetForCurrentProcess(
90 J->getDataLayout().getGlobalPrefix(),
91 [MainName = Mangle("main")](const orc::SymbolStringPtr &Name) {
92 return Name != MainName;
93 })));
94 }
95
96 // Load the input modules.
97 for (auto &InputFile : InputFiles) {
98 auto Ctx = std::make_unique<LLVMContext>();
99 SMDiagnostic Err;
100 std::unique_ptr<Module> M = parseIRFile(InputFile, Err, *Ctx);
101 if (!M) {
102 Err.print(argv[0], errs());
103 return 1;
104 }
105
106 ExitOnErr(J->addIRModule(ThreadSafeModule(std::move(M), std::move(Ctx))));
107 }
108
109 // Look up the entry point, cast it to a C main function pointer, then use
110 // runAsMain to call it.
111 auto EntryAddr = ExitOnErr(J->lookup(EntryPointName));
112 auto EntryFn = EntryAddr.toPtr<int(int, char *[])>();
113
114 return runAsMain(EntryFn, InputArgv, StringRef(InputFiles.front()));
115 }
116