15ffd83dbSDimitry Andric //===-- IRExecutionUnit.cpp -----------------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ExecutionEngine.h"
100b57cec5SDimitry Andric #include "llvm/ExecutionEngine/ObjectCache.h"
110b57cec5SDimitry Andric #include "llvm/IR/Constants.h"
12fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticHandler.h"
13fe6060f1SDimitry Andric #include "llvm/IR/DiagnosticInfo.h"
140b57cec5SDimitry Andric #include "llvm/IR/LLVMContext.h"
150b57cec5SDimitry Andric #include "llvm/IR/Module.h"
160b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
170b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
180b57cec5SDimitry Andric 
190b57cec5SDimitry Andric #include "lldb/Core/Debugger.h"
200b57cec5SDimitry Andric #include "lldb/Core/Disassembler.h"
210b57cec5SDimitry Andric #include "lldb/Core/Module.h"
220b57cec5SDimitry Andric #include "lldb/Core/Section.h"
230b57cec5SDimitry Andric #include "lldb/Expression/IRExecutionUnit.h"
2406c3fb27SDimitry Andric #include "lldb/Expression/ObjectFileJIT.h"
2581ad6265SDimitry Andric #include "lldb/Host/HostInfo.h"
260b57cec5SDimitry Andric #include "lldb/Symbol/CompileUnit.h"
270b57cec5SDimitry Andric #include "lldb/Symbol/SymbolContext.h"
280b57cec5SDimitry Andric #include "lldb/Symbol/SymbolFile.h"
290b57cec5SDimitry Andric #include "lldb/Symbol/SymbolVendor.h"
300b57cec5SDimitry Andric #include "lldb/Target/ExecutionContext.h"
31349cc55cSDimitry Andric #include "lldb/Target/Language.h"
320b57cec5SDimitry Andric #include "lldb/Target/LanguageRuntime.h"
330b57cec5SDimitry Andric #include "lldb/Target/Target.h"
340b57cec5SDimitry Andric #include "lldb/Utility/DataBufferHeap.h"
350b57cec5SDimitry Andric #include "lldb/Utility/DataExtractor.h"
360b57cec5SDimitry Andric #include "lldb/Utility/LLDBAssert.h"
3781ad6265SDimitry Andric #include "lldb/Utility/LLDBLog.h"
380b57cec5SDimitry Andric #include "lldb/Utility/Log.h"
390b57cec5SDimitry Andric 
40bdd1243dSDimitry Andric #include <optional>
410b57cec5SDimitry Andric 
420b57cec5SDimitry Andric using namespace lldb_private;
430b57cec5SDimitry Andric 
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)440b57cec5SDimitry Andric IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up,
450b57cec5SDimitry Andric                                  std::unique_ptr<llvm::Module> &module_up,
460b57cec5SDimitry Andric                                  ConstString &name,
470b57cec5SDimitry Andric                                  const lldb::TargetSP &target_sp,
480b57cec5SDimitry Andric                                  const SymbolContext &sym_ctx,
490b57cec5SDimitry Andric                                  std::vector<std::string> &cpu_features)
500b57cec5SDimitry Andric     : IRMemoryMap(target_sp), m_context_up(context_up.release()),
510b57cec5SDimitry Andric       m_module_up(module_up.release()), m_module(m_module_up.get()),
520b57cec5SDimitry Andric       m_cpu_features(cpu_features), m_name(name), m_sym_ctx(sym_ctx),
530b57cec5SDimitry Andric       m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS),
540b57cec5SDimitry Andric       m_function_end_load_addr(LLDB_INVALID_ADDRESS),
550b57cec5SDimitry Andric       m_reported_allocations(false) {}
560b57cec5SDimitry Andric 
WriteNow(const uint8_t * bytes,size_t size,Status & error)570b57cec5SDimitry Andric lldb::addr_t IRExecutionUnit::WriteNow(const uint8_t *bytes, size_t size,
580b57cec5SDimitry Andric                                        Status &error) {
590b57cec5SDimitry Andric   const bool zero_memory = false;
600b57cec5SDimitry Andric   lldb::addr_t allocation_process_addr =
610b57cec5SDimitry Andric       Malloc(size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable,
620b57cec5SDimitry Andric              eAllocationPolicyMirror, zero_memory, error);
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric   if (!error.Success())
650b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
660b57cec5SDimitry Andric 
670b57cec5SDimitry Andric   WriteMemory(allocation_process_addr, bytes, size, error);
680b57cec5SDimitry Andric 
690b57cec5SDimitry Andric   if (!error.Success()) {
700b57cec5SDimitry Andric     Status err;
710b57cec5SDimitry Andric     Free(allocation_process_addr, err);
720b57cec5SDimitry Andric 
730b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
740b57cec5SDimitry Andric   }
750b57cec5SDimitry Andric 
7681ad6265SDimitry Andric   if (Log *log = GetLog(LLDBLog::Expressions)) {
770b57cec5SDimitry Andric     DataBufferHeap my_buffer(size, 0);
780b57cec5SDimitry Andric     Status err;
790b57cec5SDimitry Andric     ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
800b57cec5SDimitry Andric 
810b57cec5SDimitry Andric     if (err.Success()) {
820b57cec5SDimitry Andric       DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(),
830b57cec5SDimitry Andric                                  lldb::eByteOrderBig, 8);
840b57cec5SDimitry Andric       my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(),
850b57cec5SDimitry Andric                             allocation_process_addr, 16,
860b57cec5SDimitry Andric                             DataExtractor::TypeUInt8);
870b57cec5SDimitry Andric     }
880b57cec5SDimitry Andric   }
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric   return allocation_process_addr;
910b57cec5SDimitry Andric }
920b57cec5SDimitry Andric 
FreeNow(lldb::addr_t allocation)930b57cec5SDimitry Andric void IRExecutionUnit::FreeNow(lldb::addr_t allocation) {
940b57cec5SDimitry Andric   if (allocation == LLDB_INVALID_ADDRESS)
950b57cec5SDimitry Andric     return;
960b57cec5SDimitry Andric 
970b57cec5SDimitry Andric   Status err;
980b57cec5SDimitry Andric 
990b57cec5SDimitry Andric   Free(allocation, err);
1000b57cec5SDimitry Andric }
1010b57cec5SDimitry Andric 
DisassembleFunction(Stream & stream,lldb::ProcessSP & process_wp)1020b57cec5SDimitry Andric Status IRExecutionUnit::DisassembleFunction(Stream &stream,
1030b57cec5SDimitry Andric                                             lldb::ProcessSP &process_wp) {
10481ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
1050b57cec5SDimitry Andric 
1060b57cec5SDimitry Andric   ExecutionContext exe_ctx(process_wp);
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   Status ret;
1090b57cec5SDimitry Andric 
1100b57cec5SDimitry Andric   ret.Clear();
1110b57cec5SDimitry Andric 
1120b57cec5SDimitry Andric   lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
1130b57cec5SDimitry Andric   lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
1140b57cec5SDimitry Andric 
1150b57cec5SDimitry Andric   for (JittedFunction &function : m_jitted_functions) {
1160b57cec5SDimitry Andric     if (function.m_name == m_name) {
1170b57cec5SDimitry Andric       func_local_addr = function.m_local_addr;
1180b57cec5SDimitry Andric       func_remote_addr = function.m_remote_addr;
1190b57cec5SDimitry Andric     }
1200b57cec5SDimitry Andric   }
1210b57cec5SDimitry Andric 
1220b57cec5SDimitry Andric   if (func_local_addr == LLDB_INVALID_ADDRESS) {
1230b57cec5SDimitry Andric     ret.SetErrorToGenericError();
1240b57cec5SDimitry Andric     ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly",
1250b57cec5SDimitry Andric                                  m_name.AsCString());
1260b57cec5SDimitry Andric     return ret;
1270b57cec5SDimitry Andric   }
1280b57cec5SDimitry Andric 
1299dba64beSDimitry Andric   LLDB_LOGF(log,
1309dba64beSDimitry Andric             "Found function, has local address 0x%" PRIx64
1310b57cec5SDimitry Andric             " and remote address 0x%" PRIx64,
1320b57cec5SDimitry Andric             (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
1330b57cec5SDimitry Andric 
1340b57cec5SDimitry Andric   std::pair<lldb::addr_t, lldb::addr_t> func_range;
1350b57cec5SDimitry Andric 
1360b57cec5SDimitry Andric   func_range = GetRemoteRangeForLocal(func_local_addr);
1370b57cec5SDimitry Andric 
1380b57cec5SDimitry Andric   if (func_range.first == 0 && func_range.second == 0) {
1390b57cec5SDimitry Andric     ret.SetErrorToGenericError();
1400b57cec5SDimitry Andric     ret.SetErrorStringWithFormat("Couldn't find code range for function %s",
1410b57cec5SDimitry Andric                                  m_name.AsCString());
1420b57cec5SDimitry Andric     return ret;
1430b57cec5SDimitry Andric   }
1440b57cec5SDimitry Andric 
1459dba64beSDimitry Andric   LLDB_LOGF(log, "Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]",
1460b57cec5SDimitry Andric             func_range.first, func_range.second);
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
1490b57cec5SDimitry Andric   if (!target) {
1500b57cec5SDimitry Andric     ret.SetErrorToGenericError();
1510b57cec5SDimitry Andric     ret.SetErrorString("Couldn't find the target");
1520b57cec5SDimitry Andric     return ret;
1530b57cec5SDimitry Andric   }
1540b57cec5SDimitry Andric 
15581ad6265SDimitry Andric   lldb::WritableDataBufferSP buffer_sp(
15681ad6265SDimitry Andric       new DataBufferHeap(func_range.second, 0));
1570b57cec5SDimitry Andric 
1580b57cec5SDimitry Andric   Process *process = exe_ctx.GetProcessPtr();
1590b57cec5SDimitry Andric   Status err;
1600b57cec5SDimitry Andric   process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(),
1610b57cec5SDimitry Andric                       buffer_sp->GetByteSize(), err);
1620b57cec5SDimitry Andric 
1630b57cec5SDimitry Andric   if (!err.Success()) {
1640b57cec5SDimitry Andric     ret.SetErrorToGenericError();
1650b57cec5SDimitry Andric     ret.SetErrorStringWithFormat("Couldn't read from process: %s",
1660b57cec5SDimitry Andric                                  err.AsCString("unknown error"));
1670b57cec5SDimitry Andric     return ret;
1680b57cec5SDimitry Andric   }
1690b57cec5SDimitry Andric 
1700b57cec5SDimitry Andric   ArchSpec arch(target->GetArchitecture());
1710b57cec5SDimitry Andric 
1720b57cec5SDimitry Andric   const char *plugin_name = nullptr;
1730b57cec5SDimitry Andric   const char *flavor_string = nullptr;
1740b57cec5SDimitry Andric   lldb::DisassemblerSP disassembler_sp =
1750b57cec5SDimitry Andric       Disassembler::FindPlugin(arch, flavor_string, plugin_name);
1760b57cec5SDimitry Andric 
1770b57cec5SDimitry Andric   if (!disassembler_sp) {
1780b57cec5SDimitry Andric     ret.SetErrorToGenericError();
1790b57cec5SDimitry Andric     ret.SetErrorStringWithFormat(
1800b57cec5SDimitry Andric         "Unable to find disassembler plug-in for %s architecture.",
1810b57cec5SDimitry Andric         arch.GetArchitectureName());
1820b57cec5SDimitry Andric     return ret;
1830b57cec5SDimitry Andric   }
1840b57cec5SDimitry Andric 
1850b57cec5SDimitry Andric   if (!process) {
1860b57cec5SDimitry Andric     ret.SetErrorToGenericError();
1870b57cec5SDimitry Andric     ret.SetErrorString("Couldn't find the process");
1880b57cec5SDimitry Andric     return ret;
1890b57cec5SDimitry Andric   }
1900b57cec5SDimitry Andric 
1910b57cec5SDimitry Andric   DataExtractor extractor(buffer_sp, process->GetByteOrder(),
1920b57cec5SDimitry Andric                           target->GetArchitecture().GetAddressByteSize());
1930b57cec5SDimitry Andric 
1940b57cec5SDimitry Andric   if (log) {
1959dba64beSDimitry Andric     LLDB_LOGF(log, "Function data has contents:");
1960b57cec5SDimitry Andric     extractor.PutToLog(log, 0, extractor.GetByteSize(), func_remote_addr, 16,
1970b57cec5SDimitry Andric                        DataExtractor::TypeUInt8);
1980b57cec5SDimitry Andric   }
1990b57cec5SDimitry Andric 
2000b57cec5SDimitry Andric   disassembler_sp->DecodeInstructions(Address(func_remote_addr), extractor, 0,
2010b57cec5SDimitry Andric                                       UINT32_MAX, false, false);
2020b57cec5SDimitry Andric 
2030b57cec5SDimitry Andric   InstructionList &instruction_list = disassembler_sp->GetInstructionList();
204753f127fSDimitry Andric   instruction_list.Dump(&stream, true, true, /*show_control_flow_kind=*/true,
205753f127fSDimitry Andric                         &exe_ctx);
206753f127fSDimitry Andric 
2070b57cec5SDimitry Andric   return ret;
2080b57cec5SDimitry Andric }
2090b57cec5SDimitry Andric 
210fe6060f1SDimitry Andric namespace {
211fe6060f1SDimitry Andric struct IRExecDiagnosticHandler : public llvm::DiagnosticHandler {
212fe6060f1SDimitry Andric   Status *err;
IRExecDiagnosticHandler__anon3a89a5830111::IRExecDiagnosticHandler213fe6060f1SDimitry Andric   IRExecDiagnosticHandler(Status *err) : err(err) {}
handleDiagnostics__anon3a89a5830111::IRExecDiagnosticHandler214fe6060f1SDimitry Andric   bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override {
215fe6060f1SDimitry Andric     if (DI.getKind() == llvm::DK_SrcMgr) {
216fe6060f1SDimitry Andric       const auto &DISM = llvm::cast<llvm::DiagnosticInfoSrcMgr>(DI);
2170b57cec5SDimitry Andric       if (err && err->Success()) {
2180b57cec5SDimitry Andric         err->SetErrorToGenericError();
219fe6060f1SDimitry Andric         err->SetErrorStringWithFormat(
220fe6060f1SDimitry Andric             "Inline assembly error: %s",
221fe6060f1SDimitry Andric             DISM.getSMDiag().getMessage().str().c_str());
2220b57cec5SDimitry Andric       }
223fe6060f1SDimitry Andric       return true;
2240b57cec5SDimitry Andric     }
2250b57cec5SDimitry Andric 
226fe6060f1SDimitry Andric     return false;
227fe6060f1SDimitry Andric   }
228fe6060f1SDimitry Andric };
229fe6060f1SDimitry Andric } // namespace
230fe6060f1SDimitry Andric 
ReportSymbolLookupError(ConstString name)2310b57cec5SDimitry Andric void IRExecutionUnit::ReportSymbolLookupError(ConstString name) {
2320b57cec5SDimitry Andric   m_failed_lookups.push_back(name);
2330b57cec5SDimitry Andric }
2340b57cec5SDimitry Andric 
GetRunnableInfo(Status & error,lldb::addr_t & func_addr,lldb::addr_t & func_end)2350b57cec5SDimitry Andric void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
2360b57cec5SDimitry Andric                                       lldb::addr_t &func_end) {
2370b57cec5SDimitry Andric   lldb::ProcessSP process_sp(GetProcessWP().lock());
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric   static std::recursive_mutex s_runnable_info_mutex;
2400b57cec5SDimitry Andric 
2410b57cec5SDimitry Andric   func_addr = LLDB_INVALID_ADDRESS;
2420b57cec5SDimitry Andric   func_end = LLDB_INVALID_ADDRESS;
2430b57cec5SDimitry Andric 
2440b57cec5SDimitry Andric   if (!process_sp) {
2450b57cec5SDimitry Andric     error.SetErrorToGenericError();
2460b57cec5SDimitry Andric     error.SetErrorString("Couldn't write the JIT compiled code into the "
2470b57cec5SDimitry Andric                          "process because the process is invalid");
2480b57cec5SDimitry Andric     return;
2490b57cec5SDimitry Andric   }
2500b57cec5SDimitry Andric 
2510b57cec5SDimitry Andric   if (m_did_jit) {
2520b57cec5SDimitry Andric     func_addr = m_function_load_addr;
2530b57cec5SDimitry Andric     func_end = m_function_end_load_addr;
2540b57cec5SDimitry Andric 
2550b57cec5SDimitry Andric     return;
2560b57cec5SDimitry Andric   };
2570b57cec5SDimitry Andric 
2580b57cec5SDimitry Andric   std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex);
2590b57cec5SDimitry Andric 
2600b57cec5SDimitry Andric   m_did_jit = true;
2610b57cec5SDimitry Andric 
26281ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
2630b57cec5SDimitry Andric 
2640b57cec5SDimitry Andric   std::string error_string;
2650b57cec5SDimitry Andric 
2660b57cec5SDimitry Andric   if (log) {
2670b57cec5SDimitry Andric     std::string s;
2680b57cec5SDimitry Andric     llvm::raw_string_ostream oss(s);
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric     m_module->print(oss, nullptr);
2710b57cec5SDimitry Andric 
2720b57cec5SDimitry Andric     oss.flush();
2730b57cec5SDimitry Andric 
2749dba64beSDimitry Andric     LLDB_LOGF(log, "Module being sent to JIT: \n%s", s.c_str());
2750b57cec5SDimitry Andric   }
2760b57cec5SDimitry Andric 
277fe6060f1SDimitry Andric   m_module_up->getContext().setDiagnosticHandler(
278fe6060f1SDimitry Andric       std::make_unique<IRExecDiagnosticHandler>(&error));
2790b57cec5SDimitry Andric 
2800b57cec5SDimitry Andric   llvm::EngineBuilder builder(std::move(m_module_up));
2810b57cec5SDimitry Andric   llvm::Triple triple(m_module->getTargetTriple());
2820b57cec5SDimitry Andric 
2830b57cec5SDimitry Andric   builder.setEngineKind(llvm::EngineKind::JIT)
2840b57cec5SDimitry Andric       .setErrorStr(&error_string)
2855ffd83dbSDimitry Andric       .setRelocationModel(triple.isOSBinFormatMachO() ? llvm::Reloc::PIC_
2860b57cec5SDimitry Andric                                                       : llvm::Reloc::Static)
2875ffd83dbSDimitry Andric       .setMCJITMemoryManager(std::make_unique<MemoryManager>(*this))
2885f757f3fSDimitry Andric       .setOptLevel(llvm::CodeGenOptLevel::Less);
2890b57cec5SDimitry Andric 
2900b57cec5SDimitry Andric   llvm::StringRef mArch;
2910b57cec5SDimitry Andric   llvm::StringRef mCPU;
2920b57cec5SDimitry Andric   llvm::SmallVector<std::string, 0> mAttrs;
2930b57cec5SDimitry Andric 
2940b57cec5SDimitry Andric   for (std::string &feature : m_cpu_features)
2950b57cec5SDimitry Andric     mAttrs.push_back(feature);
2960b57cec5SDimitry Andric 
2970b57cec5SDimitry Andric   llvm::TargetMachine *target_machine =
2980b57cec5SDimitry Andric       builder.selectTarget(triple, mArch, mCPU, mAttrs);
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   m_execution_engine_up.reset(builder.create(target_machine));
3010b57cec5SDimitry Andric 
3020b57cec5SDimitry Andric   if (!m_execution_engine_up) {
3030b57cec5SDimitry Andric     error.SetErrorToGenericError();
3040b57cec5SDimitry Andric     error.SetErrorStringWithFormat("Couldn't JIT the function: %s",
3050b57cec5SDimitry Andric                                    error_string.c_str());
3060b57cec5SDimitry Andric     return;
3070b57cec5SDimitry Andric   }
3080b57cec5SDimitry Andric 
3090b57cec5SDimitry Andric   m_strip_underscore =
3100b57cec5SDimitry Andric       (m_execution_engine_up->getDataLayout().getGlobalPrefix() == '_');
3110b57cec5SDimitry Andric 
3120b57cec5SDimitry Andric   class ObjectDumper : public llvm::ObjectCache {
3130b57cec5SDimitry Andric   public:
31481ad6265SDimitry Andric     ObjectDumper(FileSpec output_dir)  : m_out_dir(output_dir) {}
3150b57cec5SDimitry Andric     void notifyObjectCompiled(const llvm::Module *module,
3160b57cec5SDimitry Andric                               llvm::MemoryBufferRef object) override {
3170b57cec5SDimitry Andric       int fd = 0;
3180b57cec5SDimitry Andric       llvm::SmallVector<char, 256> result_path;
3190b57cec5SDimitry Andric       std::string object_name_model =
3200b57cec5SDimitry Andric           "jit-object-" + module->getModuleIdentifier() + "-%%%.o";
32181ad6265SDimitry Andric       FileSpec model_spec
32281ad6265SDimitry Andric           = m_out_dir.CopyByAppendingPathComponent(object_name_model);
32381ad6265SDimitry Andric       std::string model_path = model_spec.GetPath();
32481ad6265SDimitry Andric 
32581ad6265SDimitry Andric       std::error_code result
32681ad6265SDimitry Andric         = llvm::sys::fs::createUniqueFile(model_path, fd, result_path);
32781ad6265SDimitry Andric       if (!result) {
3280b57cec5SDimitry Andric           llvm::raw_fd_ostream fds(fd, true);
3290b57cec5SDimitry Andric           fds.write(object.getBufferStart(), object.getBufferSize());
3300b57cec5SDimitry Andric       }
33181ad6265SDimitry Andric     }
3320b57cec5SDimitry Andric     std::unique_ptr<llvm::MemoryBuffer>
3330b57cec5SDimitry Andric     getObject(const llvm::Module *module) override  {
3340b57cec5SDimitry Andric       // Return nothing - we're just abusing the object-cache mechanism to dump
3350b57cec5SDimitry Andric       // objects.
3360b57cec5SDimitry Andric       return nullptr;
3370b57cec5SDimitry Andric   }
33881ad6265SDimitry Andric   private:
33981ad6265SDimitry Andric     FileSpec m_out_dir;
3400b57cec5SDimitry Andric   };
3410b57cec5SDimitry Andric 
34281ad6265SDimitry Andric   FileSpec save_objects_dir = process_sp->GetTarget().GetSaveJITObjectsDir();
34381ad6265SDimitry Andric   if (save_objects_dir) {
34481ad6265SDimitry Andric     m_object_cache_up = std::make_unique<ObjectDumper>(save_objects_dir);
3450b57cec5SDimitry Andric     m_execution_engine_up->setObjectCache(m_object_cache_up.get());
3460b57cec5SDimitry Andric   }
3470b57cec5SDimitry Andric 
3480b57cec5SDimitry Andric   // Make sure we see all sections, including ones that don't have
3490b57cec5SDimitry Andric   // relocations...
3500b57cec5SDimitry Andric   m_execution_engine_up->setProcessAllSections(true);
3510b57cec5SDimitry Andric 
3520b57cec5SDimitry Andric   m_execution_engine_up->DisableLazyCompilation();
3530b57cec5SDimitry Andric 
3540b57cec5SDimitry Andric   for (llvm::Function &function : *m_module) {
3550b57cec5SDimitry Andric     if (function.isDeclaration() || function.hasPrivateLinkage())
3560b57cec5SDimitry Andric       continue;
3570b57cec5SDimitry Andric 
358e8d8bef9SDimitry Andric     const bool external = !function.hasLocalLinkage();
3590b57cec5SDimitry Andric 
3600b57cec5SDimitry Andric     void *fun_ptr = m_execution_engine_up->getPointerToFunction(&function);
3610b57cec5SDimitry Andric 
3620b57cec5SDimitry Andric     if (!error.Success()) {
3630b57cec5SDimitry Andric       // We got an error through our callback!
3640b57cec5SDimitry Andric       return;
3650b57cec5SDimitry Andric     }
3660b57cec5SDimitry Andric 
3670b57cec5SDimitry Andric     if (!fun_ptr) {
3680b57cec5SDimitry Andric       error.SetErrorToGenericError();
3690b57cec5SDimitry Andric       error.SetErrorStringWithFormat(
3700b57cec5SDimitry Andric           "'%s' was in the JITted module but wasn't lowered",
3710b57cec5SDimitry Andric           function.getName().str().c_str());
3720b57cec5SDimitry Andric       return;
3730b57cec5SDimitry Andric     }
3740b57cec5SDimitry Andric     m_jitted_functions.push_back(JittedFunction(
375480093f4SDimitry Andric         function.getName().str().c_str(), external, reinterpret_cast<uintptr_t>(fun_ptr)));
3760b57cec5SDimitry Andric   }
3770b57cec5SDimitry Andric 
3780b57cec5SDimitry Andric   CommitAllocations(process_sp);
3790b57cec5SDimitry Andric   ReportAllocations(*m_execution_engine_up);
3800b57cec5SDimitry Andric 
3810b57cec5SDimitry Andric   // We have to do this after calling ReportAllocations because for the MCJIT,
3820b57cec5SDimitry Andric   // getGlobalValueAddress will cause the JIT to perform all relocations.  That
3830b57cec5SDimitry Andric   // can only be done once, and has to happen after we do the remapping from
3840b57cec5SDimitry Andric   // local -> remote. That means we don't know the local address of the
3850b57cec5SDimitry Andric   // Variables, but we don't need that for anything, so that's okay.
3860b57cec5SDimitry Andric 
3870b57cec5SDimitry Andric   std::function<void(llvm::GlobalValue &)> RegisterOneValue = [this](
3880b57cec5SDimitry Andric       llvm::GlobalValue &val) {
3890b57cec5SDimitry Andric     if (val.hasExternalLinkage() && !val.isDeclaration()) {
3900b57cec5SDimitry Andric       uint64_t var_ptr_addr =
3910b57cec5SDimitry Andric           m_execution_engine_up->getGlobalValueAddress(val.getName().str());
3920b57cec5SDimitry Andric 
3930b57cec5SDimitry Andric       lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
3940b57cec5SDimitry Andric 
3950b57cec5SDimitry Andric       // This is a really unfortunae API that sometimes returns local addresses
3960b57cec5SDimitry Andric       // and sometimes returns remote addresses, based on whether the variable
3970b57cec5SDimitry Andric       // was relocated during ReportAllocations or not.
3980b57cec5SDimitry Andric 
3990b57cec5SDimitry Andric       if (remote_addr == LLDB_INVALID_ADDRESS) {
4000b57cec5SDimitry Andric         remote_addr = var_ptr_addr;
4010b57cec5SDimitry Andric       }
4020b57cec5SDimitry Andric 
4030b57cec5SDimitry Andric       if (var_ptr_addr != 0)
4040b57cec5SDimitry Andric         m_jitted_global_variables.push_back(JittedGlobalVariable(
4050b57cec5SDimitry Andric             val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr));
4060b57cec5SDimitry Andric     }
4070b57cec5SDimitry Andric   };
4080b57cec5SDimitry Andric 
40906c3fb27SDimitry Andric   for (llvm::GlobalVariable &global_var : m_module->globals()) {
4100b57cec5SDimitry Andric     RegisterOneValue(global_var);
4110b57cec5SDimitry Andric   }
4120b57cec5SDimitry Andric 
41306c3fb27SDimitry Andric   for (llvm::GlobalAlias &global_alias : m_module->aliases()) {
4140b57cec5SDimitry Andric     RegisterOneValue(global_alias);
4150b57cec5SDimitry Andric   }
4160b57cec5SDimitry Andric 
4170b57cec5SDimitry Andric   WriteData(process_sp);
4180b57cec5SDimitry Andric 
4190b57cec5SDimitry Andric   if (m_failed_lookups.size()) {
4200b57cec5SDimitry Andric     StreamString ss;
4210b57cec5SDimitry Andric 
4220b57cec5SDimitry Andric     ss.PutCString("Couldn't look up symbols:\n");
4230b57cec5SDimitry Andric 
4240b57cec5SDimitry Andric     bool emitNewLine = false;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric     for (ConstString failed_lookup : m_failed_lookups) {
4270b57cec5SDimitry Andric       if (emitNewLine)
4280b57cec5SDimitry Andric         ss.PutCString("\n");
4290b57cec5SDimitry Andric       emitNewLine = true;
4300b57cec5SDimitry Andric       ss.PutCString("  ");
4315ffd83dbSDimitry Andric       ss.PutCString(Mangled(failed_lookup).GetDemangledName().GetStringRef());
4320b57cec5SDimitry Andric     }
4330b57cec5SDimitry Andric 
4340b57cec5SDimitry Andric     m_failed_lookups.clear();
4350b57cec5SDimitry Andric 
4360b57cec5SDimitry Andric     error.SetErrorString(ss.GetString());
4370b57cec5SDimitry Andric 
4380b57cec5SDimitry Andric     return;
4390b57cec5SDimitry Andric   }
4400b57cec5SDimitry Andric 
4410b57cec5SDimitry Andric   m_function_load_addr = LLDB_INVALID_ADDRESS;
4420b57cec5SDimitry Andric   m_function_end_load_addr = LLDB_INVALID_ADDRESS;
4430b57cec5SDimitry Andric 
4440b57cec5SDimitry Andric   for (JittedFunction &jitted_function : m_jitted_functions) {
4450b57cec5SDimitry Andric     jitted_function.m_remote_addr =
4460b57cec5SDimitry Andric         GetRemoteAddressForLocal(jitted_function.m_local_addr);
4470b57cec5SDimitry Andric 
4480b57cec5SDimitry Andric     if (!m_name.IsEmpty() && jitted_function.m_name == m_name) {
4490b57cec5SDimitry Andric       AddrRange func_range =
4500b57cec5SDimitry Andric           GetRemoteRangeForLocal(jitted_function.m_local_addr);
4510b57cec5SDimitry Andric       m_function_end_load_addr = func_range.first + func_range.second;
4520b57cec5SDimitry Andric       m_function_load_addr = jitted_function.m_remote_addr;
4530b57cec5SDimitry Andric     }
4540b57cec5SDimitry Andric   }
4550b57cec5SDimitry Andric 
4560b57cec5SDimitry Andric   if (log) {
4579dba64beSDimitry Andric     LLDB_LOGF(log, "Code can be run in the target.");
4580b57cec5SDimitry Andric 
4590b57cec5SDimitry Andric     StreamString disassembly_stream;
4600b57cec5SDimitry Andric 
4610b57cec5SDimitry Andric     Status err = DisassembleFunction(disassembly_stream, process_sp);
4620b57cec5SDimitry Andric 
4630b57cec5SDimitry Andric     if (!err.Success()) {
4649dba64beSDimitry Andric       LLDB_LOGF(log, "Couldn't disassemble function : %s",
4650b57cec5SDimitry Andric                 err.AsCString("unknown error"));
4660b57cec5SDimitry Andric     } else {
4679dba64beSDimitry Andric       LLDB_LOGF(log, "Function disassembly:\n%s", disassembly_stream.GetData());
4680b57cec5SDimitry Andric     }
4690b57cec5SDimitry Andric 
4709dba64beSDimitry Andric     LLDB_LOGF(log, "Sections: ");
4710b57cec5SDimitry Andric     for (AllocationRecord &record : m_records) {
4720b57cec5SDimitry Andric       if (record.m_process_address != LLDB_INVALID_ADDRESS) {
4730b57cec5SDimitry Andric         record.dump(log);
4740b57cec5SDimitry Andric 
4750b57cec5SDimitry Andric         DataBufferHeap my_buffer(record.m_size, 0);
4760b57cec5SDimitry Andric         Status err;
4770b57cec5SDimitry Andric         ReadMemory(my_buffer.GetBytes(), record.m_process_address,
4780b57cec5SDimitry Andric                    record.m_size, err);
4790b57cec5SDimitry Andric 
4800b57cec5SDimitry Andric         if (err.Success()) {
4810b57cec5SDimitry Andric           DataExtractor my_extractor(my_buffer.GetBytes(),
4820b57cec5SDimitry Andric                                      my_buffer.GetByteSize(),
4830b57cec5SDimitry Andric                                      lldb::eByteOrderBig, 8);
4840b57cec5SDimitry Andric           my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(),
4850b57cec5SDimitry Andric                                 record.m_process_address, 16,
4860b57cec5SDimitry Andric                                 DataExtractor::TypeUInt8);
4870b57cec5SDimitry Andric         }
4880b57cec5SDimitry Andric       } else {
4890b57cec5SDimitry Andric         record.dump(log);
4900b57cec5SDimitry Andric 
4910b57cec5SDimitry Andric         DataExtractor my_extractor((const void *)record.m_host_address,
4920b57cec5SDimitry Andric                                    record.m_size, lldb::eByteOrderBig, 8);
4930b57cec5SDimitry Andric         my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16,
4940b57cec5SDimitry Andric                               DataExtractor::TypeUInt8);
4950b57cec5SDimitry Andric       }
4960b57cec5SDimitry Andric     }
4970b57cec5SDimitry Andric   }
4980b57cec5SDimitry Andric 
4990b57cec5SDimitry Andric   func_addr = m_function_load_addr;
5000b57cec5SDimitry Andric   func_end = m_function_end_load_addr;
5010b57cec5SDimitry Andric }
5020b57cec5SDimitry Andric 
~IRExecutionUnit()5030b57cec5SDimitry Andric IRExecutionUnit::~IRExecutionUnit() {
5040b57cec5SDimitry Andric   m_module_up.reset();
5050b57cec5SDimitry Andric   m_execution_engine_up.reset();
5060b57cec5SDimitry Andric   m_context_up.reset();
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric 
MemoryManager(IRExecutionUnit & parent)5090b57cec5SDimitry Andric IRExecutionUnit::MemoryManager::MemoryManager(IRExecutionUnit &parent)
5100b57cec5SDimitry Andric     : m_default_mm_up(new llvm::SectionMemoryManager()), m_parent(parent) {}
5110b57cec5SDimitry Andric 
512fe6060f1SDimitry Andric IRExecutionUnit::MemoryManager::~MemoryManager() = default;
5130b57cec5SDimitry Andric 
GetSectionTypeFromSectionName(const llvm::StringRef & name,IRExecutionUnit::AllocationKind alloc_kind)5140b57cec5SDimitry Andric lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
5150b57cec5SDimitry Andric     const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) {
5160b57cec5SDimitry Andric   lldb::SectionType sect_type = lldb::eSectionTypeCode;
5170b57cec5SDimitry Andric   switch (alloc_kind) {
5180b57cec5SDimitry Andric   case AllocationKind::Stub:
5190b57cec5SDimitry Andric     sect_type = lldb::eSectionTypeCode;
5200b57cec5SDimitry Andric     break;
5210b57cec5SDimitry Andric   case AllocationKind::Code:
5220b57cec5SDimitry Andric     sect_type = lldb::eSectionTypeCode;
5230b57cec5SDimitry Andric     break;
5240b57cec5SDimitry Andric   case AllocationKind::Data:
5250b57cec5SDimitry Andric     sect_type = lldb::eSectionTypeData;
5260b57cec5SDimitry Andric     break;
5270b57cec5SDimitry Andric   case AllocationKind::Global:
5280b57cec5SDimitry Andric     sect_type = lldb::eSectionTypeData;
5290b57cec5SDimitry Andric     break;
5300b57cec5SDimitry Andric   case AllocationKind::Bytes:
5310b57cec5SDimitry Andric     sect_type = lldb::eSectionTypeOther;
5320b57cec5SDimitry Andric     break;
5330b57cec5SDimitry Andric   }
5340b57cec5SDimitry Andric 
5350b57cec5SDimitry Andric   if (!name.empty()) {
5360b57cec5SDimitry Andric     if (name.equals("__text") || name.equals(".text"))
5370b57cec5SDimitry Andric       sect_type = lldb::eSectionTypeCode;
5380b57cec5SDimitry Andric     else if (name.equals("__data") || name.equals(".data"))
5390b57cec5SDimitry Andric       sect_type = lldb::eSectionTypeCode;
5405f757f3fSDimitry Andric     else if (name.starts_with("__debug_") || name.starts_with(".debug_")) {
5410b57cec5SDimitry Andric       const uint32_t name_idx = name[0] == '_' ? 8 : 7;
5420b57cec5SDimitry Andric       llvm::StringRef dwarf_name(name.substr(name_idx));
5430b57cec5SDimitry Andric       switch (dwarf_name[0]) {
5440b57cec5SDimitry Andric       case 'a':
5450b57cec5SDimitry Andric         if (dwarf_name.equals("abbrev"))
5460b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
5470b57cec5SDimitry Andric         else if (dwarf_name.equals("aranges"))
5480b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugAranges;
5490b57cec5SDimitry Andric         else if (dwarf_name.equals("addr"))
5500b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugAddr;
5510b57cec5SDimitry Andric         break;
5520b57cec5SDimitry Andric 
5530b57cec5SDimitry Andric       case 'f':
5540b57cec5SDimitry Andric         if (dwarf_name.equals("frame"))
5550b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugFrame;
5560b57cec5SDimitry Andric         break;
5570b57cec5SDimitry Andric 
5580b57cec5SDimitry Andric       case 'i':
5590b57cec5SDimitry Andric         if (dwarf_name.equals("info"))
5600b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugInfo;
5610b57cec5SDimitry Andric         break;
5620b57cec5SDimitry Andric 
5630b57cec5SDimitry Andric       case 'l':
5640b57cec5SDimitry Andric         if (dwarf_name.equals("line"))
5650b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugLine;
5660b57cec5SDimitry Andric         else if (dwarf_name.equals("loc"))
5670b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugLoc;
5680b57cec5SDimitry Andric         else if (dwarf_name.equals("loclists"))
5690b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugLocLists;
5700b57cec5SDimitry Andric         break;
5710b57cec5SDimitry Andric 
5720b57cec5SDimitry Andric       case 'm':
5730b57cec5SDimitry Andric         if (dwarf_name.equals("macinfo"))
5740b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
5750b57cec5SDimitry Andric         break;
5760b57cec5SDimitry Andric 
5770b57cec5SDimitry Andric       case 'p':
5780b57cec5SDimitry Andric         if (dwarf_name.equals("pubnames"))
5790b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugPubNames;
5800b57cec5SDimitry Andric         else if (dwarf_name.equals("pubtypes"))
5810b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
5820b57cec5SDimitry Andric         break;
5830b57cec5SDimitry Andric 
5840b57cec5SDimitry Andric       case 's':
5850b57cec5SDimitry Andric         if (dwarf_name.equals("str"))
5860b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugStr;
5870b57cec5SDimitry Andric         else if (dwarf_name.equals("str_offsets"))
5880b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
5890b57cec5SDimitry Andric         break;
5900b57cec5SDimitry Andric 
5910b57cec5SDimitry Andric       case 'r':
5920b57cec5SDimitry Andric         if (dwarf_name.equals("ranges"))
5930b57cec5SDimitry Andric           sect_type = lldb::eSectionTypeDWARFDebugRanges;
5940b57cec5SDimitry Andric         break;
5950b57cec5SDimitry Andric 
5960b57cec5SDimitry Andric       default:
5970b57cec5SDimitry Andric         break;
5980b57cec5SDimitry Andric       }
5995f757f3fSDimitry Andric     } else if (name.starts_with("__apple_") || name.starts_with(".apple_"))
6000b57cec5SDimitry Andric       sect_type = lldb::eSectionTypeInvalid;
6010b57cec5SDimitry Andric     else if (name.equals("__objc_imageinfo"))
6020b57cec5SDimitry Andric       sect_type = lldb::eSectionTypeOther;
6030b57cec5SDimitry Andric   }
6040b57cec5SDimitry Andric   return sect_type;
6050b57cec5SDimitry Andric }
6060b57cec5SDimitry Andric 
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,llvm::StringRef SectionName)6070b57cec5SDimitry Andric uint8_t *IRExecutionUnit::MemoryManager::allocateCodeSection(
6080b57cec5SDimitry Andric     uintptr_t Size, unsigned Alignment, unsigned SectionID,
6090b57cec5SDimitry Andric     llvm::StringRef SectionName) {
61081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
6110b57cec5SDimitry Andric 
6120b57cec5SDimitry Andric   uint8_t *return_value = m_default_mm_up->allocateCodeSection(
6130b57cec5SDimitry Andric       Size, Alignment, SectionID, SectionName);
6140b57cec5SDimitry Andric 
6150b57cec5SDimitry Andric   m_parent.m_records.push_back(AllocationRecord(
6160b57cec5SDimitry Andric       (uintptr_t)return_value,
6170b57cec5SDimitry Andric       lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
6180b57cec5SDimitry Andric       GetSectionTypeFromSectionName(SectionName, AllocationKind::Code), Size,
6190b57cec5SDimitry Andric       Alignment, SectionID, SectionName.str().c_str()));
6200b57cec5SDimitry Andric 
6219dba64beSDimitry Andric   LLDB_LOGF(log,
6229dba64beSDimitry Andric             "IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64
6230b57cec5SDimitry Andric             ", Alignment=%u, SectionID=%u) = %p",
6240b57cec5SDimitry Andric             (uint64_t)Size, Alignment, SectionID, (void *)return_value);
6250b57cec5SDimitry Andric 
6260b57cec5SDimitry Andric   if (m_parent.m_reported_allocations) {
6270b57cec5SDimitry Andric     Status err;
6280b57cec5SDimitry Andric     lldb::ProcessSP process_sp =
6290b57cec5SDimitry Andric         m_parent.GetBestExecutionContextScope()->CalculateProcess();
6300b57cec5SDimitry Andric 
6310b57cec5SDimitry Andric     m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
6320b57cec5SDimitry Andric   }
6330b57cec5SDimitry Andric 
6340b57cec5SDimitry Andric   return return_value;
6350b57cec5SDimitry Andric }
6360b57cec5SDimitry Andric 
allocateDataSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,llvm::StringRef SectionName,bool IsReadOnly)6370b57cec5SDimitry Andric uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection(
6380b57cec5SDimitry Andric     uintptr_t Size, unsigned Alignment, unsigned SectionID,
6390b57cec5SDimitry Andric     llvm::StringRef SectionName, bool IsReadOnly) {
64081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
6410b57cec5SDimitry Andric 
6420b57cec5SDimitry Andric   uint8_t *return_value = m_default_mm_up->allocateDataSection(
6430b57cec5SDimitry Andric       Size, Alignment, SectionID, SectionName, IsReadOnly);
6440b57cec5SDimitry Andric 
6450b57cec5SDimitry Andric   uint32_t permissions = lldb::ePermissionsReadable;
6460b57cec5SDimitry Andric   if (!IsReadOnly)
6470b57cec5SDimitry Andric     permissions |= lldb::ePermissionsWritable;
6480b57cec5SDimitry Andric   m_parent.m_records.push_back(AllocationRecord(
6490b57cec5SDimitry Andric       (uintptr_t)return_value, permissions,
6500b57cec5SDimitry Andric       GetSectionTypeFromSectionName(SectionName, AllocationKind::Data), Size,
6510b57cec5SDimitry Andric       Alignment, SectionID, SectionName.str().c_str()));
6529dba64beSDimitry Andric   LLDB_LOGF(log,
6539dba64beSDimitry Andric             "IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64
6540b57cec5SDimitry Andric             ", Alignment=%u, SectionID=%u) = %p",
6550b57cec5SDimitry Andric             (uint64_t)Size, Alignment, SectionID, (void *)return_value);
6560b57cec5SDimitry Andric 
6570b57cec5SDimitry Andric   if (m_parent.m_reported_allocations) {
6580b57cec5SDimitry Andric     Status err;
6590b57cec5SDimitry Andric     lldb::ProcessSP process_sp =
6600b57cec5SDimitry Andric         m_parent.GetBestExecutionContextScope()->CalculateProcess();
6610b57cec5SDimitry Andric 
6620b57cec5SDimitry Andric     m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
6630b57cec5SDimitry Andric   }
6640b57cec5SDimitry Andric 
6650b57cec5SDimitry Andric   return return_value;
6660b57cec5SDimitry Andric }
6670b57cec5SDimitry Andric 
CollectCandidateCNames(std::vector<ConstString> & C_names,ConstString name)668349cc55cSDimitry Andric void IRExecutionUnit::CollectCandidateCNames(std::vector<ConstString> &C_names,
6690b57cec5SDimitry Andric                                              ConstString name) {
6700b57cec5SDimitry Andric   if (m_strip_underscore && name.AsCString()[0] == '_')
671349cc55cSDimitry Andric     C_names.insert(C_names.begin(), ConstString(&name.AsCString()[1]));
672349cc55cSDimitry Andric   C_names.push_back(name);
6730b57cec5SDimitry Andric }
6740b57cec5SDimitry Andric 
CollectCandidateCPlusPlusNames(std::vector<ConstString> & CPP_names,const std::vector<ConstString> & C_names,const SymbolContext & sc)6750b57cec5SDimitry Andric void IRExecutionUnit::CollectCandidateCPlusPlusNames(
676349cc55cSDimitry Andric     std::vector<ConstString> &CPP_names,
677349cc55cSDimitry Andric     const std::vector<ConstString> &C_names, const SymbolContext &sc) {
678349cc55cSDimitry Andric   if (auto *cpp_lang = Language::FindPlugin(lldb::eLanguageTypeC_plus_plus)) {
679349cc55cSDimitry Andric     for (const ConstString &name : C_names) {
6809dba64beSDimitry Andric       Mangled mangled(name);
681349cc55cSDimitry Andric       if (cpp_lang->SymbolNameFitsToLanguage(mangled)) {
682349cc55cSDimitry Andric         if (ConstString best_alternate =
683349cc55cSDimitry Andric                 cpp_lang->FindBestAlternateFunctionMangledName(mangled, sc)) {
684349cc55cSDimitry Andric           CPP_names.push_back(best_alternate);
685349cc55cSDimitry Andric         }
686349cc55cSDimitry Andric       }
6870b57cec5SDimitry Andric 
688349cc55cSDimitry Andric       std::vector<ConstString> alternates =
689349cc55cSDimitry Andric           cpp_lang->GenerateAlternateFunctionManglings(name);
690349cc55cSDimitry Andric       CPP_names.insert(CPP_names.end(), alternates.begin(), alternates.end());
6910b57cec5SDimitry Andric 
692349cc55cSDimitry Andric       // As a last-ditch fallback, try the base name for C++ names.  It's
693349cc55cSDimitry Andric       // terrible, but the DWARF doesn't always encode "extern C" correctly.
694349cc55cSDimitry Andric       ConstString basename =
695349cc55cSDimitry Andric           cpp_lang->GetDemangledFunctionNameWithoutArguments(mangled);
696349cc55cSDimitry Andric       CPP_names.push_back(basename);
6970b57cec5SDimitry Andric     }
6980b57cec5SDimitry Andric   }
6990b57cec5SDimitry Andric }
7000b57cec5SDimitry Andric 
701349cc55cSDimitry Andric class LoadAddressResolver {
702349cc55cSDimitry Andric public:
LoadAddressResolver(Target * target,bool & symbol_was_missing_weak)703349cc55cSDimitry Andric   LoadAddressResolver(Target *target, bool &symbol_was_missing_weak)
704349cc55cSDimitry Andric       : m_target(target), m_symbol_was_missing_weak(symbol_was_missing_weak) {}
7050b57cec5SDimitry Andric 
Resolve(SymbolContextList & sc_list)706bdd1243dSDimitry Andric   std::optional<lldb::addr_t> Resolve(SymbolContextList &sc_list) {
707349cc55cSDimitry Andric     if (sc_list.IsEmpty())
708bdd1243dSDimitry Andric       return std::nullopt;
7090b57cec5SDimitry Andric 
710349cc55cSDimitry Andric     lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
7110b57cec5SDimitry Andric 
712349cc55cSDimitry Andric     // Missing_weak_symbol will be true only if we found only weak undefined
7130b57cec5SDimitry Andric     // references to this symbol.
714349cc55cSDimitry Andric     m_symbol_was_missing_weak = true;
7150b57cec5SDimitry Andric 
716349cc55cSDimitry Andric     for (auto candidate_sc : sc_list.SymbolContexts()) {
717349cc55cSDimitry Andric       // Only symbols can be weak undefined.
718349cc55cSDimitry Andric       if (!candidate_sc.symbol ||
719349cc55cSDimitry Andric           candidate_sc.symbol->GetType() != lldb::eSymbolTypeUndefined ||
720349cc55cSDimitry Andric           !candidate_sc.symbol->IsWeak())
721349cc55cSDimitry Andric         m_symbol_was_missing_weak = false;
722349cc55cSDimitry Andric 
723349cc55cSDimitry Andric       // First try the symbol.
724349cc55cSDimitry Andric       if (candidate_sc.symbol) {
725349cc55cSDimitry Andric         load_address = candidate_sc.symbol->ResolveCallableAddress(*m_target);
726349cc55cSDimitry Andric         if (load_address == LLDB_INVALID_ADDRESS) {
727349cc55cSDimitry Andric           Address addr = candidate_sc.symbol->GetAddress();
728349cc55cSDimitry Andric           load_address = m_target->GetProcessSP()
729349cc55cSDimitry Andric                              ? addr.GetLoadAddress(m_target)
730349cc55cSDimitry Andric                              : addr.GetFileAddress();
731349cc55cSDimitry Andric         }
732349cc55cSDimitry Andric       }
733349cc55cSDimitry Andric 
734349cc55cSDimitry Andric       // If that didn't work, try the function.
735349cc55cSDimitry Andric       if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) {
736349cc55cSDimitry Andric         Address addr =
737349cc55cSDimitry Andric             candidate_sc.function->GetAddressRange().GetBaseAddress();
738349cc55cSDimitry Andric         load_address = m_target->GetProcessSP() ? addr.GetLoadAddress(m_target)
739349cc55cSDimitry Andric                                                 : addr.GetFileAddress();
740349cc55cSDimitry Andric       }
741349cc55cSDimitry Andric 
742349cc55cSDimitry Andric       // We found a load address.
743349cc55cSDimitry Andric       if (load_address != LLDB_INVALID_ADDRESS) {
744349cc55cSDimitry Andric         // If the load address is external, we're done.
7450b57cec5SDimitry Andric         const bool is_external =
7460b57cec5SDimitry Andric             (candidate_sc.function) ||
7470b57cec5SDimitry Andric             (candidate_sc.symbol && candidate_sc.symbol->IsExternal());
748349cc55cSDimitry Andric         if (is_external)
749349cc55cSDimitry Andric           return load_address;
7500b57cec5SDimitry Andric 
751349cc55cSDimitry Andric         // Otherwise, remember the best internal load address.
752349cc55cSDimitry Andric         if (m_best_internal_load_address == LLDB_INVALID_ADDRESS)
753349cc55cSDimitry Andric           m_best_internal_load_address = load_address;
7540b57cec5SDimitry Andric       }
7550b57cec5SDimitry Andric     }
7560b57cec5SDimitry Andric 
7570b57cec5SDimitry Andric     // You test the address of a weak symbol against NULL to see if it is
7580b57cec5SDimitry Andric     // present. So we should return 0 for a missing weak symbol.
759349cc55cSDimitry Andric     if (m_symbol_was_missing_weak)
760349cc55cSDimitry Andric       return 0;
761349cc55cSDimitry Andric 
762bdd1243dSDimitry Andric     return std::nullopt;
7630b57cec5SDimitry Andric   }
7640b57cec5SDimitry Andric 
GetBestInternalLoadAddress() const765349cc55cSDimitry Andric   lldb::addr_t GetBestInternalLoadAddress() const {
766349cc55cSDimitry Andric     return m_best_internal_load_address;
767349cc55cSDimitry Andric   }
768349cc55cSDimitry Andric 
769349cc55cSDimitry Andric private:
770349cc55cSDimitry Andric   Target *m_target;
771349cc55cSDimitry Andric   bool &m_symbol_was_missing_weak;
772349cc55cSDimitry Andric   lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
7730b57cec5SDimitry Andric };
7740b57cec5SDimitry Andric 
775349cc55cSDimitry Andric lldb::addr_t
FindInSymbols(const std::vector<ConstString> & names,const lldb_private::SymbolContext & sc,bool & symbol_was_missing_weak)776349cc55cSDimitry Andric IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
777349cc55cSDimitry Andric                                const lldb_private::SymbolContext &sc,
778349cc55cSDimitry Andric                                bool &symbol_was_missing_weak) {
779349cc55cSDimitry Andric   symbol_was_missing_weak = false;
780349cc55cSDimitry Andric 
781349cc55cSDimitry Andric   Target *target = sc.target_sp.get();
782349cc55cSDimitry Andric   if (!target) {
783349cc55cSDimitry Andric     // We shouldn't be doing any symbol lookup at all without a target.
784349cc55cSDimitry Andric     return LLDB_INVALID_ADDRESS;
785349cc55cSDimitry Andric   }
786349cc55cSDimitry Andric 
787349cc55cSDimitry Andric   LoadAddressResolver resolver(target, symbol_was_missing_weak);
788349cc55cSDimitry Andric 
789349cc55cSDimitry Andric   ModuleFunctionSearchOptions function_options;
790349cc55cSDimitry Andric   function_options.include_symbols = true;
791349cc55cSDimitry Andric   function_options.include_inlines = false;
792349cc55cSDimitry Andric 
793349cc55cSDimitry Andric   for (const ConstString &name : names) {
7940b57cec5SDimitry Andric     if (sc.module_sp) {
795349cc55cSDimitry Andric       SymbolContextList sc_list;
796349cc55cSDimitry Andric       sc.module_sp->FindFunctions(name, CompilerDeclContext(),
797349cc55cSDimitry Andric                                   lldb::eFunctionNameTypeFull, function_options,
7980b57cec5SDimitry Andric                                   sc_list);
799349cc55cSDimitry Andric       if (auto load_addr = resolver.Resolve(sc_list))
800349cc55cSDimitry Andric         return *load_addr;
8010b57cec5SDimitry Andric     }
8020b57cec5SDimitry Andric 
803349cc55cSDimitry Andric     if (sc.target_sp) {
804349cc55cSDimitry Andric       SymbolContextList sc_list;
805349cc55cSDimitry Andric       sc.target_sp->GetImages().FindFunctions(name, lldb::eFunctionNameTypeFull,
806349cc55cSDimitry Andric                                               function_options, sc_list);
807349cc55cSDimitry Andric       if (auto load_addr = resolver.Resolve(sc_list))
808349cc55cSDimitry Andric         return *load_addr;
8090b57cec5SDimitry Andric     }
8100b57cec5SDimitry Andric 
811349cc55cSDimitry Andric     if (sc.target_sp) {
812349cc55cSDimitry Andric       SymbolContextList sc_list;
8130b57cec5SDimitry Andric       sc.target_sp->GetImages().FindSymbolsWithNameAndType(
814349cc55cSDimitry Andric           name, lldb::eSymbolTypeAny, sc_list);
815349cc55cSDimitry Andric       if (auto load_addr = resolver.Resolve(sc_list))
816349cc55cSDimitry Andric         return *load_addr;
8170b57cec5SDimitry Andric     }
8180b57cec5SDimitry Andric 
819349cc55cSDimitry Andric     lldb::addr_t best_internal_load_address =
820349cc55cSDimitry Andric         resolver.GetBestInternalLoadAddress();
821349cc55cSDimitry Andric     if (best_internal_load_address != LLDB_INVALID_ADDRESS)
8220b57cec5SDimitry Andric       return best_internal_load_address;
8230b57cec5SDimitry Andric   }
8240b57cec5SDimitry Andric 
8250b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
8260b57cec5SDimitry Andric }
8270b57cec5SDimitry Andric 
8280b57cec5SDimitry Andric lldb::addr_t
FindInRuntimes(const std::vector<ConstString> & names,const lldb_private::SymbolContext & sc)829349cc55cSDimitry Andric IRExecutionUnit::FindInRuntimes(const std::vector<ConstString> &names,
8300b57cec5SDimitry Andric                                 const lldb_private::SymbolContext &sc) {
8310b57cec5SDimitry Andric   lldb::TargetSP target_sp = sc.target_sp;
8320b57cec5SDimitry Andric 
8330b57cec5SDimitry Andric   if (!target_sp) {
8340b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
8350b57cec5SDimitry Andric   }
8360b57cec5SDimitry Andric 
8370b57cec5SDimitry Andric   lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP();
8380b57cec5SDimitry Andric 
8390b57cec5SDimitry Andric   if (!process_sp) {
8400b57cec5SDimitry Andric     return LLDB_INVALID_ADDRESS;
8410b57cec5SDimitry Andric   }
8420b57cec5SDimitry Andric 
843349cc55cSDimitry Andric   for (const ConstString &name : names) {
8440b57cec5SDimitry Andric     for (LanguageRuntime *runtime : process_sp->GetLanguageRuntimes()) {
845349cc55cSDimitry Andric       lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(name);
8460b57cec5SDimitry Andric 
8470b57cec5SDimitry Andric       if (symbol_load_addr != LLDB_INVALID_ADDRESS)
8480b57cec5SDimitry Andric         return symbol_load_addr;
8490b57cec5SDimitry Andric     }
8500b57cec5SDimitry Andric   }
8510b57cec5SDimitry Andric 
8520b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
8530b57cec5SDimitry Andric }
8540b57cec5SDimitry Andric 
FindInUserDefinedSymbols(const std::vector<ConstString> & names,const lldb_private::SymbolContext & sc)8550b57cec5SDimitry Andric lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
856349cc55cSDimitry Andric     const std::vector<ConstString> &names,
8570b57cec5SDimitry Andric     const lldb_private::SymbolContext &sc) {
8580b57cec5SDimitry Andric   lldb::TargetSP target_sp = sc.target_sp;
8590b57cec5SDimitry Andric 
860349cc55cSDimitry Andric   for (const ConstString &name : names) {
861349cc55cSDimitry Andric     lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(name);
8620b57cec5SDimitry Andric 
8630b57cec5SDimitry Andric     if (symbol_load_addr != LLDB_INVALID_ADDRESS)
8640b57cec5SDimitry Andric       return symbol_load_addr;
8650b57cec5SDimitry Andric   }
8660b57cec5SDimitry Andric 
8670b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
8680b57cec5SDimitry Andric }
8690b57cec5SDimitry Andric 
FindSymbol(lldb_private::ConstString name,bool & missing_weak)870349cc55cSDimitry Andric lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
871349cc55cSDimitry Andric                                          bool &missing_weak) {
872349cc55cSDimitry Andric   std::vector<ConstString> candidate_C_names;
873349cc55cSDimitry Andric   std::vector<ConstString> candidate_CPlusPlus_names;
8740b57cec5SDimitry Andric 
8750b57cec5SDimitry Andric   CollectCandidateCNames(candidate_C_names, name);
8760b57cec5SDimitry Andric 
8770b57cec5SDimitry Andric   lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx, missing_weak);
8780b57cec5SDimitry Andric   if (ret != LLDB_INVALID_ADDRESS)
8790b57cec5SDimitry Andric     return ret;
8800b57cec5SDimitry Andric 
8810b57cec5SDimitry Andric   // If we find the symbol in runtimes or user defined symbols it can't be
8820b57cec5SDimitry Andric   // a missing weak symbol.
8830b57cec5SDimitry Andric   missing_weak = false;
8840b57cec5SDimitry Andric   ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
8850b57cec5SDimitry Andric   if (ret != LLDB_INVALID_ADDRESS)
8860b57cec5SDimitry Andric     return ret;
8870b57cec5SDimitry Andric 
8880b57cec5SDimitry Andric   ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
8890b57cec5SDimitry Andric   if (ret != LLDB_INVALID_ADDRESS)
8900b57cec5SDimitry Andric     return ret;
8910b57cec5SDimitry Andric 
8920b57cec5SDimitry Andric   CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names,
8930b57cec5SDimitry Andric                                  m_sym_ctx);
8940b57cec5SDimitry Andric   ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx, missing_weak);
8950b57cec5SDimitry Andric   return ret;
8960b57cec5SDimitry Andric }
8970b57cec5SDimitry Andric 
GetStaticInitializers(std::vector<lldb::addr_t> & static_initializers)8980b57cec5SDimitry Andric void IRExecutionUnit::GetStaticInitializers(
8990b57cec5SDimitry Andric     std::vector<lldb::addr_t> &static_initializers) {
90081ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
901480093f4SDimitry Andric 
902480093f4SDimitry Andric   llvm::GlobalVariable *global_ctors =
903480093f4SDimitry Andric       m_module->getNamedGlobal("llvm.global_ctors");
904480093f4SDimitry Andric   if (!global_ctors) {
905480093f4SDimitry Andric     LLDB_LOG(log, "Couldn't find llvm.global_ctors.");
906480093f4SDimitry Andric     return;
907480093f4SDimitry Andric   }
908480093f4SDimitry Andric   auto *ctor_array =
909480093f4SDimitry Andric       llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer());
910480093f4SDimitry Andric   if (!ctor_array) {
911480093f4SDimitry Andric     LLDB_LOG(log, "llvm.global_ctors not a ConstantArray.");
912480093f4SDimitry Andric     return;
913480093f4SDimitry Andric   }
914480093f4SDimitry Andric 
9150b57cec5SDimitry Andric   for (llvm::Use &ctor_use : ctor_array->operands()) {
916480093f4SDimitry Andric     auto *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use);
917480093f4SDimitry Andric     if (!ctor_struct)
918480093f4SDimitry Andric       continue;
919480093f4SDimitry Andric     // this is standardized
920480093f4SDimitry Andric     lldbassert(ctor_struct->getNumOperands() == 3);
921480093f4SDimitry Andric     auto *ctor_function =
922480093f4SDimitry Andric         llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1));
923480093f4SDimitry Andric     if (!ctor_function) {
924480093f4SDimitry Andric       LLDB_LOG(log, "global_ctor doesn't contain an llvm::Function");
925480093f4SDimitry Andric       continue;
926480093f4SDimitry Andric     }
927480093f4SDimitry Andric 
928480093f4SDimitry Andric     ConstString ctor_function_name(ctor_function->getName().str());
929480093f4SDimitry Andric     LLDB_LOG(log, "Looking for callable jitted function with name {0}.",
930480093f4SDimitry Andric              ctor_function_name);
9310b57cec5SDimitry Andric 
9320b57cec5SDimitry Andric     for (JittedFunction &jitted_function : m_jitted_functions) {
933480093f4SDimitry Andric       if (ctor_function_name != jitted_function.m_name)
934480093f4SDimitry Andric         continue;
935480093f4SDimitry Andric       if (jitted_function.m_remote_addr == LLDB_INVALID_ADDRESS) {
936480093f4SDimitry Andric         LLDB_LOG(log, "Found jitted function with invalid address.");
937480093f4SDimitry Andric         continue;
938480093f4SDimitry Andric       }
9390b57cec5SDimitry Andric       static_initializers.push_back(jitted_function.m_remote_addr);
940480093f4SDimitry Andric       LLDB_LOG(log, "Calling function at address {0:x}.",
941480093f4SDimitry Andric                jitted_function.m_remote_addr);
9420b57cec5SDimitry Andric       break;
9430b57cec5SDimitry Andric     }
9440b57cec5SDimitry Andric   }
9450b57cec5SDimitry Andric }
9460b57cec5SDimitry Andric 
9470b57cec5SDimitry Andric llvm::JITSymbol
findSymbol(const std::string & Name)9480b57cec5SDimitry Andric IRExecutionUnit::MemoryManager::findSymbol(const std::string &Name) {
9490b57cec5SDimitry Andric     bool missing_weak = false;
9500b57cec5SDimitry Andric     uint64_t addr = GetSymbolAddressAndPresence(Name, missing_weak);
9510b57cec5SDimitry Andric     // This is a weak symbol:
9520b57cec5SDimitry Andric     if (missing_weak)
9530b57cec5SDimitry Andric       return llvm::JITSymbol(addr,
9540b57cec5SDimitry Andric           llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Weak);
9550b57cec5SDimitry Andric     else
9560b57cec5SDimitry Andric       return llvm::JITSymbol(addr, llvm::JITSymbolFlags::Exported);
9570b57cec5SDimitry Andric }
9580b57cec5SDimitry Andric 
9590b57cec5SDimitry Andric uint64_t
getSymbolAddress(const std::string & Name)9600b57cec5SDimitry Andric IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) {
9610b57cec5SDimitry Andric   bool missing_weak = false;
9620b57cec5SDimitry Andric   return GetSymbolAddressAndPresence(Name, missing_weak);
9630b57cec5SDimitry Andric }
9640b57cec5SDimitry Andric 
9650b57cec5SDimitry Andric uint64_t
GetSymbolAddressAndPresence(const std::string & Name,bool & missing_weak)9660b57cec5SDimitry Andric IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence(
9670b57cec5SDimitry Andric     const std::string &Name, bool &missing_weak) {
96881ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
9690b57cec5SDimitry Andric 
9700b57cec5SDimitry Andric   ConstString name_cs(Name.c_str());
9710b57cec5SDimitry Andric 
9720b57cec5SDimitry Andric   lldb::addr_t ret = m_parent.FindSymbol(name_cs, missing_weak);
9730b57cec5SDimitry Andric 
9740b57cec5SDimitry Andric   if (ret == LLDB_INVALID_ADDRESS) {
9759dba64beSDimitry Andric     LLDB_LOGF(log,
9760b57cec5SDimitry Andric               "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>",
9770b57cec5SDimitry Andric               Name.c_str());
9780b57cec5SDimitry Andric 
9790b57cec5SDimitry Andric     m_parent.ReportSymbolLookupError(name_cs);
9800b57cec5SDimitry Andric     return 0;
9810b57cec5SDimitry Andric   } else {
9829dba64beSDimitry Andric     LLDB_LOGF(log, "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
9830b57cec5SDimitry Andric               Name.c_str(), ret);
9840b57cec5SDimitry Andric     return ret;
9850b57cec5SDimitry Andric   }
9860b57cec5SDimitry Andric }
9870b57cec5SDimitry Andric 
getPointerToNamedFunction(const std::string & Name,bool AbortOnFailure)9880b57cec5SDimitry Andric void *IRExecutionUnit::MemoryManager::getPointerToNamedFunction(
9890b57cec5SDimitry Andric     const std::string &Name, bool AbortOnFailure) {
9900b57cec5SDimitry Andric   return (void *)getSymbolAddress(Name);
9910b57cec5SDimitry Andric }
9920b57cec5SDimitry Andric 
9930b57cec5SDimitry Andric lldb::addr_t
GetRemoteAddressForLocal(lldb::addr_t local_address)9940b57cec5SDimitry Andric IRExecutionUnit::GetRemoteAddressForLocal(lldb::addr_t local_address) {
99581ad6265SDimitry Andric   Log *log = GetLog(LLDBLog::Expressions);
9960b57cec5SDimitry Andric 
9970b57cec5SDimitry Andric   for (AllocationRecord &record : m_records) {
9980b57cec5SDimitry Andric     if (local_address >= record.m_host_address &&
9990b57cec5SDimitry Andric         local_address < record.m_host_address + record.m_size) {
10000b57cec5SDimitry Andric       if (record.m_process_address == LLDB_INVALID_ADDRESS)
10010b57cec5SDimitry Andric         return LLDB_INVALID_ADDRESS;
10020b57cec5SDimitry Andric 
10030b57cec5SDimitry Andric       lldb::addr_t ret =
10040b57cec5SDimitry Andric           record.m_process_address + (local_address - record.m_host_address);
10050b57cec5SDimitry Andric 
10069dba64beSDimitry Andric       LLDB_LOGF(log,
10070b57cec5SDimitry Andric                 "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64
10080b57cec5SDimitry Andric                 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64
10090b57cec5SDimitry Andric                 " from [0x%" PRIx64 "..0x%" PRIx64 "].",
10100b57cec5SDimitry Andric                 local_address, (uint64_t)record.m_host_address,
10110b57cec5SDimitry Andric                 (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret,
10129dba64beSDimitry Andric                 record.m_process_address,
10139dba64beSDimitry Andric                 record.m_process_address + record.m_size);
10140b57cec5SDimitry Andric 
10150b57cec5SDimitry Andric       return ret;
10160b57cec5SDimitry Andric     }
10170b57cec5SDimitry Andric   }
10180b57cec5SDimitry Andric 
10190b57cec5SDimitry Andric   return LLDB_INVALID_ADDRESS;
10200b57cec5SDimitry Andric }
10210b57cec5SDimitry Andric 
10220b57cec5SDimitry Andric IRExecutionUnit::AddrRange
GetRemoteRangeForLocal(lldb::addr_t local_address)10230b57cec5SDimitry Andric IRExecutionUnit::GetRemoteRangeForLocal(lldb::addr_t local_address) {
10240b57cec5SDimitry Andric   for (AllocationRecord &record : m_records) {
10250b57cec5SDimitry Andric     if (local_address >= record.m_host_address &&
10260b57cec5SDimitry Andric         local_address < record.m_host_address + record.m_size) {
10270b57cec5SDimitry Andric       if (record.m_process_address == LLDB_INVALID_ADDRESS)
10280b57cec5SDimitry Andric         return AddrRange(0, 0);
10290b57cec5SDimitry Andric 
10300b57cec5SDimitry Andric       return AddrRange(record.m_process_address, record.m_size);
10310b57cec5SDimitry Andric     }
10320b57cec5SDimitry Andric   }
10330b57cec5SDimitry Andric 
10340b57cec5SDimitry Andric   return AddrRange(0, 0);
10350b57cec5SDimitry Andric }
10360b57cec5SDimitry Andric 
CommitOneAllocation(lldb::ProcessSP & process_sp,Status & error,AllocationRecord & record)10370b57cec5SDimitry Andric bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp,
10380b57cec5SDimitry Andric                                           Status &error,
10390b57cec5SDimitry Andric                                           AllocationRecord &record) {
10400b57cec5SDimitry Andric   if (record.m_process_address != LLDB_INVALID_ADDRESS) {
10410b57cec5SDimitry Andric     return true;
10420b57cec5SDimitry Andric   }
10430b57cec5SDimitry Andric 
10440b57cec5SDimitry Andric   switch (record.m_sect_type) {
10450b57cec5SDimitry Andric   case lldb::eSectionTypeInvalid:
10460b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugAbbrev:
10470b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugAddr:
10480b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugAranges:
10490b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugCuIndex:
10500b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugFrame:
10510b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugInfo:
10520b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugLine:
10530b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugLoc:
10540b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugLocLists:
10550b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugMacInfo:
10560b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugPubNames:
10570b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugPubTypes:
10580b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugRanges:
10590b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugStr:
10600b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFDebugStrOffsets:
10610b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFAppleNames:
10620b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFAppleTypes:
10630b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFAppleNamespaces:
10640b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFAppleObjC:
10650b57cec5SDimitry Andric   case lldb::eSectionTypeDWARFGNUDebugAltLink:
10660b57cec5SDimitry Andric     error.Clear();
10670b57cec5SDimitry Andric     break;
10680b57cec5SDimitry Andric   default:
10690b57cec5SDimitry Andric     const bool zero_memory = false;
10700b57cec5SDimitry Andric     record.m_process_address =
10710b57cec5SDimitry Andric         Malloc(record.m_size, record.m_alignment, record.m_permissions,
10720b57cec5SDimitry Andric                eAllocationPolicyProcessOnly, zero_memory, error);
10730b57cec5SDimitry Andric     break;
10740b57cec5SDimitry Andric   }
10750b57cec5SDimitry Andric 
10760b57cec5SDimitry Andric   return error.Success();
10770b57cec5SDimitry Andric }
10780b57cec5SDimitry Andric 
CommitAllocations(lldb::ProcessSP & process_sp)10790b57cec5SDimitry Andric bool IRExecutionUnit::CommitAllocations(lldb::ProcessSP &process_sp) {
10800b57cec5SDimitry Andric   bool ret = true;
10810b57cec5SDimitry Andric 
10820b57cec5SDimitry Andric   lldb_private::Status err;
10830b57cec5SDimitry Andric 
10840b57cec5SDimitry Andric   for (AllocationRecord &record : m_records) {
10850b57cec5SDimitry Andric     ret = CommitOneAllocation(process_sp, err, record);
10860b57cec5SDimitry Andric 
10870b57cec5SDimitry Andric     if (!ret) {
10880b57cec5SDimitry Andric       break;
10890b57cec5SDimitry Andric     }
10900b57cec5SDimitry Andric   }
10910b57cec5SDimitry Andric 
10920b57cec5SDimitry Andric   if (!ret) {
10930b57cec5SDimitry Andric     for (AllocationRecord &record : m_records) {
10940b57cec5SDimitry Andric       if (record.m_process_address != LLDB_INVALID_ADDRESS) {
10950b57cec5SDimitry Andric         Free(record.m_process_address, err);
10960b57cec5SDimitry Andric         record.m_process_address = LLDB_INVALID_ADDRESS;
10970b57cec5SDimitry Andric       }
10980b57cec5SDimitry Andric     }
10990b57cec5SDimitry Andric   }
11000b57cec5SDimitry Andric 
11010b57cec5SDimitry Andric   return ret;
11020b57cec5SDimitry Andric }
11030b57cec5SDimitry Andric 
ReportAllocations(llvm::ExecutionEngine & engine)11040b57cec5SDimitry Andric void IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine &engine) {
11050b57cec5SDimitry Andric   m_reported_allocations = true;
11060b57cec5SDimitry Andric 
11070b57cec5SDimitry Andric   for (AllocationRecord &record : m_records) {
11080b57cec5SDimitry Andric     if (record.m_process_address == LLDB_INVALID_ADDRESS)
11090b57cec5SDimitry Andric       continue;
11100b57cec5SDimitry Andric 
11110b57cec5SDimitry Andric     if (record.m_section_id == eSectionIDInvalid)
11120b57cec5SDimitry Andric       continue;
11130b57cec5SDimitry Andric 
11140b57cec5SDimitry Andric     engine.mapSectionAddress((void *)record.m_host_address,
11150b57cec5SDimitry Andric                              record.m_process_address);
11160b57cec5SDimitry Andric   }
11170b57cec5SDimitry Andric 
11180b57cec5SDimitry Andric   // Trigger re-application of relocations.
11190b57cec5SDimitry Andric   engine.finalizeObject();
11200b57cec5SDimitry Andric }
11210b57cec5SDimitry Andric 
WriteData(lldb::ProcessSP & process_sp)11220b57cec5SDimitry Andric bool IRExecutionUnit::WriteData(lldb::ProcessSP &process_sp) {
11230b57cec5SDimitry Andric   bool wrote_something = false;
11240b57cec5SDimitry Andric   for (AllocationRecord &record : m_records) {
11250b57cec5SDimitry Andric     if (record.m_process_address != LLDB_INVALID_ADDRESS) {
11260b57cec5SDimitry Andric       lldb_private::Status err;
11270b57cec5SDimitry Andric       WriteMemory(record.m_process_address, (uint8_t *)record.m_host_address,
11280b57cec5SDimitry Andric                   record.m_size, err);
11290b57cec5SDimitry Andric       if (err.Success())
11300b57cec5SDimitry Andric         wrote_something = true;
11310b57cec5SDimitry Andric     }
11320b57cec5SDimitry Andric   }
11330b57cec5SDimitry Andric   return wrote_something;
11340b57cec5SDimitry Andric }
11350b57cec5SDimitry Andric 
dump(Log * log)11360b57cec5SDimitry Andric void IRExecutionUnit::AllocationRecord::dump(Log *log) {
11370b57cec5SDimitry Andric   if (!log)
11380b57cec5SDimitry Andric     return;
11390b57cec5SDimitry Andric 
11409dba64beSDimitry Andric   LLDB_LOGF(log,
11419dba64beSDimitry Andric             "[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
11420b57cec5SDimitry Andric             (unsigned long long)m_host_address, (unsigned long long)m_size,
11430b57cec5SDimitry Andric             (unsigned long long)m_process_address, (unsigned)m_alignment,
11440b57cec5SDimitry Andric             (unsigned)m_section_id, m_name.c_str());
11450b57cec5SDimitry Andric }
11460b57cec5SDimitry Andric 
GetByteOrder() const11470b57cec5SDimitry Andric lldb::ByteOrder IRExecutionUnit::GetByteOrder() const {
11480b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetBestExecutionContextScope());
11490b57cec5SDimitry Andric   return exe_ctx.GetByteOrder();
11500b57cec5SDimitry Andric }
11510b57cec5SDimitry Andric 
GetAddressByteSize() const11520b57cec5SDimitry Andric uint32_t IRExecutionUnit::GetAddressByteSize() const {
11530b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetBestExecutionContextScope());
11540b57cec5SDimitry Andric   return exe_ctx.GetAddressByteSize();
11550b57cec5SDimitry Andric }
11560b57cec5SDimitry Andric 
PopulateSymtab(lldb_private::ObjectFile * obj_file,lldb_private::Symtab & symtab)11570b57cec5SDimitry Andric void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file,
11580b57cec5SDimitry Andric                                      lldb_private::Symtab &symtab) {
11590b57cec5SDimitry Andric   // No symbols yet...
11600b57cec5SDimitry Andric }
11610b57cec5SDimitry Andric 
PopulateSectionList(lldb_private::ObjectFile * obj_file,lldb_private::SectionList & section_list)11620b57cec5SDimitry Andric void IRExecutionUnit::PopulateSectionList(
11630b57cec5SDimitry Andric     lldb_private::ObjectFile *obj_file,
11640b57cec5SDimitry Andric     lldb_private::SectionList &section_list) {
11650b57cec5SDimitry Andric   for (AllocationRecord &record : m_records) {
11660b57cec5SDimitry Andric     if (record.m_size > 0) {
11670b57cec5SDimitry Andric       lldb::SectionSP section_sp(new lldb_private::Section(
11680b57cec5SDimitry Andric           obj_file->GetModule(), obj_file, record.m_section_id,
11690b57cec5SDimitry Andric           ConstString(record.m_name), record.m_sect_type,
11700b57cec5SDimitry Andric           record.m_process_address, record.m_size,
11710b57cec5SDimitry Andric           record.m_host_address, // file_offset (which is the host address for
11720b57cec5SDimitry Andric                                  // the data)
11730b57cec5SDimitry Andric           record.m_size,         // file_size
11740b57cec5SDimitry Andric           0,
11750b57cec5SDimitry Andric           record.m_permissions)); // flags
11760b57cec5SDimitry Andric       section_list.AddSection(section_sp);
11770b57cec5SDimitry Andric     }
11780b57cec5SDimitry Andric   }
11790b57cec5SDimitry Andric }
11800b57cec5SDimitry Andric 
GetArchitecture()11810b57cec5SDimitry Andric ArchSpec IRExecutionUnit::GetArchitecture() {
11820b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetBestExecutionContextScope());
11830b57cec5SDimitry Andric   if(Target *target = exe_ctx.GetTargetPtr())
11840b57cec5SDimitry Andric     return target->GetArchitecture();
11850b57cec5SDimitry Andric   return ArchSpec();
11860b57cec5SDimitry Andric }
11870b57cec5SDimitry Andric 
GetJITModule()11880b57cec5SDimitry Andric lldb::ModuleSP IRExecutionUnit::GetJITModule() {
11890b57cec5SDimitry Andric   ExecutionContext exe_ctx(GetBestExecutionContextScope());
11900b57cec5SDimitry Andric   Target *target = exe_ctx.GetTargetPtr();
11910b57cec5SDimitry Andric   if (!target)
11920b57cec5SDimitry Andric     return nullptr;
11930b57cec5SDimitry Andric 
11940b57cec5SDimitry Andric   auto Delegate = std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(
11950b57cec5SDimitry Andric       shared_from_this());
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   lldb::ModuleSP jit_module_sp =
11980b57cec5SDimitry Andric       lldb_private::Module::CreateModuleFromObjectFile<ObjectFileJIT>(Delegate);
11990b57cec5SDimitry Andric   if (!jit_module_sp)
12000b57cec5SDimitry Andric     return nullptr;
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   bool changed = false;
12030b57cec5SDimitry Andric   jit_module_sp->SetLoadAddress(*target, 0, true, changed);
12040b57cec5SDimitry Andric   return jit_module_sp;
12050b57cec5SDimitry Andric }
1206