File: | tools/lldb/source/Expression/IRExecutionUnit.cpp |
Warning: | line 751, column 29 Array access results in a null pointer dereference |
1 | //===-- IRExecutionUnit.cpp -------------------------------------*- C++ -*-===// | |||
2 | // | |||
3 | // The LLVM Compiler Infrastructure | |||
4 | // | |||
5 | // This file is distributed under the University of Illinois Open Source | |||
6 | // License. See LICENSE.TXT for details. | |||
7 | // | |||
8 | //===----------------------------------------------------------------------===// | |||
9 | ||||
10 | #include "llvm/ExecutionEngine/ExecutionEngine.h" | |||
11 | #include "llvm/ExecutionEngine/ObjectCache.h" | |||
12 | #include "llvm/IR/Constants.h" | |||
13 | #include "llvm/IR/LLVMContext.h" | |||
14 | #include "llvm/IR/Module.h" | |||
15 | #include "llvm/Support/SourceMgr.h" | |||
16 | #include "llvm/Support/raw_ostream.h" | |||
17 | ||||
18 | #include "lldb/Core/Debugger.h" | |||
19 | #include "lldb/Core/Disassembler.h" | |||
20 | #include "lldb/Core/Module.h" | |||
21 | #include "lldb/Core/Section.h" | |||
22 | #include "lldb/Expression/IRExecutionUnit.h" | |||
23 | #include "lldb/Symbol/CompileUnit.h" | |||
24 | #include "lldb/Symbol/SymbolContext.h" | |||
25 | #include "lldb/Symbol/SymbolFile.h" | |||
26 | #include "lldb/Symbol/SymbolVendor.h" | |||
27 | #include "lldb/Target/ExecutionContext.h" | |||
28 | #include "lldb/Target/ObjCLanguageRuntime.h" | |||
29 | #include "lldb/Target/Target.h" | |||
30 | #include "lldb/Utility/DataBufferHeap.h" | |||
31 | #include "lldb/Utility/DataExtractor.h" | |||
32 | #include "lldb/Utility/LLDBAssert.h" | |||
33 | #include "lldb/Utility/Log.h" | |||
34 | ||||
35 | #include "lldb/../../source/Plugins/Language/CPlusPlus/CPlusPlusLanguage.h" | |||
36 | ||||
37 | using namespace lldb_private; | |||
38 | ||||
39 | IRExecutionUnit::IRExecutionUnit(std::unique_ptr<llvm::LLVMContext> &context_ap, | |||
40 | std::unique_ptr<llvm::Module> &module_ap, | |||
41 | ConstString &name, | |||
42 | const lldb::TargetSP &target_sp, | |||
43 | const SymbolContext &sym_ctx, | |||
44 | std::vector<std::string> &cpu_features) | |||
45 | : IRMemoryMap(target_sp), m_context_ap(context_ap.release()), | |||
46 | m_module_ap(module_ap.release()), m_module(m_module_ap.get()), | |||
47 | m_cpu_features(cpu_features), m_name(name), m_sym_ctx(sym_ctx), | |||
48 | m_did_jit(false), m_function_load_addr(LLDB_INVALID_ADDRESS(18446744073709551615UL)), | |||
49 | m_function_end_load_addr(LLDB_INVALID_ADDRESS(18446744073709551615UL)), | |||
50 | m_reported_allocations(false) {} | |||
51 | ||||
52 | lldb::addr_t IRExecutionUnit::WriteNow(const uint8_t *bytes, size_t size, | |||
53 | Status &error) { | |||
54 | const bool zero_memory = false; | |||
55 | lldb::addr_t allocation_process_addr = | |||
56 | Malloc(size, 8, lldb::ePermissionsWritable | lldb::ePermissionsReadable, | |||
57 | eAllocationPolicyMirror, zero_memory, error); | |||
58 | ||||
59 | if (!error.Success()) | |||
60 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
61 | ||||
62 | WriteMemory(allocation_process_addr, bytes, size, error); | |||
63 | ||||
64 | if (!error.Success()) { | |||
65 | Status err; | |||
66 | Free(allocation_process_addr, err); | |||
67 | ||||
68 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
69 | } | |||
70 | ||||
71 | if (Log *log = | |||
72 | lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))) { | |||
73 | DataBufferHeap my_buffer(size, 0); | |||
74 | Status err; | |||
75 | ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err); | |||
76 | ||||
77 | if (err.Success()) { | |||
78 | DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), | |||
79 | lldb::eByteOrderBig, 8); | |||
80 | my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), | |||
81 | allocation_process_addr, 16, | |||
82 | DataExtractor::TypeUInt8); | |||
83 | } | |||
84 | } | |||
85 | ||||
86 | return allocation_process_addr; | |||
87 | } | |||
88 | ||||
89 | void IRExecutionUnit::FreeNow(lldb::addr_t allocation) { | |||
90 | if (allocation == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
91 | return; | |||
92 | ||||
93 | Status err; | |||
94 | ||||
95 | Free(allocation, err); | |||
96 | } | |||
97 | ||||
98 | Status IRExecutionUnit::DisassembleFunction(Stream &stream, | |||
99 | lldb::ProcessSP &process_wp) { | |||
100 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
101 | ||||
102 | ExecutionContext exe_ctx(process_wp); | |||
103 | ||||
104 | Status ret; | |||
105 | ||||
106 | ret.Clear(); | |||
107 | ||||
108 | lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
109 | lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
110 | ||||
111 | for (JittedFunction &function : m_jitted_functions) { | |||
112 | if (function.m_name == m_name) { | |||
113 | func_local_addr = function.m_local_addr; | |||
114 | func_remote_addr = function.m_remote_addr; | |||
115 | } | |||
116 | } | |||
117 | ||||
118 | if (func_local_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
119 | ret.SetErrorToGenericError(); | |||
120 | ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", | |||
121 | m_name.AsCString()); | |||
122 | return ret; | |||
123 | } | |||
124 | ||||
125 | if (log) | |||
126 | log->Printf("Found function, has local address 0x%" PRIx64"l" "x" | |||
127 | " and remote address 0x%" PRIx64"l" "x", | |||
128 | (uint64_t)func_local_addr, (uint64_t)func_remote_addr); | |||
129 | ||||
130 | std::pair<lldb::addr_t, lldb::addr_t> func_range; | |||
131 | ||||
132 | func_range = GetRemoteRangeForLocal(func_local_addr); | |||
133 | ||||
134 | if (func_range.first == 0 && func_range.second == 0) { | |||
135 | ret.SetErrorToGenericError(); | |||
136 | ret.SetErrorStringWithFormat("Couldn't find code range for function %s", | |||
137 | m_name.AsCString()); | |||
138 | return ret; | |||
139 | } | |||
140 | ||||
141 | if (log) | |||
142 | log->Printf("Function's code range is [0x%" PRIx64"l" "x" "+0x%" PRIx64"l" "x" "]", | |||
143 | func_range.first, func_range.second); | |||
144 | ||||
145 | Target *target = exe_ctx.GetTargetPtr(); | |||
146 | if (!target) { | |||
147 | ret.SetErrorToGenericError(); | |||
148 | ret.SetErrorString("Couldn't find the target"); | |||
149 | return ret; | |||
150 | } | |||
151 | ||||
152 | lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0)); | |||
153 | ||||
154 | Process *process = exe_ctx.GetProcessPtr(); | |||
155 | Status err; | |||
156 | process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), | |||
157 | buffer_sp->GetByteSize(), err); | |||
158 | ||||
159 | if (!err.Success()) { | |||
160 | ret.SetErrorToGenericError(); | |||
161 | ret.SetErrorStringWithFormat("Couldn't read from process: %s", | |||
162 | err.AsCString("unknown error")); | |||
163 | return ret; | |||
164 | } | |||
165 | ||||
166 | ArchSpec arch(target->GetArchitecture()); | |||
167 | ||||
168 | const char *plugin_name = NULL__null; | |||
169 | const char *flavor_string = NULL__null; | |||
170 | lldb::DisassemblerSP disassembler_sp = | |||
171 | Disassembler::FindPlugin(arch, flavor_string, plugin_name); | |||
172 | ||||
173 | if (!disassembler_sp) { | |||
174 | ret.SetErrorToGenericError(); | |||
175 | ret.SetErrorStringWithFormat( | |||
176 | "Unable to find disassembler plug-in for %s architecture.", | |||
177 | arch.GetArchitectureName()); | |||
178 | return ret; | |||
179 | } | |||
180 | ||||
181 | if (!process) { | |||
182 | ret.SetErrorToGenericError(); | |||
183 | ret.SetErrorString("Couldn't find the process"); | |||
184 | return ret; | |||
185 | } | |||
186 | ||||
187 | DataExtractor extractor(buffer_sp, process->GetByteOrder(), | |||
188 | target->GetArchitecture().GetAddressByteSize()); | |||
189 | ||||
190 | if (log) { | |||
191 | log->Printf("Function data has contents:"); | |||
192 | extractor.PutToLog(log, 0, extractor.GetByteSize(), func_remote_addr, 16, | |||
193 | DataExtractor::TypeUInt8); | |||
194 | } | |||
195 | ||||
196 | disassembler_sp->DecodeInstructions(Address(func_remote_addr), extractor, 0, | |||
197 | UINT32_MAX(4294967295U), false, false); | |||
198 | ||||
199 | InstructionList &instruction_list = disassembler_sp->GetInstructionList(); | |||
200 | instruction_list.Dump(&stream, true, true, &exe_ctx); | |||
201 | return ret; | |||
202 | } | |||
203 | ||||
204 | static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, | |||
205 | void *Context, unsigned LocCookie) { | |||
206 | Status *err = static_cast<Status *>(Context); | |||
207 | ||||
208 | if (err && err->Success()) { | |||
209 | err->SetErrorToGenericError(); | |||
210 | err->SetErrorStringWithFormat("Inline assembly error: %s", | |||
211 | diagnostic.getMessage().str().c_str()); | |||
212 | } | |||
213 | } | |||
214 | ||||
215 | void IRExecutionUnit::ReportSymbolLookupError(const ConstString &name) { | |||
216 | m_failed_lookups.push_back(name); | |||
217 | } | |||
218 | ||||
219 | void IRExecutionUnit::GetRunnableInfo(Status &error, lldb::addr_t &func_addr, | |||
220 | lldb::addr_t &func_end) { | |||
221 | lldb::ProcessSP process_sp(GetProcessWP().lock()); | |||
222 | ||||
223 | static std::recursive_mutex s_runnable_info_mutex; | |||
224 | ||||
225 | func_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
226 | func_end = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
227 | ||||
228 | if (!process_sp) { | |||
229 | error.SetErrorToGenericError(); | |||
230 | error.SetErrorString("Couldn't write the JIT compiled code into the " | |||
231 | "process because the process is invalid"); | |||
232 | return; | |||
233 | } | |||
234 | ||||
235 | if (m_did_jit) { | |||
236 | func_addr = m_function_load_addr; | |||
237 | func_end = m_function_end_load_addr; | |||
238 | ||||
239 | return; | |||
240 | }; | |||
241 | ||||
242 | std::lock_guard<std::recursive_mutex> guard(s_runnable_info_mutex); | |||
243 | ||||
244 | m_did_jit = true; | |||
245 | ||||
246 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
247 | ||||
248 | std::string error_string; | |||
249 | ||||
250 | if (log) { | |||
251 | std::string s; | |||
252 | llvm::raw_string_ostream oss(s); | |||
253 | ||||
254 | m_module->print(oss, NULL__null); | |||
255 | ||||
256 | oss.flush(); | |||
257 | ||||
258 | log->Printf("Module being sent to JIT: \n%s", s.c_str()); | |||
259 | } | |||
260 | ||||
261 | llvm::Triple triple(m_module->getTargetTriple()); | |||
262 | llvm::Reloc::Model relocModel; | |||
263 | llvm::CodeModel::Model codeModel; | |||
264 | ||||
265 | if (triple.isOSBinFormatELF()) { | |||
266 | relocModel = llvm::Reloc::Static; | |||
267 | } else { | |||
268 | relocModel = llvm::Reloc::PIC_; | |||
269 | } | |||
270 | ||||
271 | // This will be small for 32-bit and large for 64-bit. | |||
272 | codeModel = llvm::CodeModel::JITDefault; | |||
273 | ||||
274 | m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, | |||
275 | &error); | |||
276 | ||||
277 | llvm::EngineBuilder builder(std::move(m_module_ap)); | |||
278 | ||||
279 | builder.setEngineKind(llvm::EngineKind::JIT) | |||
280 | .setErrorStr(&error_string) | |||
281 | .setRelocationModel(relocModel) | |||
282 | .setMCJITMemoryManager( | |||
283 | std::unique_ptr<MemoryManager>(new MemoryManager(*this))) | |||
284 | .setCodeModel(codeModel) | |||
285 | .setOptLevel(llvm::CodeGenOpt::Less) | |||
286 | .setUseOrcMCJITReplacement(true); | |||
287 | ||||
288 | llvm::StringRef mArch; | |||
289 | llvm::StringRef mCPU; | |||
290 | llvm::SmallVector<std::string, 0> mAttrs; | |||
291 | ||||
292 | for (std::string &feature : m_cpu_features) | |||
293 | mAttrs.push_back(feature); | |||
294 | ||||
295 | llvm::TargetMachine *target_machine = | |||
296 | builder.selectTarget(triple, mArch, mCPU, mAttrs); | |||
297 | ||||
298 | m_execution_engine_ap.reset(builder.create(target_machine)); | |||
299 | ||||
300 | m_strip_underscore = | |||
301 | (m_execution_engine_ap->getDataLayout().getGlobalPrefix() == '_'); | |||
302 | ||||
303 | if (!m_execution_engine_ap.get()) { | |||
304 | error.SetErrorToGenericError(); | |||
305 | error.SetErrorStringWithFormat("Couldn't JIT the function: %s", | |||
306 | error_string.c_str()); | |||
307 | return; | |||
308 | } | |||
309 | ||||
310 | class ObjectDumper : public llvm::ObjectCache { | |||
311 | public: | |||
312 | void notifyObjectCompiled(const llvm::Module *module, | |||
313 | llvm::MemoryBufferRef object) override { | |||
314 | int fd = 0; | |||
315 | llvm::SmallVector<char, 256> result_path; | |||
316 | std::string object_name_model = | |||
317 | "jit-object-" + module->getModuleIdentifier() + "-%%%.o"; | |||
318 | (void)llvm::sys::fs::createUniqueFile(object_name_model, fd, result_path); | |||
319 | llvm::raw_fd_ostream fds(fd, true); | |||
320 | fds.write(object.getBufferStart(), object.getBufferSize()); | |||
321 | } | |||
322 | ||||
323 | std::unique_ptr<llvm::MemoryBuffer> | |||
324 | getObject(const llvm::Module *module) override { | |||
325 | // Return nothing - we're just abusing the object-cache mechanism to dump | |||
326 | // objects. | |||
327 | return nullptr; | |||
328 | } | |||
329 | }; | |||
330 | ||||
331 | if (process_sp->GetTarget().GetEnableSaveObjects()) { | |||
332 | m_object_cache_ap = llvm::make_unique<ObjectDumper>(); | |||
333 | m_execution_engine_ap->setObjectCache(m_object_cache_ap.get()); | |||
334 | } | |||
335 | ||||
336 | // Make sure we see all sections, including ones that don't have | |||
337 | // relocations... | |||
338 | m_execution_engine_ap->setProcessAllSections(true); | |||
339 | ||||
340 | m_execution_engine_ap->DisableLazyCompilation(); | |||
341 | ||||
342 | for (llvm::Function &function : *m_module) { | |||
343 | if (function.isDeclaration() || function.hasPrivateLinkage()) | |||
344 | continue; | |||
345 | ||||
346 | const bool external = | |||
347 | function.hasExternalLinkage() || function.hasLinkOnceODRLinkage(); | |||
348 | ||||
349 | void *fun_ptr = m_execution_engine_ap->getPointerToFunction(&function); | |||
350 | ||||
351 | if (!error.Success()) { | |||
352 | // We got an error through our callback! | |||
353 | return; | |||
354 | } | |||
355 | ||||
356 | if (!fun_ptr) { | |||
357 | error.SetErrorToGenericError(); | |||
358 | error.SetErrorStringWithFormat( | |||
359 | "'%s' was in the JITted module but wasn't lowered", | |||
360 | function.getName().str().c_str()); | |||
361 | return; | |||
362 | } | |||
363 | m_jitted_functions.push_back(JittedFunction( | |||
364 | function.getName().str().c_str(), external, (lldb::addr_t)fun_ptr)); | |||
365 | } | |||
366 | ||||
367 | CommitAllocations(process_sp); | |||
368 | ReportAllocations(*m_execution_engine_ap); | |||
369 | ||||
370 | // We have to do this after calling ReportAllocations because for the MCJIT, | |||
371 | // getGlobalValueAddress | |||
372 | // will cause the JIT to perform all relocations. That can only be done once, | |||
373 | // and has to happen | |||
374 | // after we do the remapping from local -> remote. | |||
375 | // That means we don't know the local address of the Variables, but we don't | |||
376 | // need that for anything, | |||
377 | // so that's okay. | |||
378 | ||||
379 | std::function<void(llvm::GlobalValue &)> RegisterOneValue = [this]( | |||
380 | llvm::GlobalValue &val) { | |||
381 | if (val.hasExternalLinkage() && !val.isDeclaration()) { | |||
382 | uint64_t var_ptr_addr = | |||
383 | m_execution_engine_ap->getGlobalValueAddress(val.getName().str()); | |||
384 | ||||
385 | lldb::addr_t remote_addr = GetRemoteAddressForLocal(var_ptr_addr); | |||
386 | ||||
387 | // This is a really unfortunae API that sometimes returns local addresses | |||
388 | // and sometimes returns remote addresses, based on whether | |||
389 | // the variable was relocated during ReportAllocations or not. | |||
390 | ||||
391 | if (remote_addr == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
392 | remote_addr = var_ptr_addr; | |||
393 | } | |||
394 | ||||
395 | if (var_ptr_addr != 0) | |||
396 | m_jitted_global_variables.push_back(JittedGlobalVariable( | |||
397 | val.getName().str().c_str(), LLDB_INVALID_ADDRESS(18446744073709551615UL), remote_addr)); | |||
398 | } | |||
399 | }; | |||
400 | ||||
401 | for (llvm::GlobalVariable &global_var : m_module->getGlobalList()) { | |||
402 | RegisterOneValue(global_var); | |||
403 | } | |||
404 | ||||
405 | for (llvm::GlobalAlias &global_alias : m_module->getAliasList()) { | |||
406 | RegisterOneValue(global_alias); | |||
407 | } | |||
408 | ||||
409 | WriteData(process_sp); | |||
410 | ||||
411 | if (m_failed_lookups.size()) { | |||
412 | StreamString ss; | |||
413 | ||||
414 | ss.PutCString("Couldn't lookup symbols:\n"); | |||
415 | ||||
416 | bool emitNewLine = false; | |||
417 | ||||
418 | for (const ConstString &failed_lookup : m_failed_lookups) { | |||
419 | if (emitNewLine) | |||
420 | ss.PutCString("\n"); | |||
421 | emitNewLine = true; | |||
422 | ss.PutCString(" "); | |||
423 | ss.PutCString(Mangled(failed_lookup) | |||
424 | .GetDemangledName(lldb::eLanguageTypeObjC_plus_plus) | |||
425 | .AsCString()); | |||
426 | } | |||
427 | ||||
428 | m_failed_lookups.clear(); | |||
429 | ||||
430 | error.SetErrorString(ss.GetString()); | |||
431 | ||||
432 | return; | |||
433 | } | |||
434 | ||||
435 | m_function_load_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
436 | m_function_end_load_addr = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
437 | ||||
438 | for (JittedFunction &jitted_function : m_jitted_functions) { | |||
439 | jitted_function.m_remote_addr = | |||
440 | GetRemoteAddressForLocal(jitted_function.m_local_addr); | |||
441 | ||||
442 | if (!m_name.IsEmpty() && jitted_function.m_name == m_name) { | |||
443 | AddrRange func_range = | |||
444 | GetRemoteRangeForLocal(jitted_function.m_local_addr); | |||
445 | m_function_end_load_addr = func_range.first + func_range.second; | |||
446 | m_function_load_addr = jitted_function.m_remote_addr; | |||
447 | } | |||
448 | } | |||
449 | ||||
450 | if (log) { | |||
451 | log->Printf("Code can be run in the target."); | |||
452 | ||||
453 | StreamString disassembly_stream; | |||
454 | ||||
455 | Status err = DisassembleFunction(disassembly_stream, process_sp); | |||
456 | ||||
457 | if (!err.Success()) { | |||
458 | log->Printf("Couldn't disassemble function : %s", | |||
459 | err.AsCString("unknown error")); | |||
460 | } else { | |||
461 | log->Printf("Function disassembly:\n%s", disassembly_stream.GetData()); | |||
462 | } | |||
463 | ||||
464 | log->Printf("Sections: "); | |||
465 | for (AllocationRecord &record : m_records) { | |||
466 | if (record.m_process_address != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
467 | record.dump(log); | |||
468 | ||||
469 | DataBufferHeap my_buffer(record.m_size, 0); | |||
470 | Status err; | |||
471 | ReadMemory(my_buffer.GetBytes(), record.m_process_address, | |||
472 | record.m_size, err); | |||
473 | ||||
474 | if (err.Success()) { | |||
475 | DataExtractor my_extractor(my_buffer.GetBytes(), | |||
476 | my_buffer.GetByteSize(), | |||
477 | lldb::eByteOrderBig, 8); | |||
478 | my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), | |||
479 | record.m_process_address, 16, | |||
480 | DataExtractor::TypeUInt8); | |||
481 | } | |||
482 | } else { | |||
483 | record.dump(log); | |||
484 | ||||
485 | DataExtractor my_extractor((const void *)record.m_host_address, | |||
486 | record.m_size, lldb::eByteOrderBig, 8); | |||
487 | my_extractor.PutToLog(log, 0, record.m_size, record.m_host_address, 16, | |||
488 | DataExtractor::TypeUInt8); | |||
489 | } | |||
490 | } | |||
491 | } | |||
492 | ||||
493 | func_addr = m_function_load_addr; | |||
494 | func_end = m_function_end_load_addr; | |||
495 | ||||
496 | return; | |||
497 | } | |||
498 | ||||
499 | IRExecutionUnit::~IRExecutionUnit() { | |||
500 | m_module_ap.reset(); | |||
501 | m_execution_engine_ap.reset(); | |||
502 | m_context_ap.reset(); | |||
503 | } | |||
504 | ||||
505 | IRExecutionUnit::MemoryManager::MemoryManager(IRExecutionUnit &parent) | |||
506 | : m_default_mm_ap(new llvm::SectionMemoryManager()), m_parent(parent) {} | |||
507 | ||||
508 | IRExecutionUnit::MemoryManager::~MemoryManager() {} | |||
509 | ||||
510 | lldb::SectionType IRExecutionUnit::GetSectionTypeFromSectionName( | |||
511 | const llvm::StringRef &name, IRExecutionUnit::AllocationKind alloc_kind) { | |||
512 | lldb::SectionType sect_type = lldb::eSectionTypeCode; | |||
513 | switch (alloc_kind) { | |||
514 | case AllocationKind::Stub: | |||
515 | sect_type = lldb::eSectionTypeCode; | |||
516 | break; | |||
517 | case AllocationKind::Code: | |||
518 | sect_type = lldb::eSectionTypeCode; | |||
519 | break; | |||
520 | case AllocationKind::Data: | |||
521 | sect_type = lldb::eSectionTypeData; | |||
522 | break; | |||
523 | case AllocationKind::Global: | |||
524 | sect_type = lldb::eSectionTypeData; | |||
525 | break; | |||
526 | case AllocationKind::Bytes: | |||
527 | sect_type = lldb::eSectionTypeOther; | |||
528 | break; | |||
529 | } | |||
530 | ||||
531 | if (!name.empty()) { | |||
532 | if (name.equals("__text") || name.equals(".text")) | |||
533 | sect_type = lldb::eSectionTypeCode; | |||
534 | else if (name.equals("__data") || name.equals(".data")) | |||
535 | sect_type = lldb::eSectionTypeCode; | |||
536 | else if (name.startswith("__debug_") || name.startswith(".debug_")) { | |||
537 | const uint32_t name_idx = name[0] == '_' ? 8 : 7; | |||
538 | llvm::StringRef dwarf_name(name.substr(name_idx)); | |||
539 | switch (dwarf_name[0]) { | |||
540 | case 'a': | |||
541 | if (dwarf_name.equals("abbrev")) | |||
542 | sect_type = lldb::eSectionTypeDWARFDebugAbbrev; | |||
543 | else if (dwarf_name.equals("aranges")) | |||
544 | sect_type = lldb::eSectionTypeDWARFDebugAranges; | |||
545 | else if (dwarf_name.equals("addr")) | |||
546 | sect_type = lldb::eSectionTypeDWARFDebugAddr; | |||
547 | break; | |||
548 | ||||
549 | case 'f': | |||
550 | if (dwarf_name.equals("frame")) | |||
551 | sect_type = lldb::eSectionTypeDWARFDebugFrame; | |||
552 | break; | |||
553 | ||||
554 | case 'i': | |||
555 | if (dwarf_name.equals("info")) | |||
556 | sect_type = lldb::eSectionTypeDWARFDebugInfo; | |||
557 | break; | |||
558 | ||||
559 | case 'l': | |||
560 | if (dwarf_name.equals("line")) | |||
561 | sect_type = lldb::eSectionTypeDWARFDebugLine; | |||
562 | else if (dwarf_name.equals("loc")) | |||
563 | sect_type = lldb::eSectionTypeDWARFDebugLoc; | |||
564 | break; | |||
565 | ||||
566 | case 'm': | |||
567 | if (dwarf_name.equals("macinfo")) | |||
568 | sect_type = lldb::eSectionTypeDWARFDebugMacInfo; | |||
569 | break; | |||
570 | ||||
571 | case 'p': | |||
572 | if (dwarf_name.equals("pubnames")) | |||
573 | sect_type = lldb::eSectionTypeDWARFDebugPubNames; | |||
574 | else if (dwarf_name.equals("pubtypes")) | |||
575 | sect_type = lldb::eSectionTypeDWARFDebugPubTypes; | |||
576 | break; | |||
577 | ||||
578 | case 's': | |||
579 | if (dwarf_name.equals("str")) | |||
580 | sect_type = lldb::eSectionTypeDWARFDebugStr; | |||
581 | else if (dwarf_name.equals("str_offsets")) | |||
582 | sect_type = lldb::eSectionTypeDWARFDebugStrOffsets; | |||
583 | break; | |||
584 | ||||
585 | case 'r': | |||
586 | if (dwarf_name.equals("ranges")) | |||
587 | sect_type = lldb::eSectionTypeDWARFDebugRanges; | |||
588 | break; | |||
589 | ||||
590 | default: | |||
591 | break; | |||
592 | } | |||
593 | } else if (name.startswith("__apple_") || name.startswith(".apple_")) { | |||
594 | #if 0 | |||
595 | const uint32_t name_idx = name[0] == '_' ? 8 : 7; | |||
596 | llvm::StringRef apple_name(name.substr(name_idx)); | |||
597 | switch (apple_name[0]) | |||
598 | { | |||
599 | case 'n': | |||
600 | if (apple_name.equals("names")) | |||
601 | sect_type = lldb::eSectionTypeDWARFAppleNames; | |||
602 | else if (apple_name.equals("namespac") || apple_name.equals("namespaces")) | |||
603 | sect_type = lldb::eSectionTypeDWARFAppleNamespaces; | |||
604 | break; | |||
605 | case 't': | |||
606 | if (apple_name.equals("types")) | |||
607 | sect_type = lldb::eSectionTypeDWARFAppleTypes; | |||
608 | break; | |||
609 | case 'o': | |||
610 | if (apple_name.equals("objc")) | |||
611 | sect_type = lldb::eSectionTypeDWARFAppleObjC; | |||
612 | break; | |||
613 | default: | |||
614 | break; | |||
615 | } | |||
616 | #else | |||
617 | sect_type = lldb::eSectionTypeInvalid; | |||
618 | #endif | |||
619 | } else if (name.equals("__objc_imageinfo")) | |||
620 | sect_type = lldb::eSectionTypeOther; | |||
621 | } | |||
622 | return sect_type; | |||
623 | } | |||
624 | ||||
625 | uint8_t *IRExecutionUnit::MemoryManager::allocateCodeSection( | |||
626 | uintptr_t Size, unsigned Alignment, unsigned SectionID, | |||
627 | llvm::StringRef SectionName) { | |||
628 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
629 | ||||
630 | uint8_t *return_value = m_default_mm_ap->allocateCodeSection( | |||
631 | Size, Alignment, SectionID, SectionName); | |||
632 | ||||
633 | m_parent.m_records.push_back(AllocationRecord( | |||
634 | (uintptr_t)return_value, | |||
635 | lldb::ePermissionsReadable | lldb::ePermissionsExecutable, | |||
636 | GetSectionTypeFromSectionName(SectionName, AllocationKind::Code), Size, | |||
637 | Alignment, SectionID, SectionName.str().c_str())); | |||
638 | ||||
639 | if (log) { | |||
640 | log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64"l" "x" | |||
641 | ", Alignment=%u, SectionID=%u) = %p", | |||
642 | (uint64_t)Size, Alignment, SectionID, (void *)return_value); | |||
643 | } | |||
644 | ||||
645 | if (m_parent.m_reported_allocations) { | |||
646 | Status err; | |||
647 | lldb::ProcessSP process_sp = | |||
648 | m_parent.GetBestExecutionContextScope()->CalculateProcess(); | |||
649 | ||||
650 | m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); | |||
651 | } | |||
652 | ||||
653 | return return_value; | |||
654 | } | |||
655 | ||||
656 | uint8_t *IRExecutionUnit::MemoryManager::allocateDataSection( | |||
657 | uintptr_t Size, unsigned Alignment, unsigned SectionID, | |||
658 | llvm::StringRef SectionName, bool IsReadOnly) { | |||
659 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
660 | ||||
661 | uint8_t *return_value = m_default_mm_ap->allocateDataSection( | |||
662 | Size, Alignment, SectionID, SectionName, IsReadOnly); | |||
663 | ||||
664 | uint32_t permissions = lldb::ePermissionsReadable; | |||
665 | if (!IsReadOnly) | |||
666 | permissions |= lldb::ePermissionsWritable; | |||
667 | m_parent.m_records.push_back(AllocationRecord( | |||
668 | (uintptr_t)return_value, permissions, | |||
669 | GetSectionTypeFromSectionName(SectionName, AllocationKind::Data), Size, | |||
670 | Alignment, SectionID, SectionName.str().c_str())); | |||
671 | if (log) { | |||
672 | log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64"l" "x" | |||
673 | ", Alignment=%u, SectionID=%u) = %p", | |||
674 | (uint64_t)Size, Alignment, SectionID, (void *)return_value); | |||
675 | } | |||
676 | ||||
677 | if (m_parent.m_reported_allocations) { | |||
678 | Status err; | |||
679 | lldb::ProcessSP process_sp = | |||
680 | m_parent.GetBestExecutionContextScope()->CalculateProcess(); | |||
681 | ||||
682 | m_parent.CommitOneAllocation(process_sp, err, m_parent.m_records.back()); | |||
683 | } | |||
684 | ||||
685 | return return_value; | |||
686 | } | |||
687 | ||||
688 | static ConstString | |||
689 | FindBestAlternateMangledName(const ConstString &demangled, | |||
690 | const lldb::LanguageType &lang_type, | |||
691 | const SymbolContext &sym_ctx) { | |||
692 | CPlusPlusLanguage::MethodName cpp_name(demangled); | |||
693 | std::string scope_qualified_name = cpp_name.GetScopeQualifiedName(); | |||
694 | ||||
695 | if (!scope_qualified_name.size()) | |||
696 | return ConstString(); | |||
697 | ||||
698 | if (!sym_ctx.module_sp) | |||
699 | return ConstString(); | |||
700 | ||||
701 | SymbolVendor *sym_vendor = sym_ctx.module_sp->GetSymbolVendor(); | |||
702 | if (!sym_vendor) | |||
703 | return ConstString(); | |||
704 | ||||
705 | lldb_private::SymbolFile *sym_file = sym_vendor->GetSymbolFile(); | |||
706 | if (!sym_file) | |||
707 | return ConstString(); | |||
708 | ||||
709 | std::vector<ConstString> alternates; | |||
710 | sym_file->GetMangledNamesForFunction(scope_qualified_name, alternates); | |||
711 | ||||
712 | std::vector<ConstString> param_and_qual_matches; | |||
713 | std::vector<ConstString> param_matches; | |||
714 | for (size_t i = 0; i < alternates.size(); i++) { | |||
715 | ConstString alternate_mangled_name = alternates[i]; | |||
716 | Mangled mangled(alternate_mangled_name, true); | |||
717 | ConstString demangled = mangled.GetDemangledName(lang_type); | |||
718 | ||||
719 | CPlusPlusLanguage::MethodName alternate_cpp_name(demangled); | |||
720 | if (!cpp_name.IsValid()) | |||
721 | continue; | |||
722 | ||||
723 | if (alternate_cpp_name.GetArguments() == cpp_name.GetArguments()) { | |||
724 | if (alternate_cpp_name.GetQualifiers() == cpp_name.GetQualifiers()) | |||
725 | param_and_qual_matches.push_back(alternate_mangled_name); | |||
726 | else | |||
727 | param_matches.push_back(alternate_mangled_name); | |||
728 | } | |||
729 | } | |||
730 | ||||
731 | if (param_and_qual_matches.size()) | |||
732 | return param_and_qual_matches[0]; // It is assumed that there will be only | |||
733 | // one! | |||
734 | else if (param_matches.size()) | |||
735 | return param_matches[0]; // Return one of them as a best match | |||
736 | else | |||
737 | return ConstString(); | |||
738 | } | |||
739 | ||||
740 | struct IRExecutionUnit::SearchSpec { | |||
741 | ConstString name; | |||
742 | uint32_t mask; | |||
743 | ||||
744 | SearchSpec(ConstString n, uint32_t m = lldb::eFunctionNameTypeFull) | |||
745 | : name(n), mask(m) {} | |||
746 | }; | |||
747 | ||||
748 | void IRExecutionUnit::CollectCandidateCNames( | |||
749 | std::vector<IRExecutionUnit::SearchSpec> &C_specs, | |||
750 | const ConstString &name) { | |||
751 | if (m_strip_underscore && name.AsCString()[0] == '_') | |||
| ||||
752 | C_specs.insert(C_specs.begin(), ConstString(&name.AsCString()[1])); | |||
753 | C_specs.push_back(SearchSpec(name)); | |||
754 | } | |||
755 | ||||
756 | void IRExecutionUnit::CollectCandidateCPlusPlusNames( | |||
757 | std::vector<IRExecutionUnit::SearchSpec> &CPP_specs, | |||
758 | const std::vector<SearchSpec> &C_specs, const SymbolContext &sc) { | |||
759 | for (const SearchSpec &C_spec : C_specs) { | |||
760 | const ConstString &name = C_spec.name; | |||
761 | ||||
762 | if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { | |||
763 | Mangled mangled(name, true); | |||
764 | ConstString demangled = | |||
765 | mangled.GetDemangledName(lldb::eLanguageTypeC_plus_plus); | |||
766 | ||||
767 | if (demangled) { | |||
768 | ConstString best_alternate_mangled_name = FindBestAlternateMangledName( | |||
769 | demangled, lldb::eLanguageTypeC_plus_plus, sc); | |||
770 | ||||
771 | if (best_alternate_mangled_name) { | |||
772 | CPP_specs.push_back(best_alternate_mangled_name); | |||
773 | } | |||
774 | ||||
775 | CPP_specs.push_back(SearchSpec(demangled, lldb::eFunctionNameTypeFull)); | |||
776 | } | |||
777 | } | |||
778 | ||||
779 | std::set<ConstString> alternates; | |||
780 | CPlusPlusLanguage::FindAlternateFunctionManglings(name, alternates); | |||
781 | CPP_specs.insert(CPP_specs.end(), alternates.begin(), alternates.end()); | |||
782 | } | |||
783 | } | |||
784 | ||||
785 | void IRExecutionUnit::CollectFallbackNames( | |||
786 | std::vector<SearchSpec> &fallback_specs, | |||
787 | const std::vector<SearchSpec> &C_specs) { | |||
788 | // As a last-ditch fallback, try the base name for C++ names. It's terrible, | |||
789 | // but the DWARF doesn't always encode "extern C" correctly. | |||
790 | ||||
791 | for (const SearchSpec &C_spec : C_specs) { | |||
792 | const ConstString &name = C_spec.name; | |||
793 | ||||
794 | if (CPlusPlusLanguage::IsCPPMangledName(name.GetCString())) { | |||
795 | Mangled mangled_name(name); | |||
796 | ConstString demangled_name = | |||
797 | mangled_name.GetDemangledName(lldb::eLanguageTypeC_plus_plus); | |||
798 | if (!demangled_name.IsEmpty()) { | |||
799 | const char *demangled_cstr = demangled_name.AsCString(); | |||
800 | const char *lparen_loc = strchr(demangled_cstr, '('); | |||
801 | if (lparen_loc) { | |||
802 | llvm::StringRef base_name(demangled_cstr, | |||
803 | lparen_loc - demangled_cstr); | |||
804 | fallback_specs.push_back(ConstString(base_name)); | |||
805 | } | |||
806 | } | |||
807 | } | |||
808 | } | |||
809 | } | |||
810 | ||||
811 | lldb::addr_t IRExecutionUnit::FindInSymbols( | |||
812 | const std::vector<IRExecutionUnit::SearchSpec> &specs, | |||
813 | const lldb_private::SymbolContext &sc) { | |||
814 | Target *target = sc.target_sp.get(); | |||
815 | ||||
816 | if (!target) { | |||
817 | // we shouldn't be doing any symbol lookup at all without a target | |||
818 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
819 | } | |||
820 | ||||
821 | for (const SearchSpec &spec : specs) { | |||
822 | SymbolContextList sc_list; | |||
823 | ||||
824 | lldb::addr_t best_internal_load_address = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
825 | ||||
826 | std::function<bool(lldb::addr_t &, SymbolContextList &, | |||
827 | const lldb_private::SymbolContext &)> | |||
828 | get_external_load_address = [&best_internal_load_address, target]( | |||
829 | lldb::addr_t &load_address, SymbolContextList &sc_list, | |||
830 | const lldb_private::SymbolContext &sc) -> lldb::addr_t { | |||
831 | load_address = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
832 | ||||
833 | for (size_t si = 0, se = sc_list.GetSize(); si < se; ++si) { | |||
834 | SymbolContext candidate_sc; | |||
835 | ||||
836 | sc_list.GetContextAtIndex(si, candidate_sc); | |||
837 | ||||
838 | const bool is_external = | |||
839 | (candidate_sc.function) || | |||
840 | (candidate_sc.symbol && candidate_sc.symbol->IsExternal()); | |||
841 | if (candidate_sc.symbol) { | |||
842 | load_address = candidate_sc.symbol->ResolveCallableAddress(*target); | |||
843 | ||||
844 | if (load_address == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
845 | if (target->GetProcessSP()) | |||
846 | load_address = | |||
847 | candidate_sc.symbol->GetAddress().GetLoadAddress(target); | |||
848 | else | |||
849 | load_address = candidate_sc.symbol->GetAddress().GetFileAddress(); | |||
850 | } | |||
851 | } | |||
852 | ||||
853 | if (load_address == LLDB_INVALID_ADDRESS(18446744073709551615UL) && candidate_sc.function) { | |||
854 | if (target->GetProcessSP()) | |||
855 | load_address = candidate_sc.function->GetAddressRange() | |||
856 | .GetBaseAddress() | |||
857 | .GetLoadAddress(target); | |||
858 | else | |||
859 | load_address = candidate_sc.function->GetAddressRange() | |||
860 | .GetBaseAddress() | |||
861 | .GetFileAddress(); | |||
862 | } | |||
863 | ||||
864 | if (load_address != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
865 | if (is_external) { | |||
866 | return true; | |||
867 | } else if (best_internal_load_address == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
868 | best_internal_load_address = load_address; | |||
869 | load_address = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
870 | } | |||
871 | } | |||
872 | } | |||
873 | ||||
874 | return false; | |||
875 | }; | |||
876 | ||||
877 | if (sc.module_sp) { | |||
878 | sc.module_sp->FindFunctions(spec.name, NULL__null, spec.mask, | |||
879 | true, // include_symbols | |||
880 | false, // include_inlines | |||
881 | true, // append | |||
882 | sc_list); | |||
883 | } | |||
884 | ||||
885 | lldb::addr_t load_address = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
886 | ||||
887 | if (get_external_load_address(load_address, sc_list, sc)) { | |||
888 | return load_address; | |||
889 | } else { | |||
890 | sc_list.Clear(); | |||
891 | } | |||
892 | ||||
893 | if (sc_list.GetSize() == 0 && sc.target_sp) { | |||
894 | sc.target_sp->GetImages().FindFunctions(spec.name, spec.mask, | |||
895 | true, // include_symbols | |||
896 | false, // include_inlines | |||
897 | true, // append | |||
898 | sc_list); | |||
899 | } | |||
900 | ||||
901 | if (get_external_load_address(load_address, sc_list, sc)) { | |||
902 | return load_address; | |||
903 | } else { | |||
904 | sc_list.Clear(); | |||
905 | } | |||
906 | ||||
907 | if (sc_list.GetSize() == 0 && sc.target_sp) { | |||
908 | sc.target_sp->GetImages().FindSymbolsWithNameAndType( | |||
909 | spec.name, lldb::eSymbolTypeAny, sc_list); | |||
910 | } | |||
911 | ||||
912 | if (get_external_load_address(load_address, sc_list, sc)) { | |||
913 | return load_address; | |||
914 | } | |||
915 | // if there are any searches we try after this, add an sc_list.Clear() in an | |||
916 | // "else" clause here | |||
917 | ||||
918 | if (best_internal_load_address != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
919 | return best_internal_load_address; | |||
920 | } | |||
921 | } | |||
922 | ||||
923 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
924 | } | |||
925 | ||||
926 | lldb::addr_t | |||
927 | IRExecutionUnit::FindInRuntimes(const std::vector<SearchSpec> &specs, | |||
928 | const lldb_private::SymbolContext &sc) { | |||
929 | lldb::TargetSP target_sp = sc.target_sp; | |||
930 | ||||
931 | if (!target_sp) { | |||
932 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
933 | } | |||
934 | ||||
935 | lldb::ProcessSP process_sp = sc.target_sp->GetProcessSP(); | |||
936 | ||||
937 | if (!process_sp) { | |||
938 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
939 | } | |||
940 | ||||
941 | ObjCLanguageRuntime *runtime = process_sp->GetObjCLanguageRuntime(); | |||
942 | ||||
943 | if (runtime) { | |||
944 | for (const SearchSpec &spec : specs) { | |||
945 | lldb::addr_t symbol_load_addr = runtime->LookupRuntimeSymbol(spec.name); | |||
946 | ||||
947 | if (symbol_load_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
948 | return symbol_load_addr; | |||
949 | } | |||
950 | } | |||
951 | ||||
952 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
953 | } | |||
954 | ||||
955 | lldb::addr_t IRExecutionUnit::FindInUserDefinedSymbols( | |||
956 | const std::vector<SearchSpec> &specs, | |||
957 | const lldb_private::SymbolContext &sc) { | |||
958 | lldb::TargetSP target_sp = sc.target_sp; | |||
959 | ||||
960 | for (const SearchSpec &spec : specs) { | |||
961 | lldb::addr_t symbol_load_addr = target_sp->GetPersistentSymbol(spec.name); | |||
962 | ||||
963 | if (symbol_load_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
964 | return symbol_load_addr; | |||
965 | } | |||
966 | ||||
967 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
968 | } | |||
969 | ||||
970 | lldb::addr_t | |||
971 | IRExecutionUnit::FindSymbol(const lldb_private::ConstString &name) { | |||
972 | std::vector<SearchSpec> candidate_C_names; | |||
973 | std::vector<SearchSpec> candidate_CPlusPlus_names; | |||
974 | ||||
975 | CollectCandidateCNames(candidate_C_names, name); | |||
976 | ||||
977 | lldb::addr_t ret = FindInSymbols(candidate_C_names, m_sym_ctx); | |||
978 | if (ret == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
979 | ret = FindInRuntimes(candidate_C_names, m_sym_ctx); | |||
980 | ||||
981 | if (ret == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
982 | ret = FindInUserDefinedSymbols(candidate_C_names, m_sym_ctx); | |||
983 | ||||
984 | if (ret == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
985 | CollectCandidateCPlusPlusNames(candidate_CPlusPlus_names, candidate_C_names, | |||
986 | m_sym_ctx); | |||
987 | ret = FindInSymbols(candidate_CPlusPlus_names, m_sym_ctx); | |||
988 | } | |||
989 | ||||
990 | if (ret == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
991 | std::vector<SearchSpec> candidate_fallback_names; | |||
992 | ||||
993 | CollectFallbackNames(candidate_fallback_names, candidate_C_names); | |||
994 | ret = FindInSymbols(candidate_fallback_names, m_sym_ctx); | |||
995 | } | |||
996 | ||||
997 | return ret; | |||
998 | } | |||
999 | ||||
1000 | void IRExecutionUnit::GetStaticInitializers( | |||
1001 | std::vector<lldb::addr_t> &static_initializers) { | |||
1002 | if (llvm::GlobalVariable *global_ctors = | |||
1003 | m_module->getNamedGlobal("llvm.global_ctors")) { | |||
1004 | if (llvm::ConstantArray *ctor_array = llvm::dyn_cast<llvm::ConstantArray>( | |||
1005 | global_ctors->getInitializer())) { | |||
1006 | for (llvm::Use &ctor_use : ctor_array->operands()) { | |||
1007 | if (llvm::ConstantStruct *ctor_struct = | |||
1008 | llvm::dyn_cast<llvm::ConstantStruct>(ctor_use)) { | |||
1009 | lldbassert(ctor_struct->getNumOperands() ==lldb_private::lldb_assert(ctor_struct->getNumOperands() == 3, "ctor_struct->getNumOperands() == 3", __FUNCTION__, "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/lldb/source/Expression/IRExecutionUnit.cpp" , 1010) | |||
1010 | 3)lldb_private::lldb_assert(ctor_struct->getNumOperands() == 3, "ctor_struct->getNumOperands() == 3", __FUNCTION__, "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/lldb/source/Expression/IRExecutionUnit.cpp" , 1010); // this is standardized | |||
1011 | if (llvm::Function *ctor_function = | |||
1012 | llvm::dyn_cast<llvm::Function>(ctor_struct->getOperand(1))) { | |||
1013 | ConstString ctor_function_name_cs(ctor_function->getName().str()); | |||
1014 | ||||
1015 | for (JittedFunction &jitted_function : m_jitted_functions) { | |||
1016 | if (ctor_function_name_cs == jitted_function.m_name) { | |||
1017 | if (jitted_function.m_remote_addr != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1018 | static_initializers.push_back(jitted_function.m_remote_addr); | |||
1019 | } | |||
1020 | break; | |||
1021 | } | |||
1022 | } | |||
1023 | } | |||
1024 | } | |||
1025 | } | |||
1026 | } | |||
1027 | } | |||
1028 | } | |||
1029 | ||||
1030 | uint64_t | |||
1031 | IRExecutionUnit::MemoryManager::getSymbolAddress(const std::string &Name) { | |||
1032 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
1033 | ||||
1034 | ConstString name_cs(Name.c_str()); | |||
1035 | ||||
1036 | lldb::addr_t ret = m_parent.FindSymbol(name_cs); | |||
1037 | ||||
1038 | if (ret == LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1039 | if (log) | |||
1040 | log->Printf( | |||
1041 | "IRExecutionUnit::getSymbolAddress(Name=\"%s\") = <not found>", | |||
1042 | Name.c_str()); | |||
1043 | ||||
1044 | m_parent.ReportSymbolLookupError(name_cs); | |||
1045 | return 0xbad0bad0; | |||
1046 | } else { | |||
1047 | if (log) | |||
1048 | log->Printf("IRExecutionUnit::getSymbolAddress(Name=\"%s\") = %" PRIx64"l" "x", | |||
1049 | Name.c_str(), ret); | |||
1050 | return ret; | |||
1051 | } | |||
1052 | } | |||
1053 | ||||
1054 | void *IRExecutionUnit::MemoryManager::getPointerToNamedFunction( | |||
1055 | const std::string &Name, bool AbortOnFailure) { | |||
1056 | assert(sizeof(void *) == 8)((sizeof(void *) == 8) ? static_cast<void> (0) : __assert_fail ("sizeof(void *) == 8", "/tmp/buildd/llvm-toolchain-snapshot-5.0~svn306458/tools/lldb/source/Expression/IRExecutionUnit.cpp" , 1056, __PRETTY_FUNCTION__)); | |||
1057 | ||||
1058 | return (void *)getSymbolAddress(Name); | |||
| ||||
1059 | } | |||
1060 | ||||
1061 | lldb::addr_t | |||
1062 | IRExecutionUnit::GetRemoteAddressForLocal(lldb::addr_t local_address) { | |||
1063 | Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_EXPRESSIONS(1u << 8))); | |||
1064 | ||||
1065 | for (AllocationRecord &record : m_records) { | |||
1066 | if (local_address >= record.m_host_address && | |||
1067 | local_address < record.m_host_address + record.m_size) { | |||
1068 | if (record.m_process_address == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1069 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1070 | ||||
1071 | lldb::addr_t ret = | |||
1072 | record.m_process_address + (local_address - record.m_host_address); | |||
1073 | ||||
1074 | if (log) { | |||
1075 | log->Printf( | |||
1076 | "IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64"l" "x" | |||
1077 | " in [0x%" PRIx64"l" "x" "..0x%" PRIx64"l" "x" "], and returned 0x%" PRIx64"l" "x" | |||
1078 | " from [0x%" PRIx64"l" "x" "..0x%" PRIx64"l" "x" "].", | |||
1079 | local_address, (uint64_t)record.m_host_address, | |||
1080 | (uint64_t)record.m_host_address + (uint64_t)record.m_size, ret, | |||
1081 | record.m_process_address, record.m_process_address + record.m_size); | |||
1082 | } | |||
1083 | ||||
1084 | return ret; | |||
1085 | } | |||
1086 | } | |||
1087 | ||||
1088 | return LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1089 | } | |||
1090 | ||||
1091 | IRExecutionUnit::AddrRange | |||
1092 | IRExecutionUnit::GetRemoteRangeForLocal(lldb::addr_t local_address) { | |||
1093 | for (AllocationRecord &record : m_records) { | |||
1094 | if (local_address >= record.m_host_address && | |||
1095 | local_address < record.m_host_address + record.m_size) { | |||
1096 | if (record.m_process_address == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1097 | return AddrRange(0, 0); | |||
1098 | ||||
1099 | return AddrRange(record.m_process_address, record.m_size); | |||
1100 | } | |||
1101 | } | |||
1102 | ||||
1103 | return AddrRange(0, 0); | |||
1104 | } | |||
1105 | ||||
1106 | bool IRExecutionUnit::CommitOneAllocation(lldb::ProcessSP &process_sp, | |||
1107 | Status &error, | |||
1108 | AllocationRecord &record) { | |||
1109 | if (record.m_process_address != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1110 | return true; | |||
1111 | } | |||
1112 | ||||
1113 | switch (record.m_sect_type) { | |||
1114 | case lldb::eSectionTypeInvalid: | |||
1115 | case lldb::eSectionTypeDWARFDebugAbbrev: | |||
1116 | case lldb::eSectionTypeDWARFDebugAddr: | |||
1117 | case lldb::eSectionTypeDWARFDebugAranges: | |||
1118 | case lldb::eSectionTypeDWARFDebugFrame: | |||
1119 | case lldb::eSectionTypeDWARFDebugInfo: | |||
1120 | case lldb::eSectionTypeDWARFDebugLine: | |||
1121 | case lldb::eSectionTypeDWARFDebugLoc: | |||
1122 | case lldb::eSectionTypeDWARFDebugMacInfo: | |||
1123 | case lldb::eSectionTypeDWARFDebugPubNames: | |||
1124 | case lldb::eSectionTypeDWARFDebugPubTypes: | |||
1125 | case lldb::eSectionTypeDWARFDebugRanges: | |||
1126 | case lldb::eSectionTypeDWARFDebugStr: | |||
1127 | case lldb::eSectionTypeDWARFDebugStrOffsets: | |||
1128 | case lldb::eSectionTypeDWARFAppleNames: | |||
1129 | case lldb::eSectionTypeDWARFAppleTypes: | |||
1130 | case lldb::eSectionTypeDWARFAppleNamespaces: | |||
1131 | case lldb::eSectionTypeDWARFAppleObjC: | |||
1132 | error.Clear(); | |||
1133 | break; | |||
1134 | default: | |||
1135 | const bool zero_memory = false; | |||
1136 | record.m_process_address = | |||
1137 | Malloc(record.m_size, record.m_alignment, record.m_permissions, | |||
1138 | eAllocationPolicyProcessOnly, zero_memory, error); | |||
1139 | break; | |||
1140 | } | |||
1141 | ||||
1142 | return error.Success(); | |||
1143 | } | |||
1144 | ||||
1145 | bool IRExecutionUnit::CommitAllocations(lldb::ProcessSP &process_sp) { | |||
1146 | bool ret = true; | |||
1147 | ||||
1148 | lldb_private::Status err; | |||
1149 | ||||
1150 | for (AllocationRecord &record : m_records) { | |||
1151 | ret = CommitOneAllocation(process_sp, err, record); | |||
1152 | ||||
1153 | if (!ret) { | |||
1154 | break; | |||
1155 | } | |||
1156 | } | |||
1157 | ||||
1158 | if (!ret) { | |||
1159 | for (AllocationRecord &record : m_records) { | |||
1160 | if (record.m_process_address != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1161 | Free(record.m_process_address, err); | |||
1162 | record.m_process_address = LLDB_INVALID_ADDRESS(18446744073709551615UL); | |||
1163 | } | |||
1164 | } | |||
1165 | } | |||
1166 | ||||
1167 | return ret; | |||
1168 | } | |||
1169 | ||||
1170 | void IRExecutionUnit::ReportAllocations(llvm::ExecutionEngine &engine) { | |||
1171 | m_reported_allocations = true; | |||
1172 | ||||
1173 | for (AllocationRecord &record : m_records) { | |||
1174 | if (record.m_process_address == LLDB_INVALID_ADDRESS(18446744073709551615UL)) | |||
1175 | continue; | |||
1176 | ||||
1177 | if (record.m_section_id == eSectionIDInvalid) | |||
1178 | continue; | |||
1179 | ||||
1180 | engine.mapSectionAddress((void *)record.m_host_address, | |||
1181 | record.m_process_address); | |||
1182 | } | |||
1183 | ||||
1184 | // Trigger re-application of relocations. | |||
1185 | engine.finalizeObject(); | |||
1186 | } | |||
1187 | ||||
1188 | bool IRExecutionUnit::WriteData(lldb::ProcessSP &process_sp) { | |||
1189 | bool wrote_something = false; | |||
1190 | for (AllocationRecord &record : m_records) { | |||
1191 | if (record.m_process_address != LLDB_INVALID_ADDRESS(18446744073709551615UL)) { | |||
1192 | lldb_private::Status err; | |||
1193 | WriteMemory(record.m_process_address, (uint8_t *)record.m_host_address, | |||
1194 | record.m_size, err); | |||
1195 | if (err.Success()) | |||
1196 | wrote_something = true; | |||
1197 | } | |||
1198 | } | |||
1199 | return wrote_something; | |||
1200 | } | |||
1201 | ||||
1202 | void IRExecutionUnit::AllocationRecord::dump(Log *log) { | |||
1203 | if (!log) | |||
1204 | return; | |||
1205 | ||||
1206 | log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d, name %s)", | |||
1207 | (unsigned long long)m_host_address, (unsigned long long)m_size, | |||
1208 | (unsigned long long)m_process_address, (unsigned)m_alignment, | |||
1209 | (unsigned)m_section_id, m_name.c_str()); | |||
1210 | } | |||
1211 | ||||
1212 | lldb::ByteOrder IRExecutionUnit::GetByteOrder() const { | |||
1213 | ExecutionContext exe_ctx(GetBestExecutionContextScope()); | |||
1214 | return exe_ctx.GetByteOrder(); | |||
1215 | } | |||
1216 | ||||
1217 | uint32_t IRExecutionUnit::GetAddressByteSize() const { | |||
1218 | ExecutionContext exe_ctx(GetBestExecutionContextScope()); | |||
1219 | return exe_ctx.GetAddressByteSize(); | |||
1220 | } | |||
1221 | ||||
1222 | void IRExecutionUnit::PopulateSymtab(lldb_private::ObjectFile *obj_file, | |||
1223 | lldb_private::Symtab &symtab) { | |||
1224 | // No symbols yet... | |||
1225 | } | |||
1226 | ||||
1227 | void IRExecutionUnit::PopulateSectionList( | |||
1228 | lldb_private::ObjectFile *obj_file, | |||
1229 | lldb_private::SectionList §ion_list) { | |||
1230 | for (AllocationRecord &record : m_records) { | |||
1231 | if (record.m_size > 0) { | |||
1232 | lldb::SectionSP section_sp(new lldb_private::Section( | |||
1233 | obj_file->GetModule(), obj_file, record.m_section_id, | |||
1234 | ConstString(record.m_name), record.m_sect_type, | |||
1235 | record.m_process_address, record.m_size, | |||
1236 | record.m_host_address, // file_offset (which is the host address for | |||
1237 | // the data) | |||
1238 | record.m_size, // file_size | |||
1239 | 0, | |||
1240 | record.m_permissions)); // flags | |||
1241 | section_list.AddSection(section_sp); | |||
1242 | } | |||
1243 | } | |||
1244 | } | |||
1245 | ||||
1246 | bool IRExecutionUnit::GetArchitecture(lldb_private::ArchSpec &arch) { | |||
1247 | ExecutionContext exe_ctx(GetBestExecutionContextScope()); | |||
1248 | Target *target = exe_ctx.GetTargetPtr(); | |||
1249 | if (target) | |||
1250 | arch = target->GetArchitecture(); | |||
1251 | else | |||
1252 | arch.Clear(); | |||
1253 | return arch.IsValid(); | |||
1254 | } | |||
1255 | ||||
1256 | lldb::ModuleSP IRExecutionUnit::GetJITModule() { | |||
1257 | ExecutionContext exe_ctx(GetBestExecutionContextScope()); | |||
1258 | Target *target = exe_ctx.GetTargetPtr(); | |||
1259 | if (target) { | |||
1260 | lldb::ModuleSP jit_module_sp = lldb_private::Module::CreateJITModule( | |||
1261 | std::static_pointer_cast<lldb_private::ObjectFileJITDelegate>( | |||
1262 | shared_from_this())); | |||
1263 | if (jit_module_sp) { | |||
1264 | bool changed = false; | |||
1265 | jit_module_sp->SetLoadAddress(*target, 0, true, changed); | |||
1266 | } | |||
1267 | return jit_module_sp; | |||
1268 | } | |||
1269 | return lldb::ModuleSP(); | |||
1270 | } |