1dda28197Spatrick //===-- IRExecutionUnit.cpp -----------------------------------------------===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick
9061da546Spatrick #include "llvm/ExecutionEngine/ExecutionEngine.h"
10061da546Spatrick #include "llvm/ExecutionEngine/ObjectCache.h"
11061da546Spatrick #include "llvm/IR/Constants.h"
12be691f3bSpatrick #include "llvm/IR/DiagnosticHandler.h"
13be691f3bSpatrick #include "llvm/IR/DiagnosticInfo.h"
14061da546Spatrick #include "llvm/IR/LLVMContext.h"
15061da546Spatrick #include "llvm/IR/Module.h"
16061da546Spatrick #include "llvm/Support/SourceMgr.h"
17061da546Spatrick #include "llvm/Support/raw_ostream.h"
18061da546Spatrick
19061da546Spatrick #include "lldb/Core/Debugger.h"
20061da546Spatrick #include "lldb/Core/Disassembler.h"
21061da546Spatrick #include "lldb/Core/Module.h"
22061da546Spatrick #include "lldb/Core/Section.h"
23061da546Spatrick #include "lldb/Expression/IRExecutionUnit.h"
24*f6aab3d8Srobert #include "lldb/Host/HostInfo.h"
25061da546Spatrick #include "lldb/Symbol/CompileUnit.h"
26061da546Spatrick #include "lldb/Symbol/SymbolContext.h"
27061da546Spatrick #include "lldb/Symbol/SymbolFile.h"
28061da546Spatrick #include "lldb/Symbol/SymbolVendor.h"
29061da546Spatrick #include "lldb/Target/ExecutionContext.h"
30*f6aab3d8Srobert #include "lldb/Target/Language.h"
31061da546Spatrick #include "lldb/Target/LanguageRuntime.h"
32061da546Spatrick #include "lldb/Target/Target.h"
33061da546Spatrick #include "lldb/Utility/DataBufferHeap.h"
34061da546Spatrick #include "lldb/Utility/DataExtractor.h"
35061da546Spatrick #include "lldb/Utility/LLDBAssert.h"
36*f6aab3d8Srobert #include "lldb/Utility/LLDBLog.h"
37061da546Spatrick #include "lldb/Utility/Log.h"
38061da546Spatrick
39061da546Spatrick #include "lldb/../../source/Plugins/ObjectFile/JIT/ObjectFileJIT.h"
40*f6aab3d8Srobert #include <optional>
41061da546Spatrick
42061da546Spatrick using namespace lldb_private;
43061da546Spatrick
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)44061da546Spatrick IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_up,
45061da546Spatrick std::unique_ptr<llvm::Module> &module_up,
46061da546Spatrick ConstString &name,
47061da546Spatrick const lldb::TargetSP &target_sp,
48061da546Spatrick const SymbolContext &sym_ctx,
49061da546Spatrick std::vector<std::string> &cpu_features)
50061da546Spatrick : IRMemoryMap(target_sp), m_context_up(context_up.release()),
51061da546Spatrick m_module_up(module_up.release()), m_module(m_module_up.get()),
52061da546Spatrick m_cpu_features(cpu_features), m_name(name), m_sym_ctx(sym_ctx),
53061da546Spatrick m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS),
54061da546Spatrick m_function_end_load_addr(LLDB_INVALID_ADDRESS),
55061da546Spatrick m_reported_allocations(false) {}
56061da546Spatrick
WriteNow(const uint8_t * bytes,size_t size,Status & error)57061da546Spatrick lldb::addr_t IRExecutionUnit::WriteNow(const uint8_t *bytes, size_t size,
58061da546Spatrick Status &error) {
59061da546Spatrick const bool zero_memory = false;
60061da546Spatrick lldb::addr_t allocation_process_addr =
61061da546Spatrick Malloc(size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable,
62061da546Spatrick eAllocationPolicyMirror, zero_memory, error);
63061da546Spatrick
64061da546Spatrick if (!error.Success())
65061da546Spatrick return LLDB_INVALID_ADDRESS;
66061da546Spatrick
67061da546Spatrick WriteMemory(allocation_process_addr, bytes, size, error);
68061da546Spatrick
69061da546Spatrick if (!error.Success()) {
70061da546Spatrick Status err;
71061da546Spatrick Free(allocation_process_addr, err);
72061da546Spatrick
73061da546Spatrick return LLDB_INVALID_ADDRESS;
74061da546Spatrick }
75061da546Spatrick
76*f6aab3d8Srobert if (Log *log = GetLog(LLDBLog::Expressions)) {
77061da546Spatrick DataBufferHeap my_buffer(size, 0);
78061da546Spatrick Status err;
79061da546Spatrick ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
80061da546Spatrick
81061da546Spatrick if (err.Success()) {
82061da546Spatrick DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(),
83061da546Spatrick lldb::eByteOrderBig, 8);
84061da546Spatrick my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(),
85061da546Spatrick allocation_process_addr, 16,
86061da546Spatrick DataExtractor::TypeUInt8);
87061da546Spatrick }
88061da546Spatrick }
89061da546Spatrick
90061da546Spatrick return allocation_process_addr;
91061da546Spatrick }
92061da546Spatrick
FreeNow(lldb::addr_t allocation)93061da546Spatrick void IRExecutionUnit::FreeNow(lldb::addr_t allocation) {
94061da546Spatrick if (allocation == LLDB_INVALID_ADDRESS)
95061da546Spatrick return;
96061da546Spatrick
97061da546Spatrick Status err;
98061da546Spatrick
99061da546Spatrick Free(allocation, err);
100061da546Spatrick }
101061da546Spatrick
DisassembleFunction(Stream & stream,lldb::ProcessSP & process_wp)102061da546Spatrick Status IRExecutionUnit::DisassembleFunction(Stream &stream,
103061da546Spatrick lldb::ProcessSP &process_wp) {
104*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
105061da546Spatrick
106061da546Spatrick ExecutionContext exe_ctx(process_wp);
107061da546Spatrick
108061da546Spatrick Status ret;
109061da546Spatrick
110061da546Spatrick ret.Clear();
111061da546Spatrick
112061da546Spatrick lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
113061da546Spatrick lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
114061da546Spatrick
115061da546Spatrick for (JittedFunction &function : m_jitted_functions) {
116061da546Spatrick if (function.m_name == m_name) {
117061da546Spatrick func_local_addr = function.m_local_addr;
118061da546Spatrick func_remote_addr = function.m_remote_addr;
119061da546Spatrick }
120061da546Spatrick }
121061da546Spatrick
122061da546Spatrick if (func_local_addr == LLDB_INVALID_ADDRESS) {
123061da546Spatrick ret.SetErrorToGenericError();
124061da546Spatrick ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly",
125061da546Spatrick m_name.AsCString());
126061da546Spatrick return ret;
127061da546Spatrick }
128061da546Spatrick
129061da546Spatrick LLDB_LOGF(log,
130061da546Spatrick "Found function, has local address 0x%" PRIx64
131061da546Spatrick " and remote address 0x%" PRIx64,
132061da546Spatrick (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
133061da546Spatrick
134061da546Spatrick std::pair<lldb::addr_t, lldb::addr_t> func_range;
135061da546Spatrick
136061da546Spatrick func_range = GetRemoteRangeForLocal(func_local_addr);
137061da546Spatrick
138061da546Spatrick if (func_range.first == 0 && func_range.second == 0) {
139061da546Spatrick ret.SetErrorToGenericError();
140061da546Spatrick ret.SetErrorStringWithFormat("Couldn't find code range for function %s",
141061da546Spatrick m_name.AsCString());
142061da546Spatrick return ret;
143061da546Spatrick }
144061da546Spatrick
145061da546Spatrick LLDB_LOGF(log, "Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]",
146061da546Spatrick func_range.first, func_range.second);
147061da546Spatrick
148061da546Spatrick Target *target = exe_ctx.GetTargetPtr();
149061da546Spatrick if (!target) {
150061da546Spatrick ret.SetErrorToGenericError();
151061da546Spatrick ret.SetErrorString("Couldn't find the target");
152061da546Spatrick return ret;
153061da546Spatrick }
154061da546Spatrick
155*f6aab3d8Srobert lldb::WritableDataBufferSP buffer_sp(
156*f6aab3d8Srobert new DataBufferHeap(func_range.second, 0));
157061da546Spatrick
158061da546Spatrick Process *process = exe_ctx.GetProcessPtr();
159061da546Spatrick Status err;
160061da546Spatrick process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(),
161061da546Spatrick buffer_sp->GetByteSize(), err);
162061da546Spatrick
163061da546Spatrick if (!err.Success()) {
164061da546Spatrick ret.SetErrorToGenericError();
165061da546Spatrick ret.SetErrorStringWithFormat("Couldn't read from process: %s",
166061da546Spatrick err.AsCString("unknown error"));
167061da546Spatrick return ret;
168061da546Spatrick }
169061da546Spatrick
170061da546Spatrick ArchSpec arch(target->GetArchitecture());
171061da546Spatrick
172061da546Spatrick const char *plugin_name = nullptr;
173061da546Spatrick const char *flavor_string = nullptr;
174061da546Spatrick lldb::DisassemblerSP disassembler_sp =
175061da546Spatrick Disassembler::FindPlugin(arch, flavor_string, plugin_name);
176061da546Spatrick
177061da546Spatrick if (!disassembler_sp) {
178061da546Spatrick ret.SetErrorToGenericError();
179061da546Spatrick ret.SetErrorStringWithFormat(
180061da546Spatrick "Unable to find disassembler plug-in for %s architecture.",
181061da546Spatrick arch.GetArchitectureName());
182061da546Spatrick return ret;
183061da546Spatrick }
184061da546Spatrick
185061da546Spatrick if (!process) {
186061da546Spatrick ret.SetErrorToGenericError();
187061da546Spatrick ret.SetErrorString("Couldn't find the process");
188061da546Spatrick return ret;
189061da546Spatrick }
190061da546Spatrick
191061da546Spatrick DataExtractor extractor(buffer_sp, process->GetByteOrder(),
192061da546Spatrick target->GetArchitecture().GetAddressByteSize());
193061da546Spatrick
194061da546Spatrick if (log) {
195061da546Spatrick LLDB_LOGF(log, "Function data has contents:");
196061da546Spatrick extractor.PutToLog(log, 0, extractor.GetByteSize(), func_remote_addr, 16,
197061da546Spatrick DataExtractor::TypeUInt8);
198061da546Spatrick }
199061da546Spatrick
200061da546Spatrick disassembler_sp->DecodeInstructions(Address(func_remote_addr), extractor, 0,
201061da546Spatrick UINT32_MAX, false, false);
202061da546Spatrick
203061da546Spatrick InstructionList &instruction_list = disassembler_sp->GetInstructionList();
204*f6aab3d8Srobert instruction_list.Dump(&stream, true, true, /*show_control_flow_kind=*/true,
205*f6aab3d8Srobert &exe_ctx);
206*f6aab3d8Srobert
207061da546Spatrick return ret;
208061da546Spatrick }
209061da546Spatrick
210be691f3bSpatrick namespace {
211be691f3bSpatrick struct IRExecDiagnosticHandler : public llvm::DiagnosticHandler {
212be691f3bSpatrick Status *err;
IRExecDiagnosticHandler__anon34e0a8320111::IRExecDiagnosticHandler213be691f3bSpatrick IRExecDiagnosticHandler(Status *err) : err(err) {}
handleDiagnostics__anon34e0a8320111::IRExecDiagnosticHandler214be691f3bSpatrick bool handleDiagnostics(const llvm::DiagnosticInfo &DI) override {
215be691f3bSpatrick if (DI.getKind() == llvm::DK_SrcMgr) {
216be691f3bSpatrick const auto &DISM = llvm::cast<llvm::DiagnosticInfoSrcMgr>(DI);
217061da546Spatrick if (err && err->Success()) {
218061da546Spatrick err->SetErrorToGenericError();
219be691f3bSpatrick err->SetErrorStringWithFormat(
220be691f3bSpatrick "Inline assembly error: %s",
221be691f3bSpatrick DISM.getSMDiag().getMessage().str().c_str());
222061da546Spatrick }
223be691f3bSpatrick return true;
224061da546Spatrick }
225061da546Spatrick
226be691f3bSpatrick return false;
227be691f3bSpatrick }
228be691f3bSpatrick };
229be691f3bSpatrick } // namespace
230be691f3bSpatrick
ReportSymbolLookupError(ConstString name)231061da546Spatrick void IRExecutionUnit::ReportSymbolLookupError(ConstString name) {
232061da546Spatrick m_failed_lookups.push_back(name);
233061da546Spatrick }
234061da546Spatrick
GetRunnableInfo(Status & error,lldb::addr_t & func_addr,lldb::addr_t & func_end)235061da546Spatrick void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr,
236061da546Spatrick lldb::addr_t &func_end) {
237061da546Spatrick lldb::ProcessSP process_sp(GetProcessWP().lock());
238061da546Spatrick
239061da546Spatrick static std::recursive_mutex s_runnable_info_mutex;
240061da546Spatrick
241061da546Spatrick func_addr = LLDB_INVALID_ADDRESS;
242061da546Spatrick func_end = LLDB_INVALID_ADDRESS;
243061da546Spatrick
244061da546Spatrick if (!process_sp) {
245061da546Spatrick error.SetErrorToGenericError();
246061da546Spatrick error.SetErrorString("Couldn't write the JIT compiled code into the "
247061da546Spatrick "process because the process is invalid");
248061da546Spatrick return;
249061da546Spatrick }
250061da546Spatrick
251061da546Spatrick if (m_did_jit) {
252061da546Spatrick func_addr = m_function_load_addr;
253061da546Spatrick func_end = m_function_end_load_addr;
254061da546Spatrick
255061da546Spatrick return;
256061da546Spatrick };
257061da546Spatrick
258061da546Spatrick std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex);
259061da546Spatrick
260061da546Spatrick m_did_jit = true;
261061da546Spatrick
262*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
263061da546Spatrick
264061da546Spatrick std::string error_string;
265061da546Spatrick
266061da546Spatrick if (log) {
267061da546Spatrick std::string s;
268061da546Spatrick llvm::raw_string_ostream oss(s);
269061da546Spatrick
270061da546Spatrick m_module->print(oss, nullptr);
271061da546Spatrick
272061da546Spatrick oss.flush();
273061da546Spatrick
274061da546Spatrick LLDB_LOGF(log, "Module being sent to JIT: \n%s", s.c_str());
275061da546Spatrick }
276061da546Spatrick
277be691f3bSpatrick m_module_up->getContext().setDiagnosticHandler(
278be691f3bSpatrick std::make_unique<IRExecDiagnosticHandler>(&error));
279061da546Spatrick
280061da546Spatrick llvm::EngineBuilder builder(std::move(m_module_up));
281061da546Spatrick llvm::Triple triple(m_module->getTargetTriple());
282061da546Spatrick
283061da546Spatrick builder.setEngineKind(llvm::EngineKind::JIT)
284061da546Spatrick .setErrorStr(&error_string)
285dda28197Spatrick .setRelocationModel(triple.isOSBinFormatMachO() ? llvm::Reloc::PIC_
286061da546Spatrick : llvm::Reloc::Static)
287dda28197Spatrick .setMCJITMemoryManager(std::make_unique<MemoryManager>(*this))
288061da546Spatrick .setOptLevel(llvm::CodeGenOpt::Less);
289061da546Spatrick
290061da546Spatrick llvm::StringRef mArch;
291061da546Spatrick llvm::StringRef mCPU;
292061da546Spatrick llvm::SmallVector<std::string, 0> mAttrs;
293061da546Spatrick
294061da546Spatrick for (std::string &feature : m_cpu_features)
295061da546Spatrick mAttrs.push_back(feature);
296061da546Spatrick
297061da546Spatrick llvm::TargetMachine *target_machine =
298061da546Spatrick builder.selectTarget(triple, mArch, mCPU, mAttrs);
299061da546Spatrick
300061da546Spatrick m_execution_engine_up.reset(builder.create(target_machine));
301061da546Spatrick
302061da546Spatrick if (!m_execution_engine_up) {
303061da546Spatrick error.SetErrorToGenericError();
304061da546Spatrick error.SetErrorStringWithFormat("Couldn't JIT the function: %s",
305061da546Spatrick error_string.c_str());
306061da546Spatrick return;
307061da546Spatrick }
308061da546Spatrick
309061da546Spatrick m_strip_underscore =
310061da546Spatrick (m_execution_engine_up->getDataLayout().getGlobalPrefix() == '_');
311061da546Spatrick
312061da546Spatrick class ObjectDumper : public llvm::ObjectCache {
313061da546Spatrick public:
314*f6aab3d8Srobert ObjectDumper(FileSpec output_dir) : m_out_dir(output_dir) {}
315061da546Spatrick void notifyObjectCompiled(const llvm::Module *module,
316061da546Spatrick llvm::MemoryBufferRef object) override {
317061da546Spatrick int fd = 0;
318061da546Spatrick llvm::SmallVector<char, 256> result_path;
319061da546Spatrick std::string object_name_model =
320061da546Spatrick "jit-object-" + module->getModuleIdentifier() + "-%%%.o";
321*f6aab3d8Srobert FileSpec model_spec
322*f6aab3d8Srobert = m_out_dir.CopyByAppendingPathComponent(object_name_model);
323*f6aab3d8Srobert std::string model_path = model_spec.GetPath();
324*f6aab3d8Srobert
325*f6aab3d8Srobert std::error_code result
326*f6aab3d8Srobert = llvm::sys::fs::createUniqueFile(model_path, fd, result_path);
327*f6aab3d8Srobert if (!result) {
328061da546Spatrick llvm::raw_fd_ostream fds(fd, true);
329061da546Spatrick fds.write(object.getBufferStart(), object.getBufferSize());
330061da546Spatrick }
331*f6aab3d8Srobert }
332061da546Spatrick std::unique_ptr<llvm::MemoryBuffer>
333061da546Spatrick getObject(const llvm::Module *module) override {
334061da546Spatrick // Return nothing - we're just abusing the object-cache mechanism to dump
335061da546Spatrick // objects.
336061da546Spatrick return nullptr;
337061da546Spatrick }
338*f6aab3d8Srobert private:
339*f6aab3d8Srobert FileSpec m_out_dir;
340061da546Spatrick };
341061da546Spatrick
342*f6aab3d8Srobert FileSpec save_objects_dir = process_sp->GetTarget().GetSaveJITObjectsDir();
343*f6aab3d8Srobert if (save_objects_dir) {
344*f6aab3d8Srobert m_object_cache_up = std::make_unique<ObjectDumper>(save_objects_dir);
345061da546Spatrick m_execution_engine_up->setObjectCache(m_object_cache_up.get());
346061da546Spatrick }
347061da546Spatrick
348061da546Spatrick // Make sure we see all sections, including ones that don't have
349061da546Spatrick // relocations...
350061da546Spatrick m_execution_engine_up->setProcessAllSections(true);
351061da546Spatrick
352061da546Spatrick m_execution_engine_up->DisableLazyCompilation();
353061da546Spatrick
354061da546Spatrick for (llvm::Function &function : *m_module) {
355061da546Spatrick if (function.isDeclaration() || function.hasPrivateLinkage())
356061da546Spatrick continue;
357061da546Spatrick
358be691f3bSpatrick const bool external = !function.hasLocalLinkage();
359061da546Spatrick
360061da546Spatrick void *fun_ptr = m_execution_engine_up->getPointerToFunction(&function);
361061da546Spatrick
362061da546Spatrick if (!error.Success()) {
363061da546Spatrick // We got an error through our callback!
364061da546Spatrick return;
365061da546Spatrick }
366061da546Spatrick
367061da546Spatrick if (!fun_ptr) {
368061da546Spatrick error.SetErrorToGenericError();
369061da546Spatrick error.SetErrorStringWithFormat(
370061da546Spatrick "'%s' was in the JITted module but wasn't lowered",
371061da546Spatrick function.getName().str().c_str());
372061da546Spatrick return;
373061da546Spatrick }
374061da546Spatrick m_jitted_functions.push_back(JittedFunction(
375061da546Spatrick function.getName().str().c_str(), external, reinterpret_cast<uintptr_t>(fun_ptr)));
376061da546Spatrick }
377061da546Spatrick
378061da546Spatrick CommitAllocations(process_sp);
379061da546Spatrick ReportAllocations(*m_execution_engine_up);
380061da546Spatrick
381061da546Spatrick // We have to do this after calling ReportAllocations because for the MCJIT,
382061da546Spatrick // getGlobalValueAddress will cause the JIT to perform all relocations. That
383061da546Spatrick // can only be done once, and has to happen after we do the remapping from
384061da546Spatrick // local -> remote. That means we don't know the local address of the
385061da546Spatrick // Variables, but we don't need that for anything, so that's okay.
386061da546Spatrick
387061da546Spatrick std::function<void(llvm::GlobalValue &)> RegisterOneValue = [this](
388061da546Spatrick llvm::GlobalValue &val) {
389061da546Spatrick if (val.hasExternalLinkage() && !val.isDeclaration()) {
390061da546Spatrick uint64_t var_ptr_addr =
391061da546Spatrick m_execution_engine_up->getGlobalValueAddress(val.getName().str());
392061da546Spatrick
393061da546Spatrick lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr);
394061da546Spatrick
395061da546Spatrick // This is a really unfortunae API that sometimes returns local addresses
396061da546Spatrick // and sometimes returns remote addresses, based on whether the variable
397061da546Spatrick // was relocated during ReportAllocations or not.
398061da546Spatrick
399061da546Spatrick if (remote_addr == LLDB_INVALID_ADDRESS) {
400061da546Spatrick remote_addr = var_ptr_addr;
401061da546Spatrick }
402061da546Spatrick
403061da546Spatrick if (var_ptr_addr != 0)
404061da546Spatrick m_jitted_global_variables.push_back(JittedGlobalVariable(
405061da546Spatrick val.getName().str().c_str(), LLDB_INVALID_ADDRESS, remote_addr));
406061da546Spatrick }
407061da546Spatrick };
408061da546Spatrick
409061da546Spatrick for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) {
410061da546Spatrick RegisterOneValue(global_var);
411061da546Spatrick }
412061da546Spatrick
413061da546Spatrick for (llvm::GlobalAlias &global_alias : m_module->getAliasList()) {
414061da546Spatrick RegisterOneValue(global_alias);
415061da546Spatrick }
416061da546Spatrick
417061da546Spatrick WriteData(process_sp);
418061da546Spatrick
419061da546Spatrick if (m_failed_lookups.size()) {
420061da546Spatrick StreamString ss;
421061da546Spatrick
422061da546Spatrick ss.PutCString("Couldn't lookup symbols:\n");
423061da546Spatrick
424061da546Spatrick bool emitNewLine = false;
425061da546Spatrick
426061da546Spatrick for (ConstString failed_lookup : m_failed_lookups) {
427061da546Spatrick if (emitNewLine)
428061da546Spatrick ss.PutCString("\n");
429061da546Spatrick emitNewLine = true;
430061da546Spatrick ss.PutCString(" ");
431dda28197Spatrick ss.PutCString(Mangled(failed_lookup).GetDemangledName().GetStringRef());
432061da546Spatrick }
433061da546Spatrick
434061da546Spatrick m_failed_lookups.clear();
435061da546Spatrick
436061da546Spatrick error.SetErrorString(ss.GetString());
437061da546Spatrick
438061da546Spatrick return;
439061da546Spatrick }
440061da546Spatrick
441061da546Spatrick m_function_load_addr = LLDB_INVALID_ADDRESS;
442061da546Spatrick m_function_end_load_addr = LLDB_INVALID_ADDRESS;
443061da546Spatrick
444061da546Spatrick for (JittedFunction &jitted_function : m_jitted_functions) {
445061da546Spatrick jitted_function.m_remote_addr =
446061da546Spatrick GetRemoteAddressForLocal(jitted_function.m_local_addr);
447061da546Spatrick
448061da546Spatrick if (!m_name.IsEmpty() && jitted_function.m_name == m_name) {
449061da546Spatrick AddrRange func_range =
450061da546Spatrick GetRemoteRangeForLocal(jitted_function.m_local_addr);
451061da546Spatrick m_function_end_load_addr = func_range.first + func_range.second;
452061da546Spatrick m_function_load_addr = jitted_function.m_remote_addr;
453061da546Spatrick }
454061da546Spatrick }
455061da546Spatrick
456061da546Spatrick if (log) {
457061da546Spatrick LLDB_LOGF(log, "Code can be run in the target.");
458061da546Spatrick
459061da546Spatrick StreamString disassembly_stream;
460061da546Spatrick
461061da546Spatrick Status err = DisassembleFunction(disassembly_stream, process_sp);
462061da546Spatrick
463061da546Spatrick if (!err.Success()) {
464061da546Spatrick LLDB_LOGF(log, "Couldn't disassemble function : %s",
465061da546Spatrick err.AsCString("unknown error"));
466061da546Spatrick } else {
467061da546Spatrick LLDB_LOGF(log, "Function disassembly:\n%s", disassembly_stream.GetData());
468061da546Spatrick }
469061da546Spatrick
470061da546Spatrick LLDB_LOGF(log, "Sections: ");
471061da546Spatrick for (AllocationRecord &record : m_records) {
472061da546Spatrick if (record.m_process_address != LLDB_INVALID_ADDRESS) {
473061da546Spatrick record.dump(log);
474061da546Spatrick
475061da546Spatrick DataBufferHeap my_buffer(record.m_size, 0);
476061da546Spatrick Status err;
477061da546Spatrick ReadMemory(my_buffer.GetBytes(), record.m_process_address,
478061da546Spatrick record.m_size, err);
479061da546Spatrick
480061da546Spatrick if (err.Success()) {
481061da546Spatrick DataExtractor my_extractor(my_buffer.GetBytes(),
482061da546Spatrick my_buffer.GetByteSize(),
483061da546Spatrick lldb::eByteOrderBig, 8);
484061da546Spatrick my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(),
485061da546Spatrick record.m_process_address, 16,
486061da546Spatrick DataExtractor::TypeUInt8);
487061da546Spatrick }
488061da546Spatrick } else {
489061da546Spatrick record.dump(log);
490061da546Spatrick
491061da546Spatrick DataExtractor my_extractor((const void *)record.m_host_address,
492061da546Spatrick record.m_size, lldb::eByteOrderBig, 8);
493061da546Spatrick my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16,
494061da546Spatrick DataExtractor::TypeUInt8);
495061da546Spatrick }
496061da546Spatrick }
497061da546Spatrick }
498061da546Spatrick
499061da546Spatrick func_addr = m_function_load_addr;
500061da546Spatrick func_end = m_function_end_load_addr;
501061da546Spatrick }
502061da546Spatrick
~IRExecutionUnit()503061da546Spatrick IRExecutionUnit::~IRExecutionUnit() {
504061da546Spatrick m_module_up.reset();
505061da546Spatrick m_execution_engine_up.reset();
506061da546Spatrick m_context_up.reset();
507061da546Spatrick }
508061da546Spatrick
MemoryManager(IRExecutionUnit & parent)509061da546Spatrick IRExecutionUnit::MemoryManager::MemoryManager(IRExecutionUnit &parent)
510061da546Spatrick : m_default_mm_up(new llvm::SectionMemoryManager()), m_parent(parent) {}
511061da546Spatrick
512be691f3bSpatrick IRExecutionUnit::MemoryManager::~MemoryManager() = default;
513061da546Spatrick
GetSectionTypeFromSectionName(const llvm::StringRef & name,IRExecutionUnit::AllocationKind alloc_kind)514061da546Spatrick lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName(
515061da546Spatrick const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) {
516061da546Spatrick lldb::SectionType sect_type = lldb::eSectionTypeCode;
517061da546Spatrick switch (alloc_kind) {
518061da546Spatrick case AllocationKind::Stub:
519061da546Spatrick sect_type = lldb::eSectionTypeCode;
520061da546Spatrick break;
521061da546Spatrick case AllocationKind::Code:
522061da546Spatrick sect_type = lldb::eSectionTypeCode;
523061da546Spatrick break;
524061da546Spatrick case AllocationKind::Data:
525061da546Spatrick sect_type = lldb::eSectionTypeData;
526061da546Spatrick break;
527061da546Spatrick case AllocationKind::Global:
528061da546Spatrick sect_type = lldb::eSectionTypeData;
529061da546Spatrick break;
530061da546Spatrick case AllocationKind::Bytes:
531061da546Spatrick sect_type = lldb::eSectionTypeOther;
532061da546Spatrick break;
533061da546Spatrick }
534061da546Spatrick
535061da546Spatrick if (!name.empty()) {
536061da546Spatrick if (name.equals("__text") || name.equals(".text"))
537061da546Spatrick sect_type = lldb::eSectionTypeCode;
538061da546Spatrick else if (name.equals("__data") || name.equals(".data"))
539061da546Spatrick sect_type = lldb::eSectionTypeCode;
540061da546Spatrick else if (name.startswith("__debug_") || name.startswith(".debug_")) {
541061da546Spatrick const uint32_t name_idx = name[0] == '_' ? 8 : 7;
542061da546Spatrick llvm::StringRef dwarf_name(name.substr(name_idx));
543061da546Spatrick switch (dwarf_name[0]) {
544061da546Spatrick case 'a':
545061da546Spatrick if (dwarf_name.equals("abbrev"))
546061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugAbbrev;
547061da546Spatrick else if (dwarf_name.equals("aranges"))
548061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugAranges;
549061da546Spatrick else if (dwarf_name.equals("addr"))
550061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugAddr;
551061da546Spatrick break;
552061da546Spatrick
553061da546Spatrick case 'f':
554061da546Spatrick if (dwarf_name.equals("frame"))
555061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugFrame;
556061da546Spatrick break;
557061da546Spatrick
558061da546Spatrick case 'i':
559061da546Spatrick if (dwarf_name.equals("info"))
560061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugInfo;
561061da546Spatrick break;
562061da546Spatrick
563061da546Spatrick case 'l':
564061da546Spatrick if (dwarf_name.equals("line"))
565061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugLine;
566061da546Spatrick else if (dwarf_name.equals("loc"))
567061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugLoc;
568061da546Spatrick else if (dwarf_name.equals("loclists"))
569061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugLocLists;
570061da546Spatrick break;
571061da546Spatrick
572061da546Spatrick case 'm':
573061da546Spatrick if (dwarf_name.equals("macinfo"))
574061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugMacInfo;
575061da546Spatrick break;
576061da546Spatrick
577061da546Spatrick case 'p':
578061da546Spatrick if (dwarf_name.equals("pubnames"))
579061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugPubNames;
580061da546Spatrick else if (dwarf_name.equals("pubtypes"))
581061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugPubTypes;
582061da546Spatrick break;
583061da546Spatrick
584061da546Spatrick case 's':
585061da546Spatrick if (dwarf_name.equals("str"))
586061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugStr;
587061da546Spatrick else if (dwarf_name.equals("str_offsets"))
588061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugStrOffsets;
589061da546Spatrick break;
590061da546Spatrick
591061da546Spatrick case 'r':
592061da546Spatrick if (dwarf_name.equals("ranges"))
593061da546Spatrick sect_type = lldb::eSectionTypeDWARFDebugRanges;
594061da546Spatrick break;
595061da546Spatrick
596061da546Spatrick default:
597061da546Spatrick break;
598061da546Spatrick }
599061da546Spatrick } else if (name.startswith("__apple_") || name.startswith(".apple_"))
600061da546Spatrick sect_type = lldb::eSectionTypeInvalid;
601061da546Spatrick else if (name.equals("__objc_imageinfo"))
602061da546Spatrick sect_type = lldb::eSectionTypeOther;
603061da546Spatrick }
604061da546Spatrick return sect_type;
605061da546Spatrick }
606061da546Spatrick
allocateCodeSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,llvm::StringRef SectionName)607061da546Spatrick uint8_t *IRExecutionUnit::MemoryManager::allocateCodeSection(
608061da546Spatrick uintptr_t Size, unsigned Alignment, unsigned SectionID,
609061da546Spatrick llvm::StringRef SectionName) {
610*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
611061da546Spatrick
612061da546Spatrick uint8_t *return_value = m_default_mm_up->allocateCodeSection(
613061da546Spatrick Size, Alignment, SectionID, SectionName);
614061da546Spatrick
615061da546Spatrick m_parent.m_records.push_back(AllocationRecord(
616061da546Spatrick (uintptr_t)return_value,
617061da546Spatrick lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
618061da546Spatrick GetSectionTypeFromSectionName(SectionName, AllocationKind::Code), Size,
619061da546Spatrick Alignment, SectionID, SectionName.str().c_str()));
620061da546Spatrick
621061da546Spatrick LLDB_LOGF(log,
622061da546Spatrick "IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64
623061da546Spatrick ", Alignment=%u, SectionID=%u) = %p",
624061da546Spatrick (uint64_t)Size, Alignment, SectionID, (void *)return_value);
625061da546Spatrick
626061da546Spatrick if (m_parent.m_reported_allocations) {
627061da546Spatrick Status err;
628061da546Spatrick lldb::ProcessSP process_sp =
629061da546Spatrick m_parent.GetBestExecutionContextScope()->CalculateProcess();
630061da546Spatrick
631061da546Spatrick m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
632061da546Spatrick }
633061da546Spatrick
634061da546Spatrick return return_value;
635061da546Spatrick }
636061da546Spatrick
allocateDataSection(uintptr_t Size,unsigned Alignment,unsigned SectionID,llvm::StringRef SectionName,bool IsReadOnly)637061da546Spatrick uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection(
638061da546Spatrick uintptr_t Size, unsigned Alignment, unsigned SectionID,
639061da546Spatrick llvm::StringRef SectionName, bool IsReadOnly) {
640*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
641061da546Spatrick
642061da546Spatrick uint8_t *return_value = m_default_mm_up->allocateDataSection(
643061da546Spatrick Size, Alignment, SectionID, SectionName, IsReadOnly);
644061da546Spatrick
645061da546Spatrick uint32_t permissions = lldb::ePermissionsReadable;
646061da546Spatrick if (!IsReadOnly)
647061da546Spatrick permissions |= lldb::ePermissionsWritable;
648061da546Spatrick m_parent.m_records.push_back(AllocationRecord(
649061da546Spatrick (uintptr_t)return_value, permissions,
650061da546Spatrick GetSectionTypeFromSectionName(SectionName, AllocationKind::Data), Size,
651061da546Spatrick Alignment, SectionID, SectionName.str().c_str()));
652061da546Spatrick LLDB_LOGF(log,
653061da546Spatrick "IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64
654061da546Spatrick ", Alignment=%u, SectionID=%u) = %p",
655061da546Spatrick (uint64_t)Size, Alignment, SectionID, (void *)return_value);
656061da546Spatrick
657061da546Spatrick if (m_parent.m_reported_allocations) {
658061da546Spatrick Status err;
659061da546Spatrick lldb::ProcessSP process_sp =
660061da546Spatrick m_parent.GetBestExecutionContextScope()->CalculateProcess();
661061da546Spatrick
662061da546Spatrick m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back());
663061da546Spatrick }
664061da546Spatrick
665061da546Spatrick return return_value;
666061da546Spatrick }
667061da546Spatrick
CollectCandidateCNames(std::vector<ConstString> & C_names,ConstString name)668*f6aab3d8Srobert void IRExecutionUnit::CollectCandidateCNames(std::vector<ConstString> &C_names,
669061da546Spatrick ConstString name) {
670061da546Spatrick if (m_strip_underscore && name.AsCString()[0] == '_')
671*f6aab3d8Srobert C_names.insert(C_names.begin(), ConstString(&name.AsCString()[1]));
672*f6aab3d8Srobert C_names.push_back(name);
673061da546Spatrick }
674061da546Spatrick
CollectCandidateCPlusPlusNames(std::vector<ConstString> & CPP_names,const std::vector<ConstString> & C_names,const SymbolContext & sc)675061da546Spatrick void IRExecutionUnit::CollectCandidateCPlusPlusNames(
676*f6aab3d8Srobert std::vector<ConstString> &CPP_names,
677*f6aab3d8Srobert const std::vector<ConstString> &C_names, const SymbolContext &sc) {
678*f6aab3d8Srobert if (auto *cpp_lang = Language::FindPlugin(lldb::eLanguageTypeC_plus_plus)) {
679*f6aab3d8Srobert for (const ConstString &name : C_names) {
680061da546Spatrick Mangled mangled(name);
681*f6aab3d8Srobert if (cpp_lang->SymbolNameFitsToLanguage(mangled)) {
682*f6aab3d8Srobert if (ConstString best_alternate =
683*f6aab3d8Srobert cpp_lang->FindBestAlternateFunctionMangledName(mangled, sc)) {
684*f6aab3d8Srobert CPP_names.push_back(best_alternate);
685*f6aab3d8Srobert }
686*f6aab3d8Srobert }
687061da546Spatrick
688*f6aab3d8Srobert std::vector<ConstString> alternates =
689*f6aab3d8Srobert cpp_lang->GenerateAlternateFunctionManglings(name);
690*f6aab3d8Srobert CPP_names.insert(CPP_names.end(), alternates.begin(), alternates.end());
691061da546Spatrick
692*f6aab3d8Srobert // As a last-ditch fallback, try the base name for C++ names. It's
693*f6aab3d8Srobert // terrible, but the DWARF doesn't always encode "extern C" correctly.
694*f6aab3d8Srobert ConstString basename =
695*f6aab3d8Srobert cpp_lang->GetDemangledFunctionNameWithoutArguments(mangled);
696*f6aab3d8Srobert CPP_names.push_back(basename);
697061da546Spatrick }
698061da546Spatrick }
699061da546Spatrick }
700061da546Spatrick
701*f6aab3d8Srobert class LoadAddressResolver {
702*f6aab3d8Srobert public:
LoadAddressResolver(Target * target,bool & symbol_was_missing_weak)703*f6aab3d8Srobert LoadAddressResolver(Target *target, bool &symbol_was_missing_weak)
704*f6aab3d8Srobert : m_target(target), m_symbol_was_missing_weak(symbol_was_missing_weak) {}
705061da546Spatrick
Resolve(SymbolContextList & sc_list)706*f6aab3d8Srobert std::optional<lldb::addr_t> Resolve(SymbolContextList &sc_list) {
707*f6aab3d8Srobert if (sc_list.IsEmpty())
708*f6aab3d8Srobert return std::nullopt;
709061da546Spatrick
710*f6aab3d8Srobert lldb::addr_t load_address = LLDB_INVALID_ADDRESS;
711061da546Spatrick
712*f6aab3d8Srobert // Missing_weak_symbol will be true only if we found only weak undefined
713061da546Spatrick // references to this symbol.
714*f6aab3d8Srobert m_symbol_was_missing_weak = true;
715061da546Spatrick
716*f6aab3d8Srobert for (auto candidate_sc : sc_list.SymbolContexts()) {
717*f6aab3d8Srobert // Only symbols can be weak undefined.
718*f6aab3d8Srobert if (!candidate_sc.symbol ||
719*f6aab3d8Srobert candidate_sc.symbol->GetType() != lldb::eSymbolTypeUndefined ||
720*f6aab3d8Srobert !candidate_sc.symbol->IsWeak())
721*f6aab3d8Srobert m_symbol_was_missing_weak = false;
722*f6aab3d8Srobert
723*f6aab3d8Srobert // First try the symbol.
724*f6aab3d8Srobert if (candidate_sc.symbol) {
725*f6aab3d8Srobert load_address = candidate_sc.symbol->ResolveCallableAddress(*m_target);
726*f6aab3d8Srobert if (load_address == LLDB_INVALID_ADDRESS) {
727*f6aab3d8Srobert Address addr = candidate_sc.symbol->GetAddress();
728*f6aab3d8Srobert load_address = m_target->GetProcessSP()
729*f6aab3d8Srobert ? addr.GetLoadAddress(m_target)
730*f6aab3d8Srobert : addr.GetFileAddress();
731*f6aab3d8Srobert }
732*f6aab3d8Srobert }
733*f6aab3d8Srobert
734*f6aab3d8Srobert // If that didn't work, try the function.
735*f6aab3d8Srobert if (load_address == LLDB_INVALID_ADDRESS && candidate_sc.function) {
736*f6aab3d8Srobert Address addr =
737*f6aab3d8Srobert candidate_sc.function->GetAddressRange().GetBaseAddress();
738*f6aab3d8Srobert load_address = m_target->GetProcessSP() ? addr.GetLoadAddress(m_target)
739*f6aab3d8Srobert : addr.GetFileAddress();
740*f6aab3d8Srobert }
741*f6aab3d8Srobert
742*f6aab3d8Srobert // We found a load address.
743*f6aab3d8Srobert if (load_address != LLDB_INVALID_ADDRESS) {
744*f6aab3d8Srobert // If the load address is external, we're done.
745061da546Spatrick const bool is_external =
746061da546Spatrick (candidate_sc.function) ||
747061da546Spatrick (candidate_sc.symbol && candidate_sc.symbol->IsExternal());
748*f6aab3d8Srobert if (is_external)
749*f6aab3d8Srobert return load_address;
750061da546Spatrick
751*f6aab3d8Srobert // Otherwise, remember the best internal load address.
752*f6aab3d8Srobert if (m_best_internal_load_address == LLDB_INVALID_ADDRESS)
753*f6aab3d8Srobert m_best_internal_load_address = load_address;
754061da546Spatrick }
755061da546Spatrick }
756061da546Spatrick
757061da546Spatrick // You test the address of a weak symbol against NULL to see if it is
758061da546Spatrick // present. So we should return 0 for a missing weak symbol.
759*f6aab3d8Srobert if (m_symbol_was_missing_weak)
760*f6aab3d8Srobert return 0;
761*f6aab3d8Srobert
762*f6aab3d8Srobert return std::nullopt;
763061da546Spatrick }
764061da546Spatrick
GetBestInternalLoadAddress() const765*f6aab3d8Srobert lldb::addr_t GetBestInternalLoadAddress() const {
766*f6aab3d8Srobert return m_best_internal_load_address;
767*f6aab3d8Srobert }
768*f6aab3d8Srobert
769*f6aab3d8Srobert private:
770*f6aab3d8Srobert Target *m_target;
771*f6aab3d8Srobert bool &m_symbol_was_missing_weak;
772*f6aab3d8Srobert lldb::addr_t m_best_internal_load_address = LLDB_INVALID_ADDRESS;
773061da546Spatrick };
774061da546Spatrick
775*f6aab3d8Srobert lldb::addr_t
FindInSymbols(const std::vector<ConstString> & names,const lldb_private::SymbolContext & sc,bool & symbol_was_missing_weak)776*f6aab3d8Srobert IRExecutionUnit::FindInSymbols(const std::vector<ConstString> &names,
777*f6aab3d8Srobert const lldb_private::SymbolContext &sc,
778*f6aab3d8Srobert bool &symbol_was_missing_weak) {
779*f6aab3d8Srobert symbol_was_missing_weak = false;
780*f6aab3d8Srobert
781*f6aab3d8Srobert Target *target = sc.target_sp.get();
782*f6aab3d8Srobert if (!target) {
783*f6aab3d8Srobert // We shouldn't be doing any symbol lookup at all without a target.
784*f6aab3d8Srobert return LLDB_INVALID_ADDRESS;
785*f6aab3d8Srobert }
786*f6aab3d8Srobert
787*f6aab3d8Srobert LoadAddressResolver resolver(target, symbol_was_missing_weak);
788*f6aab3d8Srobert
789*f6aab3d8Srobert ModuleFunctionSearchOptions function_options;
790*f6aab3d8Srobert function_options.include_symbols = true;
791*f6aab3d8Srobert function_options.include_inlines = false;
792*f6aab3d8Srobert
793*f6aab3d8Srobert for (const ConstString &name : names) {
794061da546Spatrick if (sc.module_sp) {
795*f6aab3d8Srobert SymbolContextList sc_list;
796*f6aab3d8Srobert sc.module_sp->FindFunctions(name, CompilerDeclContext(),
797*f6aab3d8Srobert lldb::eFunctionNameTypeFull, function_options,
798061da546Spatrick sc_list);
799*f6aab3d8Srobert if (auto load_addr = resolver.Resolve(sc_list))
800*f6aab3d8Srobert return *load_addr;
801061da546Spatrick }
802061da546Spatrick
803*f6aab3d8Srobert if (sc.target_sp) {
804*f6aab3d8Srobert SymbolContextList sc_list;
805*f6aab3d8Srobert sc.target_sp->GetImages().FindFunctions(name, lldb::eFunctionNameTypeFull,
806*f6aab3d8Srobert function_options, sc_list);
807*f6aab3d8Srobert if (auto load_addr = resolver.Resolve(sc_list))
808*f6aab3d8Srobert return *load_addr;
809061da546Spatrick }
810061da546Spatrick
811*f6aab3d8Srobert if (sc.target_sp) {
812*f6aab3d8Srobert SymbolContextList sc_list;
813061da546Spatrick sc.target_sp->GetImages().FindSymbolsWithNameAndType(
814*f6aab3d8Srobert name, lldb::eSymbolTypeAny, sc_list);
815*f6aab3d8Srobert if (auto load_addr = resolver.Resolve(sc_list))
816*f6aab3d8Srobert return *load_addr;
817061da546Spatrick }
818061da546Spatrick
819*f6aab3d8Srobert lldb::addr_t best_internal_load_address =
820*f6aab3d8Srobert resolver.GetBestInternalLoadAddress();
821*f6aab3d8Srobert if (best_internal_load_address != LLDB_INVALID_ADDRESS)
822061da546Spatrick return best_internal_load_address;
823061da546Spatrick }
824061da546Spatrick
825061da546Spatrick return LLDB_INVALID_ADDRESS;
826061da546Spatrick }
827061da546Spatrick
828061da546Spatrick lldb::addr_t
FindInRuntimes(const std::vector<ConstString> & names,const lldb_private::SymbolContext & sc)829*f6aab3d8Srobert IRExecutionUnit::FindInRuntimes(const std::vector<ConstString> &names,
830061da546Spatrick const lldb_private::SymbolContext &sc) {
831061da546Spatrick lldb::TargetSP target_sp = sc.target_sp;
832061da546Spatrick
833061da546Spatrick if (!target_sp) {
834061da546Spatrick return LLDB_INVALID_ADDRESS;
835061da546Spatrick }
836061da546Spatrick
837061da546Spatrick lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP();
838061da546Spatrick
839061da546Spatrick if (!process_sp) {
840061da546Spatrick return LLDB_INVALID_ADDRESS;
841061da546Spatrick }
842061da546Spatrick
843*f6aab3d8Srobert for (const ConstString &name : names) {
844061da546Spatrick for (LanguageRuntime *runtime : process_sp->GetLanguageRuntimes()) {
845*f6aab3d8Srobert lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(name);
846061da546Spatrick
847061da546Spatrick if (symbol_load_addr != LLDB_INVALID_ADDRESS)
848061da546Spatrick return symbol_load_addr;
849061da546Spatrick }
850061da546Spatrick }
851061da546Spatrick
852061da546Spatrick return LLDB_INVALID_ADDRESS;
853061da546Spatrick }
854061da546Spatrick
FindInUserDefinedSymbols(const std::vector<ConstString> & names,const lldb_private::SymbolContext & sc)855061da546Spatrick lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols(
856*f6aab3d8Srobert const std::vector<ConstString> &names,
857061da546Spatrick const lldb_private::SymbolContext &sc) {
858061da546Spatrick lldb::TargetSP target_sp = sc.target_sp;
859061da546Spatrick
860*f6aab3d8Srobert for (const ConstString &name : names) {
861*f6aab3d8Srobert lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(name);
862061da546Spatrick
863061da546Spatrick if (symbol_load_addr != LLDB_INVALID_ADDRESS)
864061da546Spatrick return symbol_load_addr;
865061da546Spatrick }
866061da546Spatrick
867061da546Spatrick return LLDB_INVALID_ADDRESS;
868061da546Spatrick }
869061da546Spatrick
FindSymbol(lldb_private::ConstString name,bool & missing_weak)870*f6aab3d8Srobert lldb::addr_t IRExecutionUnit::FindSymbol(lldb_private::ConstString name,
871*f6aab3d8Srobert bool &missing_weak) {
872*f6aab3d8Srobert std::vector<ConstString> candidate_C_names;
873*f6aab3d8Srobert std::vector<ConstString> candidate_CPlusPlus_names;
874061da546Spatrick
875061da546Spatrick CollectCandidateCNames(candidate_C_names, name);
876061da546Spatrick
877061da546Spatrick lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx, missing_weak);
878061da546Spatrick if (ret != LLDB_INVALID_ADDRESS)
879061da546Spatrick return ret;
880061da546Spatrick
881061da546Spatrick // If we find the symbol in runtimes or user defined symbols it can't be
882061da546Spatrick // a missing weak symbol.
883061da546Spatrick missing_weak = false;
884061da546Spatrick ret = FindInRuntimes(candidate_C_names, m_sym_ctx);
885061da546Spatrick if (ret != LLDB_INVALID_ADDRESS)
886061da546Spatrick return ret;
887061da546Spatrick
888061da546Spatrick ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx);
889061da546Spatrick if (ret != LLDB_INVALID_ADDRESS)
890061da546Spatrick return ret;
891061da546Spatrick
892061da546Spatrick CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names,
893061da546Spatrick m_sym_ctx);
894061da546Spatrick ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx, missing_weak);
895061da546Spatrick return ret;
896061da546Spatrick }
897061da546Spatrick
GetStaticInitializers(std::vector<lldb::addr_t> & static_initializers)898061da546Spatrick void IRExecutionUnit::GetStaticInitializers(
899061da546Spatrick std::vector<lldb::addr_t> &static_initializers) {
900*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
901061da546Spatrick
902061da546Spatrick llvm::GlobalVariable *global_ctors =
903061da546Spatrick m_module->getNamedGlobal("llvm.global_ctors");
904061da546Spatrick if (!global_ctors) {
905061da546Spatrick LLDB_LOG(log, "Couldn't find llvm.global_ctors.");
906061da546Spatrick return;
907061da546Spatrick }
908061da546Spatrick auto *ctor_array =
909061da546Spatrick llvm::dyn_cast<llvm::ConstantArray>(global_ctors->getInitializer());
910061da546Spatrick if (!ctor_array) {
911061da546Spatrick LLDB_LOG(log, "llvm.global_ctors not a ConstantArray.");
912061da546Spatrick return;
913061da546Spatrick }
914061da546Spatrick
915061da546Spatrick for (llvm::Use &ctor_use : ctor_array->operands()) {
916061da546Spatrick auto *ctor_struct = llvm::dyn_cast<llvm::ConstantStruct>(ctor_use);
917061da546Spatrick if (!ctor_struct)
918061da546Spatrick continue;
919061da546Spatrick // this is standardized
920061da546Spatrick lldbassert(ctor_struct->getNumOperands() == 3);
921061da546Spatrick auto *ctor_function =
922061da546Spatrick llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1));
923061da546Spatrick if (!ctor_function) {
924061da546Spatrick LLDB_LOG(log, "global_ctor doesn't contain an llvm::Function");
925061da546Spatrick continue;
926061da546Spatrick }
927061da546Spatrick
928061da546Spatrick ConstString ctor_function_name(ctor_function->getName().str());
929061da546Spatrick LLDB_LOG(log, "Looking for callable jitted function with name {0}.",
930061da546Spatrick ctor_function_name);
931061da546Spatrick
932061da546Spatrick for (JittedFunction &jitted_function : m_jitted_functions) {
933061da546Spatrick if (ctor_function_name != jitted_function.m_name)
934061da546Spatrick continue;
935061da546Spatrick if (jitted_function.m_remote_addr == LLDB_INVALID_ADDRESS) {
936061da546Spatrick LLDB_LOG(log, "Found jitted function with invalid address.");
937061da546Spatrick continue;
938061da546Spatrick }
939061da546Spatrick static_initializers.push_back(jitted_function.m_remote_addr);
940061da546Spatrick LLDB_LOG(log, "Calling function at address {0:x}.",
941061da546Spatrick jitted_function.m_remote_addr);
942061da546Spatrick break;
943061da546Spatrick }
944061da546Spatrick }
945061da546Spatrick }
946061da546Spatrick
947061da546Spatrick llvm::JITSymbol
findSymbol(const std::string & Name)948061da546Spatrick IRExecutionUnit::MemoryManager::findSymbol(const std::string &Name) {
949061da546Spatrick bool missing_weak = false;
950061da546Spatrick uint64_t addr = GetSymbolAddressAndPresence(Name, missing_weak);
951061da546Spatrick // This is a weak symbol:
952061da546Spatrick if (missing_weak)
953061da546Spatrick return llvm::JITSymbol(addr,
954061da546Spatrick llvm::JITSymbolFlags::Exported | llvm::JITSymbolFlags::Weak);
955061da546Spatrick else
956061da546Spatrick return llvm::JITSymbol(addr, llvm::JITSymbolFlags::Exported);
957061da546Spatrick }
958061da546Spatrick
959061da546Spatrick uint64_t
getSymbolAddress(const std::string & Name)960061da546Spatrick IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) {
961061da546Spatrick bool missing_weak = false;
962061da546Spatrick return GetSymbolAddressAndPresence(Name, missing_weak);
963061da546Spatrick }
964061da546Spatrick
965061da546Spatrick uint64_t
GetSymbolAddressAndPresence(const std::string & Name,bool & missing_weak)966061da546Spatrick IRExecutionUnit::MemoryManager::GetSymbolAddressAndPresence(
967061da546Spatrick const std::string &Name, bool &missing_weak) {
968*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
969061da546Spatrick
970061da546Spatrick ConstString name_cs(Name.c_str());
971061da546Spatrick
972061da546Spatrick lldb::addr_t ret = m_parent.FindSymbol(name_cs, missing_weak);
973061da546Spatrick
974061da546Spatrick if (ret == LLDB_INVALID_ADDRESS) {
975061da546Spatrick LLDB_LOGF(log,
976061da546Spatrick "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>",
977061da546Spatrick Name.c_str());
978061da546Spatrick
979061da546Spatrick m_parent.ReportSymbolLookupError(name_cs);
980061da546Spatrick return 0;
981061da546Spatrick } else {
982061da546Spatrick LLDB_LOGF(log, "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64,
983061da546Spatrick Name.c_str(), ret);
984061da546Spatrick return ret;
985061da546Spatrick }
986061da546Spatrick }
987061da546Spatrick
getPointerToNamedFunction(const std::string & Name,bool AbortOnFailure)988061da546Spatrick void *IRExecutionUnit::MemoryManager::getPointerToNamedFunction(
989061da546Spatrick const std::string &Name, bool AbortOnFailure) {
990061da546Spatrick return (void *)getSymbolAddress(Name);
991061da546Spatrick }
992061da546Spatrick
993061da546Spatrick lldb::addr_t
GetRemoteAddressForLocal(lldb::addr_t local_address)994061da546Spatrick IRExecutionUnit::GetRemoteAddressForLocal(lldb::addr_t local_address) {
995*f6aab3d8Srobert Log *log = GetLog(LLDBLog::Expressions);
996061da546Spatrick
997061da546Spatrick for (AllocationRecord &record : m_records) {
998061da546Spatrick if (local_address >= record.m_host_address &&
999061da546Spatrick local_address < record.m_host_address + record.m_size) {
1000061da546Spatrick if (record.m_process_address == LLDB_INVALID_ADDRESS)
1001061da546Spatrick return LLDB_INVALID_ADDRESS;
1002061da546Spatrick
1003061da546Spatrick lldb::addr_t ret =
1004061da546Spatrick record.m_process_address + (local_address - record.m_host_address);
1005061da546Spatrick
1006061da546Spatrick LLDB_LOGF(log,
1007061da546Spatrick "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64
1008061da546Spatrick " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64
1009061da546Spatrick " from [0x%" PRIx64 "..0x%" PRIx64 "].",
1010061da546Spatrick local_address, (uint64_t)record.m_host_address,
1011061da546Spatrick (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret,
1012061da546Spatrick record.m_process_address,
1013061da546Spatrick record.m_process_address + record.m_size);
1014061da546Spatrick
1015061da546Spatrick return ret;
1016061da546Spatrick }
1017061da546Spatrick }
1018061da546Spatrick
1019061da546Spatrick return LLDB_INVALID_ADDRESS;
1020061da546Spatrick }
1021061da546Spatrick
1022061da546Spatrick IRExecutionUnit::AddrRange
GetRemoteRangeForLocal(lldb::addr_t local_address)1023061da546Spatrick IRExecutionUnit::GetRemoteRangeForLocal(lldb::addr_t local_address) {
1024061da546Spatrick for (AllocationRecord &record : m_records) {
1025061da546Spatrick if (local_address >= record.m_host_address &&
1026061da546Spatrick local_address < record.m_host_address + record.m_size) {
1027061da546Spatrick if (record.m_process_address == LLDB_INVALID_ADDRESS)
1028061da546Spatrick return AddrRange(0, 0);
1029061da546Spatrick
1030061da546Spatrick return AddrRange(record.m_process_address, record.m_size);
1031061da546Spatrick }
1032061da546Spatrick }
1033061da546Spatrick
1034061da546Spatrick return AddrRange(0, 0);
1035061da546Spatrick }
1036061da546Spatrick
CommitOneAllocation(lldb::ProcessSP & process_sp,Status & error,AllocationRecord & record)1037061da546Spatrick bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp,
1038061da546Spatrick Status &error,
1039061da546Spatrick AllocationRecord &record) {
1040061da546Spatrick if (record.m_process_address != LLDB_INVALID_ADDRESS) {
1041061da546Spatrick return true;
1042061da546Spatrick }
1043061da546Spatrick
1044061da546Spatrick switch (record.m_sect_type) {
1045061da546Spatrick case lldb::eSectionTypeInvalid:
1046061da546Spatrick case lldb::eSectionTypeDWARFDebugAbbrev:
1047061da546Spatrick case lldb::eSectionTypeDWARFDebugAddr:
1048061da546Spatrick case lldb::eSectionTypeDWARFDebugAranges:
1049061da546Spatrick case lldb::eSectionTypeDWARFDebugCuIndex:
1050061da546Spatrick case lldb::eSectionTypeDWARFDebugFrame:
1051061da546Spatrick case lldb::eSectionTypeDWARFDebugInfo:
1052061da546Spatrick case lldb::eSectionTypeDWARFDebugLine:
1053061da546Spatrick case lldb::eSectionTypeDWARFDebugLoc:
1054061da546Spatrick case lldb::eSectionTypeDWARFDebugLocLists:
1055061da546Spatrick case lldb::eSectionTypeDWARFDebugMacInfo:
1056061da546Spatrick case lldb::eSectionTypeDWARFDebugPubNames:
1057061da546Spatrick case lldb::eSectionTypeDWARFDebugPubTypes:
1058061da546Spatrick case lldb::eSectionTypeDWARFDebugRanges:
1059061da546Spatrick case lldb::eSectionTypeDWARFDebugStr:
1060061da546Spatrick case lldb::eSectionTypeDWARFDebugStrOffsets:
1061061da546Spatrick case lldb::eSectionTypeDWARFAppleNames:
1062061da546Spatrick case lldb::eSectionTypeDWARFAppleTypes:
1063061da546Spatrick case lldb::eSectionTypeDWARFAppleNamespaces:
1064061da546Spatrick case lldb::eSectionTypeDWARFAppleObjC:
1065061da546Spatrick case lldb::eSectionTypeDWARFGNUDebugAltLink:
1066061da546Spatrick error.Clear();
1067061da546Spatrick break;
1068061da546Spatrick default:
1069061da546Spatrick const bool zero_memory = false;
1070061da546Spatrick record.m_process_address =
1071061da546Spatrick Malloc(record.m_size, record.m_alignment, record.m_permissions,
1072061da546Spatrick eAllocationPolicyProcessOnly, zero_memory, error);
1073061da546Spatrick break;
1074061da546Spatrick }
1075061da546Spatrick
1076061da546Spatrick return error.Success();
1077061da546Spatrick }
1078061da546Spatrick
CommitAllocations(lldb::ProcessSP & process_sp)1079061da546Spatrick bool IRExecutionUnit::CommitAllocations(lldb::ProcessSP &process_sp) {
1080061da546Spatrick bool ret = true;
1081061da546Spatrick
1082061da546Spatrick lldb_private::Status err;
1083061da546Spatrick
1084061da546Spatrick for (AllocationRecord &record : m_records) {
1085061da546Spatrick ret = CommitOneAllocation(process_sp, err, record);
1086061da546Spatrick
1087061da546Spatrick if (!ret) {
1088061da546Spatrick break;
1089061da546Spatrick }
1090061da546Spatrick }
1091061da546Spatrick
1092061da546Spatrick if (!ret) {
1093061da546Spatrick for (AllocationRecord &record : m_records) {
1094061da546Spatrick if (record.m_process_address != LLDB_INVALID_ADDRESS) {
1095061da546Spatrick Free(record.m_process_address, err);
1096061da546Spatrick record.m_process_address = LLDB_INVALID_ADDRESS;
1097061da546Spatrick }
1098061da546Spatrick }
1099061da546Spatrick }
1100061da546Spatrick
1101061da546Spatrick return ret;
1102061da546Spatrick }
1103061da546Spatrick
ReportAllocations(llvm::ExecutionEngine & engine)1104061da546Spatrick void IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine &engine) {
1105061da546Spatrick m_reported_allocations = true;
1106061da546Spatrick
1107061da546Spatrick for (AllocationRecord &record : m_records) {
1108061da546Spatrick if (record.m_process_address == LLDB_INVALID_ADDRESS)
1109061da546Spatrick continue;
1110061da546Spatrick
1111061da546Spatrick if (record.m_section_id == eSectionIDInvalid)
1112061da546Spatrick continue;
1113061da546Spatrick
1114061da546Spatrick engine.mapSectionAddress((void *)record.m_host_address,
1115061da546Spatrick record.m_process_address);
1116061da546Spatrick }
1117061da546Spatrick
1118061da546Spatrick // Trigger re-application of relocations.
1119061da546Spatrick engine.finalizeObject();
1120061da546Spatrick }
1121061da546Spatrick
WriteData(lldb::ProcessSP & process_sp)1122061da546Spatrick bool IRExecutionUnit::WriteData(lldb::ProcessSP &process_sp) {
1123061da546Spatrick bool wrote_something = false;
1124061da546Spatrick for (AllocationRecord &record : m_records) {
1125061da546Spatrick if (record.m_process_address != LLDB_INVALID_ADDRESS) {
1126061da546Spatrick lldb_private::Status err;
1127061da546Spatrick WriteMemory(record.m_process_address, (uint8_t *)record.m_host_address,
1128061da546Spatrick record.m_size, err);
1129061da546Spatrick if (err.Success())
1130061da546Spatrick wrote_something = true;
1131061da546Spatrick }
1132061da546Spatrick }
1133061da546Spatrick return wrote_something;
1134061da546Spatrick }
1135061da546Spatrick
dump(Log * log)1136061da546Spatrick void IRExecutionUnit::AllocationRecord::dump(Log *log) {
1137061da546Spatrick if (!log)
1138061da546Spatrick return;
1139061da546Spatrick
1140061da546Spatrick LLDB_LOGF(log,
1141061da546Spatrick "[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)",
1142061da546Spatrick (unsigned long long)m_host_address, (unsigned long long)m_size,
1143061da546Spatrick (unsigned long long)m_process_address, (unsigned)m_alignment,
1144061da546Spatrick (unsigned)m_section_id, m_name.c_str());
1145061da546Spatrick }
1146061da546Spatrick
GetByteOrder() const1147061da546Spatrick lldb::ByteOrder IRExecutionUnit::GetByteOrder() const {
1148061da546Spatrick ExecutionContext exe_ctx(GetBestExecutionContextScope());
1149061da546Spatrick return exe_ctx.GetByteOrder();
1150061da546Spatrick }
1151061da546Spatrick
GetAddressByteSize() const1152061da546Spatrick uint32_t IRExecutionUnit::GetAddressByteSize() const {
1153061da546Spatrick ExecutionContext exe_ctx(GetBestExecutionContextScope());
1154061da546Spatrick return exe_ctx.GetAddressByteSize();
1155061da546Spatrick }
1156061da546Spatrick
PopulateSymtab(lldb_private::ObjectFile * obj_file,lldb_private::Symtab & symtab)1157061da546Spatrick void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file,
1158061da546Spatrick lldb_private::Symtab &symtab) {
1159061da546Spatrick // No symbols yet...
1160061da546Spatrick }
1161061da546Spatrick
PopulateSectionList(lldb_private::ObjectFile * obj_file,lldb_private::SectionList & section_list)1162061da546Spatrick void IRExecutionUnit::PopulateSectionList(
1163061da546Spatrick lldb_private::ObjectFile *obj_file,
1164061da546Spatrick lldb_private::SectionList §ion_list) {
1165061da546Spatrick for (AllocationRecord &record : m_records) {
1166061da546Spatrick if (record.m_size > 0) {
1167061da546Spatrick lldb::SectionSP section_sp(new lldb_private::Section(
1168061da546Spatrick obj_file->GetModule(), obj_file, record.m_section_id,
1169061da546Spatrick ConstString(record.m_name), record.m_sect_type,
1170061da546Spatrick record.m_process_address, record.m_size,
1171061da546Spatrick record.m_host_address, // file_offset (which is the host address for
1172061da546Spatrick // the data)
1173061da546Spatrick record.m_size, // file_size
1174061da546Spatrick 0,
1175061da546Spatrick record.m_permissions)); // flags
1176061da546Spatrick section_list.AddSection(section_sp);
1177061da546Spatrick }
1178061da546Spatrick }
1179061da546Spatrick }
1180061da546Spatrick
GetArchitecture()1181061da546Spatrick ArchSpec IRExecutionUnit::GetArchitecture() {
1182061da546Spatrick ExecutionContext exe_ctx(GetBestExecutionContextScope());
1183061da546Spatrick if(Target *target = exe_ctx.GetTargetPtr())
1184061da546Spatrick return target->GetArchitecture();
1185061da546Spatrick return ArchSpec();
1186061da546Spatrick }
1187061da546Spatrick
GetJITModule()1188061da546Spatrick lldb::ModuleSP IRExecutionUnit::GetJITModule() {
1189061da546Spatrick ExecutionContext exe_ctx(GetBestExecutionContextScope());
1190061da546Spatrick Target *target = exe_ctx.GetTargetPtr();
1191061da546Spatrick if (!target)
1192061da546Spatrick return nullptr;
1193061da546Spatrick
1194061da546Spatrick auto Delegate = std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>(
1195061da546Spatrick shared_from_this());
1196061da546Spatrick
1197061da546Spatrick lldb::ModuleSP jit_module_sp =
1198061da546Spatrick lldb_private::Module::CreateModuleFromObjectFile<ObjectFileJIT>(Delegate);
1199061da546Spatrick if (!jit_module_sp)
1200061da546Spatrick return nullptr;
1201061da546Spatrick
1202061da546Spatrick bool changed = false;
1203061da546Spatrick jit_module_sp->SetLoadAddress(*target, 0, true, changed);
1204061da546Spatrick return jit_module_sp;
1205061da546Spatrick }
1206