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