/Users/buildslave/jenkins/workspace/coverage/llvm-project/lldb/include/lldb/Expression/IRExecutionUnit.h
Line | Count | Source (jump to first uncovered line) |
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 | 2.96k | ConstString GetFunctionName() { return m_name; } |
70 | | |
71 | 23.5k | llvm::Module *GetModule() { return m_module; } |
72 | | |
73 | 12.6k | llvm::Function *GetFunction() { |
74 | 12.6k | return ((m_module != nullptr) ? m_module->getFunction(m_name.GetStringRef()) |
75 | 12.6k | : nullptr0 ); |
76 | 12.6k | } |
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 | 9.77k | : 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 | 8.80k | : 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 | 969 | : JittedEntity(name, local_addr, remote_addr) {} |
154 | | }; |
155 | | |
156 | 7.22k | const std::vector<JittedFunction> &GetJittedFunctions() { |
157 | 7.22k | return m_jitted_functions; |
158 | 7.22k | } |
159 | | |
160 | 329 | const std::vector<JittedGlobalVariable> &GetJittedGlobalVariables() { |
161 | 329 | return m_jitted_global_variables; |
162 | 329 | } |
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 | 6.90k | 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 | 6.90k | return false; |
295 | 6.90k | } |
296 | | |
297 | | // Ignore any EHFrame registration. |
298 | | void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, |
299 | 0 | size_t Size) override {} |
300 | 5.90k | 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 | 62.0k | : m_process_address(LLDB_INVALID_ADDRESS), m_host_address(host_address), |
351 | 62.0k | m_permissions(permissions), m_sect_type(sect_type), m_size(size), |
352 | 62.0k | m_alignment(alignment), m_section_id(section_id) { |
353 | 62.0k | if (name && name[0]) |
354 | 62.0k | m_name = name; |
355 | 62.0k | } |
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 |