xref: /openbsd-src/gnu/llvm/llvm/tools/lli/ExecutionUtils.cpp (revision 73471bf04ceb096474c7f0fa83b1b65c70a787a1)
1 //===---- ExecutionUtils.cpp - Utilities for executing functions in lli ---===//
2 //
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6 //
7 //===----------------------------------------------------------------------===//
8 
9 #include "ExecutionUtils.h"
10 
11 #include "llvm/Support/FileSystem.h"
12 #include "llvm/Support/FormatVariadic.h"
13 #include "llvm/Support/raw_ostream.h"
14 
15 #include <cstdint>
16 #include <vector>
17 
18 // Declarations follow the GDB JIT interface (version 1, 2009) and must match
19 // those of the DYLD used for testing. See:
20 //
21 //   llvm/lib/ExecutionEngine/Orc/TargetProcess/JITLoaderGDB.cpp
22 //   llvm/lib/ExecutionEngine/GDBRegistrationListener.cpp
23 //
24 typedef enum {
25   JIT_NOACTION = 0,
26   JIT_REGISTER_FN,
27   JIT_UNREGISTER_FN
28 } jit_actions_t;
29 
30 struct jit_code_entry {
31   struct jit_code_entry *next_entry;
32   struct jit_code_entry *prev_entry;
33   const char *symfile_addr;
34   uint64_t symfile_size;
35 };
36 
37 struct jit_descriptor {
38   uint32_t version;
39   // This should be jit_actions_t, but we want to be specific about the
40   // bit-width.
41   uint32_t action_flag;
42   struct jit_code_entry *relevant_entry;
43   struct jit_code_entry *first_entry;
44 };
45 
46 namespace llvm {
47 
outsv(const char * Fmt,Ts &&...Vals)48 template <typename... Ts> static void outsv(const char *Fmt, Ts &&...Vals) {
49   outs() << formatv(Fmt, Vals...);
50 }
51 
actionFlagToStr(uint32_t ActionFlag)52 static const char *actionFlagToStr(uint32_t ActionFlag) {
53   switch (ActionFlag) {
54   case JIT_NOACTION:
55     return "JIT_NOACTION";
56   case JIT_REGISTER_FN:
57     return "JIT_REGISTER_FN";
58   case JIT_UNREGISTER_FN:
59     return "JIT_UNREGISTER_FN";
60   }
61   return "<invalid action_flag>";
62 }
63 
64 // Sample output:
65 //
66 //   Reading __jit_debug_descriptor at 0x0000000000404048
67 //
68 //   Version: 0
69 //   Action: JIT_REGISTER_FN
70 //
71 //         Entry               Symbol File         Size  Previous Entry
72 //   [ 0]  0x0000000000451290  0x0000000000002000   200  0x0000000000000000
73 //   [ 1]  0x0000000000451260  0x0000000000001000   100  0x0000000000451290
74 //   ...
75 //
dumpDebugDescriptor(void * Addr)76 static void dumpDebugDescriptor(void *Addr) {
77   outsv("Reading __jit_debug_descriptor at {0}\n\n", Addr);
78 
79   jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
80   outsv("Version: {0}\n", Descriptor->version);
81   outsv("Action: {0}\n\n", actionFlagToStr(Descriptor->action_flag));
82   outsv("{0,11}  {1,24}  {2,15}  {3,14}\n", "Entry", "Symbol File", "Size",
83         "Previous Entry");
84 
85   unsigned Idx = 0;
86   for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
87     outsv("[{0,2}]  {1:X16}  {2:X16}  {3,8:D}  {4}\n", Idx++, Entry,
88           reinterpret_cast<const void *>(Entry->symfile_addr),
89           Entry->symfile_size, Entry->prev_entry);
90 }
91 
92 static LLIBuiltinFunctionGenerator *Generator = nullptr;
93 
dumpDebugObjects(void * Addr)94 static void dumpDebugObjects(void *Addr) {
95   jit_descriptor *Descriptor = reinterpret_cast<jit_descriptor *>(Addr);
96   for (auto *Entry = Descriptor->first_entry; Entry; Entry = Entry->next_entry)
97     Generator->appendDebugObject(Entry->symfile_addr, Entry->symfile_size);
98 }
99 
LLIBuiltinFunctionGenerator(std::vector<BuiltinFunctionKind> Enabled,orc::MangleAndInterner & Mangle)100 LLIBuiltinFunctionGenerator::LLIBuiltinFunctionGenerator(
101     std::vector<BuiltinFunctionKind> Enabled, orc::MangleAndInterner &Mangle)
102     : TestOut(nullptr) {
103   Generator = this;
104   for (BuiltinFunctionKind F : Enabled) {
105     switch (F) {
106     case BuiltinFunctionKind::DumpDebugDescriptor:
107       expose(Mangle("__dump_jit_debug_descriptor"), &dumpDebugDescriptor);
108       break;
109     case BuiltinFunctionKind::DumpDebugObjects:
110       expose(Mangle("__dump_jit_debug_objects"), &dumpDebugObjects);
111       TestOut = createToolOutput();
112       break;
113     }
114   }
115 }
116 
tryToGenerate(orc::LookupState & LS,orc::LookupKind K,orc::JITDylib & JD,orc::JITDylibLookupFlags JDLookupFlags,const orc::SymbolLookupSet & Symbols)117 Error LLIBuiltinFunctionGenerator::tryToGenerate(
118     orc::LookupState &LS, orc::LookupKind K, orc::JITDylib &JD,
119     orc::JITDylibLookupFlags JDLookupFlags,
120     const orc::SymbolLookupSet &Symbols) {
121   orc::SymbolMap NewSymbols;
122   for (const auto &NameFlags : Symbols) {
123     auto It = BuiltinFunctions.find(NameFlags.first);
124     if (It != BuiltinFunctions.end())
125       NewSymbols.insert(*It);
126   }
127 
128   if (NewSymbols.empty())
129     return Error::success();
130 
131   return JD.define(absoluteSymbols(std::move(NewSymbols)));
132 }
133 
134 // static
135 std::unique_ptr<ToolOutputFile>
createToolOutput()136 LLIBuiltinFunctionGenerator::createToolOutput() {
137   std::error_code EC;
138   auto TestOut = std::make_unique<ToolOutputFile>("-", EC, sys::fs::OF_None);
139   if (EC) {
140     errs() << "Error creating tool output file: " << EC.message() << '\n';
141     exit(1);
142   }
143   return TestOut;
144 }
145 
146 } // namespace llvm
147