1 | //===-- IRExecutionUnit.h ---------------------------------------*- C++ -*-===// |
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 | #ifndef LLDB_EXPRESSION_IREXECUTIONUNIT_H |
10 | #define LLDB_EXPRESSION_IREXECUTIONUNIT_H |
11 | |
12 | #include <atomic> |
13 | #include <memory> |
14 | #include <string> |
15 | #include <vector> |
16 | |
17 | #include "llvm/ExecutionEngine/SectionMemoryManager.h" |
18 | #include "llvm/IR/Module.h" |
19 | |
20 | #include "lldb/Expression/IRMemoryMap.h" |
21 | #include "lldb/Expression/ObjectFileJIT.h" |
22 | #include "lldb/Symbol/SymbolContext.h" |
23 | #include "lldb/Utility/DataBufferHeap.h" |
24 | #include "lldb/lldb-forward.h" |
25 | #include "lldb/lldb-private.h" |
26 | |
27 | namespace llvm { |
28 | |
29 | class Module; |
30 | class ExecutionEngine; |
31 | class ObjectCache; |
32 | |
33 | } // namespace llvm |
34 | |
35 | namespace lldb_private { |
36 | |
37 | class Status; |
38 | |
39 | /// \class IRExecutionUnit IRExecutionUnit.h |
40 | /// "lldb/Expression/IRExecutionUnit.h" Contains the IR and, optionally, JIT- |
41 | /// compiled code for a module. |
42 | /// |
43 | /// This class encapsulates the compiled version of an expression, in IR form |
44 | /// (for interpretation purposes) and in raw machine code form (for execution |
45 | /// in the target). |
46 | /// |
47 | /// This object wraps an IR module that comes from the expression parser, and |
48 | /// knows how to use the JIT to make it into executable code. It can then be |
49 | /// used as input to the IR interpreter, or the address of the executable code |
50 | /// can be passed to a thread plan to run in the target. |
51 | /// |
52 | /// This class creates a subclass of LLVM's SectionMemoryManager, because that |
53 | /// is how the JIT emits code. Because LLDB needs to move JIT-compiled code |
54 | /// into the target process, the IRExecutionUnit knows how to copy the emitted |
55 | /// code into the target process. |
56 | class IRExecutionUnit : public std::enable_shared_from_this<IRExecutionUnit>, |
57 | public IRMemoryMap, |
58 | public ObjectFileJITDelegate { |
59 | public: |
60 | /// Constructor |
61 | IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up, |
62 | std::unique_ptr<llvm::Module> &module_up, ConstString &name, |
63 | const lldb::TargetSP &target_sp, const SymbolContext &sym_ctx, |
64 | std::vector<std::string> &cpu_features); |
65 | |
66 | /// Destructor |
67 | ~IRExecutionUnit() override; |
68 | |
69 | ConstString GetFunctionName() { return m_name; } |
70 | |
71 | llvm::Module *GetModule() { return m_module; } |
72 | |
73 | llvm::Function *GetFunction() { |
74 | return ((m_module != nullptr) ? m_module->getFunction(Name: m_name.GetStringRef()) |
75 | : nullptr); |
76 | } |
77 | |
78 | void GetRunnableInfo(Status &error, lldb::addr_t &func_addr, |
79 | lldb::addr_t &func_end); |
80 | |
81 | /// Accessors for IRForTarget and other clients that may want binary data |
82 | /// placed on their behalf. The binary data is owned by the IRExecutionUnit |
83 | /// unless the client explicitly chooses to free it. |
84 | |
85 | lldb::addr_t WriteNow(const uint8_t *bytes, size_t size, Status &error); |
86 | |
87 | void FreeNow(lldb::addr_t allocation); |
88 | |
89 | /// ObjectFileJITDelegate overrides |
90 | lldb::ByteOrder GetByteOrder() const override; |
91 | |
92 | uint32_t GetAddressByteSize() const override; |
93 | |
94 | void PopulateSymtab(lldb_private::ObjectFile *obj_file, |
95 | lldb_private::Symtab &symtab) override; |
96 | |
97 | void PopulateSectionList(lldb_private::ObjectFile *obj_file, |
98 | lldb_private::SectionList §ion_list) override; |
99 | |
100 | ArchSpec GetArchitecture() override; |
101 | |
102 | lldb::ModuleSP GetJITModule(); |
103 | |
104 | lldb::addr_t FindSymbol(ConstString name, bool &missing_weak); |
105 | |
106 | void GetStaticInitializers(std::vector<lldb::addr_t> &static_initializers); |
107 | |
108 | /// \class JittedFunction IRExecutionUnit.h |
109 | /// "lldb/Expression/IRExecutionUnit.h" |
110 | /// Encapsulates a single function that has been generated by the JIT. |
111 | /// |
112 | /// Functions that have been generated by the JIT are first resident in the |
113 | /// local process, and then placed in the target process. JittedFunction |
114 | /// represents a function possibly resident in both. |
115 | struct JittedEntity { |
116 | ConstString m_name; ///< The function's name |
117 | lldb::addr_t m_local_addr; ///< The address of the function in LLDB's memory |
118 | lldb::addr_t |
119 | m_remote_addr; ///< The address of the function in the target's memory |
120 | |
121 | /// Constructor |
122 | /// |
123 | /// Initializes class variabes. |
124 | /// |
125 | /// \param[in] name |
126 | /// The name of the function. |
127 | /// |
128 | /// \param[in] local_addr |
129 | /// The address of the function in LLDB, or LLDB_INVALID_ADDRESS if |
130 | /// it is not present in LLDB's memory. |
131 | /// |
132 | /// \param[in] remote_addr |
133 | /// The address of the function in the target, or LLDB_INVALID_ADDRESS |
134 | /// if it is not present in the target's memory. |
135 | JittedEntity(const char *name, |
136 | lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, |
137 | lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) |
138 | : m_name(name), m_local_addr(local_addr), m_remote_addr(remote_addr) {} |
139 | }; |
140 | |
141 | struct JittedFunction : JittedEntity { |
142 | bool m_external; |
143 | JittedFunction(const char *name, bool external, |
144 | lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, |
145 | lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) |
146 | : JittedEntity(name, local_addr, remote_addr), m_external(external) {} |
147 | }; |
148 | |
149 | struct JittedGlobalVariable : JittedEntity { |
150 | JittedGlobalVariable(const char *name, |
151 | lldb::addr_t local_addr = LLDB_INVALID_ADDRESS, |
152 | lldb::addr_t remote_addr = LLDB_INVALID_ADDRESS) |
153 | : JittedEntity(name, local_addr, remote_addr) {} |
154 | }; |
155 | |
156 | const std::vector<JittedFunction> &GetJittedFunctions() { |
157 | return m_jitted_functions; |
158 | } |
159 | |
160 | const std::vector<JittedGlobalVariable> &GetJittedGlobalVariables() { |
161 | return m_jitted_global_variables; |
162 | } |
163 | |
164 | private: |
165 | /// Look up the object in m_address_map that contains a given address, find |
166 | /// where it was copied to, and return the remote address at the same offset |
167 | /// into the copied entity |
168 | /// |
169 | /// \param[in] local_address |
170 | /// The address in the debugger. |
171 | /// |
172 | /// \return |
173 | /// The address in the target process. |
174 | lldb::addr_t GetRemoteAddressForLocal(lldb::addr_t local_address); |
175 | |
176 | typedef std::pair<lldb::addr_t, uintptr_t> AddrRange; |
177 | |
178 | /// Look up the object in m_address_map that contains a given address, find |
179 | /// where it was copied to, and return its address range in the target |
180 | /// process |
181 | /// |
182 | /// \param[in] local_address |
183 | /// The address in the debugger. |
184 | /// |
185 | /// \return |
186 | /// The range of the containing object in the target process. |
187 | AddrRange GetRemoteRangeForLocal(lldb::addr_t local_address); |
188 | |
189 | /// Commit all allocations to the process and record where they were stored. |
190 | /// |
191 | /// \param[in] process_sp |
192 | /// The process to allocate memory in. |
193 | /// |
194 | /// \return |
195 | /// True <=> all allocations were performed successfully. |
196 | /// This method will attempt to free allocated memory if the |
197 | /// operation fails. |
198 | bool CommitAllocations(lldb::ProcessSP &process_sp); |
199 | |
200 | /// Report all committed allocations to the execution engine. |
201 | /// |
202 | /// \param[in] engine |
203 | /// The execution engine to notify. |
204 | void ReportAllocations(llvm::ExecutionEngine &engine); |
205 | |
206 | /// Write the contents of all allocations to the process. |
207 | /// |
208 | /// \param[in] process_sp |
209 | /// The process containing the allocations. |
210 | /// |
211 | /// \return |
212 | /// True <=> all allocations were performed successfully. |
213 | bool WriteData(lldb::ProcessSP &process_sp); |
214 | |
215 | Status DisassembleFunction(Stream &stream, lldb::ProcessSP &process_sp); |
216 | |
217 | void CollectCandidateCNames(std::vector<ConstString> &C_names, |
218 | ConstString name); |
219 | |
220 | void CollectCandidateCPlusPlusNames(std::vector<ConstString> &CPP_names, |
221 | const std::vector<ConstString> &C_names, |
222 | const SymbolContext &sc); |
223 | |
224 | lldb::addr_t FindInSymbols(const std::vector<ConstString> &names, |
225 | const lldb_private::SymbolContext &sc, |
226 | bool &symbol_was_missing_weak); |
227 | |
228 | lldb::addr_t FindInRuntimes(const std::vector<ConstString> &names, |
229 | const lldb_private::SymbolContext &sc); |
230 | |
231 | lldb::addr_t FindInUserDefinedSymbols(const std::vector<ConstString> &names, |
232 | const lldb_private::SymbolContext &sc); |
233 | |
234 | void ReportSymbolLookupError(ConstString name); |
235 | |
236 | class MemoryManager : public llvm::SectionMemoryManager { |
237 | public: |
238 | MemoryManager(IRExecutionUnit &parent); |
239 | |
240 | ~MemoryManager() override; |
241 | |
242 | /// Allocate space for executable code, and add it to the m_spaceBlocks |
243 | /// map |
244 | /// |
245 | /// \param[in] Size |
246 | /// The size of the area. |
247 | /// |
248 | /// \param[in] Alignment |
249 | /// The required alignment of the area. |
250 | /// |
251 | /// \param[in] SectionID |
252 | /// A unique identifier for the section. |
253 | /// |
254 | /// \return |
255 | /// Allocated space. |
256 | uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, |
257 | unsigned SectionID, |
258 | llvm::StringRef SectionName) override; |
259 | |
260 | /// Allocate space for data, and add it to the m_spaceBlocks map |
261 | /// |
262 | /// \param[in] Size |
263 | /// The size of the area. |
264 | /// |
265 | /// \param[in] Alignment |
266 | /// The required alignment of the area. |
267 | /// |
268 | /// \param[in] SectionID |
269 | /// A unique identifier for the section. |
270 | /// |
271 | /// \param[in] IsReadOnly |
272 | /// Flag indicating the section is read-only. |
273 | /// |
274 | /// \return |
275 | /// Allocated space. |
276 | uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, |
277 | unsigned SectionID, |
278 | llvm::StringRef SectionName, |
279 | bool IsReadOnly) override; |
280 | |
281 | /// Called when object loading is complete and section page permissions |
282 | /// can be applied. Currently unimplemented for LLDB. |
283 | /// |
284 | /// \param[out] ErrMsg |
285 | /// The error that prevented the page protection from succeeding. |
286 | /// |
287 | /// \return |
288 | /// True in case of failure, false in case of success. |
289 | bool finalizeMemory(std::string *ErrMsg) override { |
290 | // TODO: Ensure that the instruction cache is flushed because |
291 | // relocations are updated by dy-load. See: |
292 | // sys::Memory::InvalidateInstructionCache |
293 | // llvm::SectionMemoryManager |
294 | return false; |
295 | } |
296 | |
297 | // Ignore any EHFrame registration. |
298 | void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, |
299 | size_t Size) override {} |
300 | void deregisterEHFrames() override {} |
301 | |
302 | uint64_t getSymbolAddress(const std::string &Name) override; |
303 | |
304 | // Find the address of the symbol Name. If Name is a missing weak symbol |
305 | // then missing_weak will be true. |
306 | uint64_t GetSymbolAddressAndPresence(const std::string &Name, |
307 | bool &missing_weak); |
308 | |
309 | llvm::JITSymbol findSymbol(const std::string &Name) override; |
310 | |
311 | void *getPointerToNamedFunction(const std::string &Name, |
312 | bool AbortOnFailure = true) override; |
313 | |
314 | private: |
315 | std::unique_ptr<SectionMemoryManager> m_default_mm_up; ///< The memory |
316 | /// allocator to use |
317 | /// in actually |
318 | /// creating space. |
319 | /// All calls are |
320 | /// passed through to |
321 | /// it. |
322 | IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. |
323 | }; |
324 | |
325 | static const unsigned eSectionIDInvalid = (unsigned)-1; |
326 | |
327 | enum class AllocationKind { Stub, Code, Data, Global, Bytes }; |
328 | |
329 | static lldb::SectionType |
330 | GetSectionTypeFromSectionName(const llvm::StringRef &name, |
331 | AllocationKind alloc_kind); |
332 | |
333 | /// Encapsulates a single allocation request made by the JIT. |
334 | /// |
335 | /// Allocations made by the JIT are first queued up and then applied in bulk |
336 | /// to the underlying process. |
337 | struct AllocationRecord { |
338 | std::string m_name; |
339 | lldb::addr_t m_process_address; |
340 | uintptr_t m_host_address; |
341 | uint32_t m_permissions; |
342 | lldb::SectionType m_sect_type; |
343 | size_t m_size; |
344 | unsigned m_alignment; |
345 | unsigned m_section_id; |
346 | |
347 | AllocationRecord(uintptr_t host_address, uint32_t permissions, |
348 | lldb::SectionType sect_type, size_t size, |
349 | unsigned alignment, unsigned section_id, const char *name) |
350 | : m_process_address(LLDB_INVALID_ADDRESS), m_host_address(host_address), |
351 | m_permissions(permissions), m_sect_type(sect_type), m_size(size), |
352 | m_alignment(alignment), m_section_id(section_id) { |
353 | if (name && name[0]) |
354 | m_name = name; |
355 | } |
356 | |
357 | void dump(Log *log); |
358 | }; |
359 | |
360 | bool CommitOneAllocation(lldb::ProcessSP &process_sp, Status &error, |
361 | AllocationRecord &record); |
362 | |
363 | typedef std::vector<AllocationRecord> RecordVector; |
364 | RecordVector m_records; |
365 | |
366 | std::unique_ptr<llvm::LLVMContext> m_context_up; |
367 | std::unique_ptr<llvm::ExecutionEngine> m_execution_engine_up; |
368 | std::unique_ptr<llvm::ObjectCache> m_object_cache_up; |
369 | std::unique_ptr<llvm::Module> |
370 | m_module_up; ///< Holder for the module until it's been handed off |
371 | llvm::Module *m_module; ///< Owned by the execution engine |
372 | std::vector<std::string> m_cpu_features; |
373 | std::vector<JittedFunction> m_jitted_functions; ///< A vector of all functions |
374 | ///that have been JITted into |
375 | ///machine code |
376 | std::vector<JittedGlobalVariable> m_jitted_global_variables; ///< A vector of |
377 | ///all functions |
378 | ///that have been |
379 | ///JITted into |
380 | ///machine code |
381 | const ConstString m_name; |
382 | SymbolContext m_sym_ctx; ///< Used for symbol lookups |
383 | std::vector<ConstString> m_failed_lookups; |
384 | |
385 | std::atomic<bool> m_did_jit; |
386 | |
387 | lldb::addr_t m_function_load_addr; |
388 | lldb::addr_t m_function_end_load_addr; |
389 | |
390 | bool m_strip_underscore = true; ///< True for platforms where global symbols |
391 | /// have a _ prefix |
392 | bool m_reported_allocations; ///< True after allocations have been reported. |
393 | ///It is possible that |
394 | ///< sections will be allocated when this is true, in which case they weren't |
395 | ///< depended on by any function. (Top-level code defining a variable, but |
396 | ///< defining no functions using that variable, would do this.) If this |
397 | ///< is true, any allocations need to be committed immediately -- no |
398 | ///< opportunity for relocation. |
399 | }; |
400 | |
401 | } // namespace lldb_private |
402 | |
403 | #endif // LLDB_EXPRESSION_IREXECUTIONUNIT_H |
404 | |