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