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 §ion_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