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 liblldb_IRExecutionUnit_h_ 10 #define liblldb_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/Symbol/ObjectFile.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(m_name.AsCString()) 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 /// Look up the object in m_address_map that contains a given address, find 177 /// where it was copied to, and return its address range in the target 178 /// process 179 /// 180 /// \param[in] local_address 181 /// The address in the debugger. 182 /// 183 /// \return 184 /// The range of the containing object in the target process. 185 typedef std::pair<lldb::addr_t, uintptr_t> AddrRange; 186 AddrRange GetRemoteRangeForLocal(lldb::addr_t local_address); 187 188 /// Commit all allocations to the process and record where they were stored. 189 /// 190 /// \param[in] process 191 /// The process to allocate memory in. 192 /// 193 /// \return 194 /// True <=> all allocations were performed successfully. 195 /// This method will attempt to free allocated memory if the 196 /// operation fails. 197 bool CommitAllocations(lldb::ProcessSP &process_sp); 198 199 /// Report all committed allocations to the execution engine. 200 /// 201 /// \param[in] engine 202 /// The execution engine to notify. 203 void ReportAllocations(llvm::ExecutionEngine &engine); 204 205 /// Write the contents of all allocations to the process. 206 /// 207 /// \param[in] local_address 208 /// The process containing the allocations. 209 /// 210 /// \return 211 /// True <=> all allocations were performed successfully. 212 bool WriteData(lldb::ProcessSP &process_sp); 213 214 Status DisassembleFunction(Stream &stream, lldb::ProcessSP &process_sp); 215 216 struct SearchSpec; 217 218 void CollectCandidateCNames(std::vector<SearchSpec> &C_specs, 219 ConstString name); 220 221 void CollectCandidateCPlusPlusNames(std::vector<SearchSpec> &CPP_specs, 222 const std::vector<SearchSpec> &C_specs, 223 const SymbolContext &sc); 224 225 void CollectFallbackNames(std::vector<SearchSpec> &fallback_specs, 226 const std::vector<SearchSpec> &C_specs); 227 228 lldb::addr_t FindInSymbols(const std::vector<SearchSpec> &specs, 229 const lldb_private::SymbolContext &sc, 230 bool &symbol_was_missing_weak); 231 232 lldb::addr_t FindInRuntimes(const std::vector<SearchSpec> &specs, 233 const lldb_private::SymbolContext &sc); 234 235 lldb::addr_t FindInUserDefinedSymbols(const std::vector<SearchSpec> &specs, 236 const lldb_private::SymbolContext &sc); 237 238 void ReportSymbolLookupError(ConstString name); 239 240 class MemoryManager : public llvm::SectionMemoryManager { 241 public: 242 MemoryManager(IRExecutionUnit &parent); 243 244 ~MemoryManager() override; 245 246 /// Allocate space for executable code, and add it to the m_spaceBlocks 247 /// map 248 /// 249 /// \param[in] Size 250 /// The size of the area. 251 /// 252 /// \param[in] Alignment 253 /// The required alignment of the area. 254 /// 255 /// \param[in] SectionID 256 /// A unique identifier for the section. 257 /// 258 /// \return 259 /// Allocated space. 260 uint8_t *allocateCodeSection(uintptr_t Size, unsigned Alignment, 261 unsigned SectionID, 262 llvm::StringRef SectionName) override; 263 264 /// Allocate space for data, and add it to the m_spaceBlocks map 265 /// 266 /// \param[in] Size 267 /// The size of the area. 268 /// 269 /// \param[in] Alignment 270 /// The required alignment of the area. 271 /// 272 /// \param[in] SectionID 273 /// A unique identifier for the section. 274 /// 275 /// \param[in] IsReadOnly 276 /// Flag indicating the section is read-only. 277 /// 278 /// \return 279 /// Allocated space. 280 uint8_t *allocateDataSection(uintptr_t Size, unsigned Alignment, 281 unsigned SectionID, 282 llvm::StringRef SectionName, 283 bool IsReadOnly) override; 284 285 /// Called when object loading is complete and section page permissions 286 /// can be applied. Currently unimplemented for LLDB. 287 /// 288 /// \param[out] ErrMsg 289 /// The error that prevented the page protection from succeeding. 290 /// 291 /// \return 292 /// True in case of failure, false in case of success. 293 bool finalizeMemory(std::string *ErrMsg) override { 294 // TODO: Ensure that the instruction cache is flushed because 295 // relocations are updated by dy-load. See: 296 // sys::Memory::InvalidateInstructionCache 297 // llvm::SectionMemoryManager 298 return false; 299 } 300 301 void registerEHFrames(uint8_t *Addr, uint64_t LoadAddr, 302 size_t Size) override {} 303 304 uint64_t getSymbolAddress(const std::string &Name) override; 305 306 // Find the address of the symbol Name. If Name is a missing weak symbol 307 // then missing_weak will be true. 308 uint64_t GetSymbolAddressAndPresence(const std::string &Name, 309 bool &missing_weak); 310 311 llvm::JITSymbol findSymbol(const std::string &Name) override; 312 313 void *getPointerToNamedFunction(const std::string &Name, 314 bool AbortOnFailure = true) override; 315 316 private: 317 std::unique_ptr<SectionMemoryManager> m_default_mm_up; ///< The memory 318 /// allocator to use 319 /// in actually 320 /// creating space. 321 /// All calls are 322 /// passed through to 323 /// it. 324 IRExecutionUnit &m_parent; ///< The execution unit this is a proxy for. 325 }; 326 327 static const unsigned eSectionIDInvalid = (unsigned)-1; 328 329 /// \class AllocationRecord IRExecutionUnit.h 330 /// "lldb/Expression/IRExecutionUnit.h" Encapsulates a single allocation 331 /// request made by the JIT. 332 /// 333 /// Allocations made by the JIT are first queued up and then applied in bulk 334 /// to the underlying process. 335 enum class AllocationKind { Stub, Code, Data, Global, Bytes }; 336 337 static lldb::SectionType 338 GetSectionTypeFromSectionName(const llvm::StringRef &name, 339 AllocationKind alloc_kind); 340 341 struct AllocationRecord { 342 std::string m_name; 343 lldb::addr_t m_process_address; 344 uintptr_t m_host_address; 345 uint32_t m_permissions; 346 lldb::SectionType m_sect_type; 347 size_t m_size; 348 unsigned m_alignment; 349 unsigned m_section_id; 350 351 AllocationRecord(uintptr_t host_address, uint32_t permissions, 352 lldb::SectionType sect_type, size_t size, 353 unsigned alignment, unsigned section_id, const char *name) 354 : m_name(), m_process_address(LLDB_INVALID_ADDRESS), 355 m_host_address(host_address), m_permissions(permissions), 356 m_sect_type(sect_type), m_size(size), m_alignment(alignment), 357 m_section_id(section_id) { 358 if (name && name[0]) 359 m_name = name; 360 } 361 362 void dump(Log *log); 363 }; 364 365 bool CommitOneAllocation(lldb::ProcessSP &process_sp, Status &error, 366 AllocationRecord &record); 367 368 typedef std::vector<AllocationRecord> RecordVector; 369 RecordVector m_records; 370 371 std::unique_ptr<llvm::LLVMContext> m_context_up; 372 std::unique_ptr<llvm::ExecutionEngine> m_execution_engine_up; 373 std::unique_ptr<llvm::ObjectCache> m_object_cache_up; 374 std::unique_ptr<llvm::Module> 375 m_module_up; ///< Holder for the module until it's been handed off 376 llvm::Module *m_module; ///< Owned by the execution engine 377 std::vector<std::string> m_cpu_features; 378 std::vector<JittedFunction> m_jitted_functions; ///< A vector of all functions 379 ///that have been JITted into 380 ///machine code 381 std::vector<JittedGlobalVariable> m_jitted_global_variables; ///< A vector of 382 ///all functions 383 ///that have been 384 ///JITted into 385 ///machine code 386 const ConstString m_name; 387 SymbolContext m_sym_ctx; ///< Used for symbol lookups 388 std::vector<ConstString> m_failed_lookups; 389 390 std::atomic<bool> m_did_jit; 391 392 lldb::addr_t m_function_load_addr; 393 lldb::addr_t m_function_end_load_addr; 394 395 bool m_strip_underscore = true; ///< True for platforms where global symbols 396 /// have a _ prefix 397 bool m_reported_allocations; ///< True after allocations have been reported. 398 ///It is possible that 399 ///< sections will be allocated when this is true, in which case they weren't 400 ///< depended on by any function. (Top-level code defining a variable, but 401 ///< defining no functions using that variable, would do this.) If this 402 ///< is true, any allocations need to be committed immediately -- no 403 ///< opportunity for relocation. 404 }; 405 406 } // namespace lldb_private 407 408 #endif // liblldb_IRExecutionUnit_h_ 409