blob: c3a2f8aacb78d802ee5db87fbba667c7f654097c [file] [log] [blame]
Sean Callanan8dfb68e2013-03-19 00:10:07 +00001//===-- 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// C Includes
11// C++ Includes
12// Other libraries and framework includes
13#include "llvm/ExecutionEngine/ExecutionEngine.h"
Sean Callanan44bc6572013-03-27 03:09:55 +000014#include "llvm/IR/LLVMContext.h"
Sean Callanan8dfb68e2013-03-19 00:10:07 +000015#include "llvm/IR/Module.h"
Sean Callanan44bc6572013-03-27 03:09:55 +000016#include "llvm/Support/SourceMgr.h"
Sean Callanan8dfb68e2013-03-19 00:10:07 +000017// Project includes
18#include "lldb/Core/DataBufferHeap.h"
19#include "lldb/Core/DataExtractor.h"
20#include "lldb/Core/Disassembler.h"
21#include "lldb/Core/Log.h"
22#include "lldb/Expression/IRExecutionUnit.h"
23#include "lldb/Target/ExecutionContext.h"
24#include "lldb/Target/Target.h"
25
26using namespace lldb_private;
27
28IRExecutionUnit::IRExecutionUnit (std::auto_ptr<llvm::Module> &module_ap,
29 ConstString &name,
30 lldb::ProcessSP process_sp,
31 std::vector<std::string> &cpu_features) :
32 m_process_wp(process_sp),
33 m_module_ap(module_ap),
34 m_module(m_module_ap.get()),
Sean Callanan2c047352013-03-19 23:03:21 +000035 m_cpu_features(cpu_features),
Sean Callanan8dfb68e2013-03-19 00:10:07 +000036 m_name(name),
37 m_did_jit(false),
38 m_function_load_addr(LLDB_INVALID_ADDRESS),
39 m_function_end_load_addr(LLDB_INVALID_ADDRESS)
40{
Sean Callanan8dfb68e2013-03-19 00:10:07 +000041}
42
43lldb::addr_t
44IRExecutionUnit::WriteNow (const uint8_t *bytes,
45 size_t size,
46 Error &error)
47{
48 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
49
Sean Callanan2c047352013-03-19 23:03:21 +000050 auto iter = m_allocations.insert(m_allocations.end(), Allocation());
51
52 Allocation &allocation(*iter);
53
Sean Callanan8dfb68e2013-03-19 00:10:07 +000054 allocation.m_size = size;
55 allocation.m_alignment = 8;
Sean Callanan2c047352013-03-19 23:03:21 +000056 allocation.m_data.reset(new DataBufferHeap(bytes, size));
57 allocation.m_local_start = (uintptr_t)allocation.m_data->GetBytes();
Sean Callanan8dfb68e2013-03-19 00:10:07 +000058 allocation.m_section_id = Allocation::eSectionIDNone;
59
60 lldb_private::Error err;
61
62 size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
63
64 if (allocation_size == 0)
65 allocation_size = 1;
66
67 lldb::ProcessSP process_sp = m_process_wp.lock();
68
69 if (!process_sp)
70 {
71 err.SetErrorToGenericError();
72 err.SetErrorString("Couldn't find the process");
Sean Callanan2c047352013-03-19 23:03:21 +000073 return LLDB_INVALID_ADDRESS;
Sean Callanan8dfb68e2013-03-19 00:10:07 +000074 }
75
76 allocation.m_remote_allocation = process_sp->AllocateMemory(allocation_size,
77 (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
78 err);
79
80 if (!err.Success())
81 return LLDB_INVALID_ADDRESS;
82
83 process_sp->WriteMemory(allocation.m_remote_allocation, bytes, size, err);
84
85 if (!err.Success())
86 {
87 process_sp->DeallocateMemory(allocation.m_remote_allocation);
88 allocation.m_remote_allocation = LLDB_INVALID_ADDRESS;
89 return LLDB_INVALID_ADDRESS;
90 }
91
92 uint64_t mask = allocation.m_alignment - 1;
93
94 allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
95
96 allocation.m_allocated = true;
97
98 if (log)
99 {
100 log->Printf("IRExecutionUnit::WriteNow() wrote to 0x%llx", allocation.m_remote_start);
101 allocation.dump(log);
102 }
Sean Callanan2c047352013-03-19 23:03:21 +0000103
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000104 return allocation.m_remote_start;
105}
106
107void
108IRExecutionUnit::FreeNow (lldb::addr_t allocation)
109{
110 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
111
112 if (allocation == LLDB_INVALID_ADDRESS)
113 return;
114
115 lldb::ProcessSP process_sp = m_process_wp.lock();
116
117 if (!process_sp)
118 return;
119
120 for (auto ai = m_allocations.begin(), ae = m_allocations.end();
121 ai != ae;
122 ++ai)
123 {
124 if (ai->m_remote_allocation == allocation)
125 {
126 m_allocations.erase(ai);
127 log->Printf("IRExecutionUnit::FreeNow() freed 0x%llx", allocation);
128 return;
129 }
130 }
131}
132
133Error
134IRExecutionUnit::DisassembleFunction (Stream &stream,
135 lldb::ProcessSP &process_wp)
136{
137 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
138
139 ExecutionContext exe_ctx(process_wp);
140
141 Error ret;
142
143 ret.Clear();
144
145 lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
146 lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
147
148 for (JittedFunction &function : m_jitted_functions)
149 {
150 if (strstr(function.m_name.c_str(), m_name.AsCString()))
151 {
152 func_local_addr = function.m_local_addr;
153 func_remote_addr = function.m_remote_addr;
154 }
155 }
156
157 if (func_local_addr == LLDB_INVALID_ADDRESS)
158 {
159 ret.SetErrorToGenericError();
160 ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
161 return ret;
162 }
163
164 if (log)
165 log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (uint64_t)func_local_addr, (uint64_t)func_remote_addr);
166
167 std::pair <lldb::addr_t, lldb::addr_t> func_range;
168
169 func_range = GetRemoteRangeForLocal(func_local_addr);
170
171 if (func_range.first == 0 && func_range.second == 0)
172 {
173 ret.SetErrorToGenericError();
174 ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
175 return ret;
176 }
177
178 if (log)
179 log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);
180
181 Target *target = exe_ctx.GetTargetPtr();
182 if (!target)
183 {
184 ret.SetErrorToGenericError();
185 ret.SetErrorString("Couldn't find the target");
186 return ret;
187 }
188
189 lldb::DataBufferSP buffer_sp(new DataBufferHeap(func_range.second, 0));
190
191 Process *process = exe_ctx.GetProcessPtr();
192 Error err;
193 process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
194
195 if (!err.Success())
196 {
197 ret.SetErrorToGenericError();
198 ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
199 return ret;
200 }
201
202 ArchSpec arch(target->GetArchitecture());
203
204 const char *plugin_name = NULL;
205 const char *flavor_string = NULL;
206 lldb::DisassemblerSP disassembler = Disassembler::FindPlugin(arch, flavor_string, plugin_name);
207
208 if (!disassembler)
209 {
210 ret.SetErrorToGenericError();
211 ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
212 return ret;
213 }
214
215 if (!process)
216 {
217 ret.SetErrorToGenericError();
218 ret.SetErrorString("Couldn't find the process");
219 return ret;
220 }
221
222 DataExtractor extractor(buffer_sp,
223 process->GetByteOrder(),
224 target->GetArchitecture().GetAddressByteSize());
225
226 if (log)
227 {
228 log->Printf("Function data has contents:");
229 extractor.PutToLog (log.get(),
230 0,
231 extractor.GetByteSize(),
232 func_remote_addr,
233 16,
234 DataExtractor::TypeUInt8);
235 }
236
237 disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false);
238
239 InstructionList &instruction_list = disassembler->GetInstructionList();
240 const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
241
242 for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
243 instruction_index < num_instructions;
244 ++instruction_index)
245 {
246 Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
247 instruction->Dump (&stream,
248 max_opcode_byte_size,
249 true,
250 true,
251 &exe_ctx);
252 stream.PutChar('\n');
253 }
254
255 return ret;
256}
257
Sean Callanan44bc6572013-03-27 03:09:55 +0000258static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie)
259{
260 Error *err = static_cast<Error*>(Context);
261
262 if (err && err->Success())
263 {
264 err->SetErrorToGenericError();
265 err->SetErrorStringWithFormat("Inline assembly error: %s", diagnostic.getMessage().str().c_str());
266 }
267}
268
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000269void
270IRExecutionUnit::GetRunnableInfo(Error &error,
271 lldb::addr_t &func_addr,
272 lldb::addr_t &func_end)
273{
274 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
275 lldb::ProcessSP process_sp(m_process_wp.lock());
276
277 func_addr = LLDB_INVALID_ADDRESS;
278 func_end = LLDB_INVALID_ADDRESS;
279
280 if (!process_sp)
281 {
282 error.SetErrorToGenericError();
283 error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
284 return;
285 }
286
287 if (m_did_jit)
288 {
289 func_addr = m_function_load_addr;
290 func_end = m_function_end_load_addr;
291
292 return;
293 }; // someone else may have gotten the mutex first
294
295 {
296 Mutex::Locker jit_mutex_locker(m_jit_mutex);
297
298 if (m_did_jit)
299 {
300 func_addr = m_function_load_addr;
301 func_end = m_function_end_load_addr;
302
303 return;
304 }; // someone else may have gotten the mutex first
305
306 m_did_jit = true;
307
308 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
309
310 std::string error_string;
311
312 if (log)
313 {
314 std::string s;
315 llvm::raw_string_ostream oss(s);
316
317 m_module->print(oss, NULL);
318
319 oss.flush();
320
321 log->Printf ("Module being sent to JIT: \n%s", s.c_str());
322 }
323
324 llvm::Triple triple(m_module->getTargetTriple());
325 llvm::Function *function = m_module->getFunction (m_name.AsCString());
326 llvm::Reloc::Model relocModel;
327 llvm::CodeModel::Model codeModel;
328
329 if (triple.isOSBinFormatELF())
330 {
331 relocModel = llvm::Reloc::Static;
332 // This will be small for 32-bit and large for 64-bit.
333 codeModel = llvm::CodeModel::JITDefault;
334 }
335 else
336 {
337 relocModel = llvm::Reloc::PIC_;
338 codeModel = llvm::CodeModel::Small;
339 }
340
Sean Callanan44bc6572013-03-27 03:09:55 +0000341 m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
342
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000343 llvm::EngineBuilder builder(m_module_ap.get());
344
345 builder.setEngineKind(llvm::EngineKind::JIT)
346 .setErrorStr(&error_string)
347 .setRelocationModel(relocModel)
348 .setJITMemoryManager(new MemoryManager(*this))
349 .setOptLevel(llvm::CodeGenOpt::Less)
350 .setAllocateGVsWithCode(true)
351 .setCodeModel(codeModel)
352 .setUseMCJIT(true);
353
354 llvm::StringRef mArch;
355 llvm::StringRef mCPU;
356 llvm::SmallVector<std::string, 0> mAttrs;
357
358 for (std::string &feature : m_cpu_features)
359 mAttrs.push_back(feature);
360
361 llvm::TargetMachine *target_machine = builder.selectTarget(triple,
362 mArch,
363 mCPU,
364 mAttrs);
365
366 m_execution_engine_ap.reset(builder.create(target_machine));
367
368 if (!m_execution_engine_ap.get())
369 {
370 error.SetErrorToGenericError();
371 error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
372 return;
373 }
374 else
375 {
376 m_module_ap.release(); // ownership was transferred
377 }
378
379 m_execution_engine_ap->DisableLazyCompilation();
380
381 // We don't actually need the function pointer here, this just forces it to get resolved.
382
383 void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
384
Sean Callanan44bc6572013-03-27 03:09:55 +0000385 if (!error.Success())
386 {
387 // We got an error through our callback!
388 return;
389 }
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000390
391 if (!function)
392 {
393 error.SetErrorToGenericError();
394 error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
395 return;
396 }
397
398 if (!fun_ptr)
399 {
400 error.SetErrorToGenericError();
401 error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
402 return;
403 }
404
405 m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
406
407 CommitAllocations(process_sp);
408 ReportAllocations(*m_execution_engine_ap);
409 WriteData(process_sp);
410
411 for (JittedFunction &jitted_function : m_jitted_functions)
412 {
413 jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
414
415 if (!jitted_function.m_name.compare(m_name.AsCString()))
416 {
417 AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
418 m_function_end_load_addr = func_range.first + func_range.second;
419 m_function_load_addr = jitted_function.m_remote_addr;
420 }
421 }
422
423 if (log)
424 {
425 log->Printf("Code can be run in the target.");
426
427 StreamString disassembly_stream;
428
429 Error err = DisassembleFunction(disassembly_stream, process_sp);
430
431 if (!err.Success())
432 {
433 log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
434 }
435 else
436 {
437 log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
438 }
439 }
440
441 func_addr = m_function_load_addr;
442 func_end = m_function_end_load_addr;
443
444 return;
445 }
446}
447
448IRExecutionUnit::~IRExecutionUnit ()
449{
450}
451
452IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
453 m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()),
454 m_parent (parent)
455{
456}
457
458void
459IRExecutionUnit::MemoryManager::setMemoryWritable ()
460{
461 m_default_mm_ap->setMemoryWritable();
462}
463
464void
465IRExecutionUnit::MemoryManager::setMemoryExecutable ()
466{
467 m_default_mm_ap->setMemoryExecutable();
468}
469
470
471uint8_t *
472IRExecutionUnit::MemoryManager::startFunctionBody(const llvm::Function *F,
473 uintptr_t &ActualSize)
474{
475 return m_default_mm_ap->startFunctionBody(F, ActualSize);
476}
477
478uint8_t *
479IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
480 unsigned StubSize,
481 unsigned Alignment)
482{
483 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
484
485 uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
486
Sean Callanan2c047352013-03-19 23:03:21 +0000487 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
488
489 Allocation &allocation(*iter);
490
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000491 allocation.m_size = StubSize;
492 allocation.m_alignment = Alignment;
493 allocation.m_local_start = (uintptr_t)return_value;
494
495 if (log)
496 {
497 log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
498 F, StubSize, Alignment, return_value);
499 allocation.dump(log);
500 }
Sean Callanan2c047352013-03-19 23:03:21 +0000501
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000502 return return_value;
503}
504
505void
506IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F,
507 uint8_t *FunctionStart,
508 uint8_t *FunctionEnd)
509{
510 m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
511}
512
513uint8_t *
514IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
515{
516 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
517
518 uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
519
Sean Callanan2c047352013-03-19 23:03:21 +0000520 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
521
522 Allocation &allocation(*iter);
523
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000524 allocation.m_size = Size;
525 allocation.m_alignment = Alignment;
526 allocation.m_local_start = (uintptr_t)return_value;
527
528 if (log)
529 {
530 log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
531 (uint64_t)Size, Alignment, return_value);
532 allocation.dump(log);
533 }
Sean Callanan2c047352013-03-19 23:03:21 +0000534
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000535 return return_value;
536}
537
538uint8_t *
539IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
540 unsigned Alignment,
541 unsigned SectionID)
542{
543 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
544
545 uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
546
Sean Callanan2c047352013-03-19 23:03:21 +0000547 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
548
549 Allocation &allocation(*iter);
550
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000551 allocation.m_size = Size;
552 allocation.m_alignment = Alignment;
553 allocation.m_local_start = (uintptr_t)return_value;
554 allocation.m_section_id = SectionID;
555 allocation.m_executable = true;
556
557 if (log)
558 {
559 log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
560 (uint64_t)Size, Alignment, SectionID, return_value);
561 allocation.dump(log);
562 }
Sean Callanan2c047352013-03-19 23:03:21 +0000563
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000564 return return_value;
565}
566
567uint8_t *
568IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
569 unsigned Alignment,
570 unsigned SectionID,
571 bool IsReadOnly)
572{
573 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
574
575 uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
576
Sean Callanan2c047352013-03-19 23:03:21 +0000577 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
578
579 Allocation &allocation(*iter);
580
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000581 allocation.m_size = Size;
582 allocation.m_alignment = Alignment;
583 allocation.m_local_start = (uintptr_t)return_value;
584 allocation.m_section_id = SectionID;
585
586 if (log)
587 {
588 log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
589 (uint64_t)Size, Alignment, SectionID, return_value);
590 allocation.dump(log);
591 }
Sean Callanan2c047352013-03-19 23:03:21 +0000592
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000593 return return_value;
594}
595
596uint8_t *
597IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
598 unsigned Alignment)
599{
600 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
601
602 uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
603
Sean Callanan2c047352013-03-19 23:03:21 +0000604 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
605
606 Allocation &allocation(*iter);
607
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000608 allocation.m_size = Size;
609 allocation.m_alignment = Alignment;
610 allocation.m_local_start = (uintptr_t)return_value;
611
612 if (log)
613 {
614 log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
615 (uint64_t)Size, Alignment, return_value);
616 allocation.dump(log);
617 }
618
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000619 return return_value;
620}
621
622void
623IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body)
624{
625 m_default_mm_ap->deallocateFunctionBody(Body);
626}
627
628uint8_t*
629IRExecutionUnit::MemoryManager::startExceptionTable(const llvm::Function* F,
630 uintptr_t &ActualSize)
631{
632 return m_default_mm_ap->startExceptionTable(F, ActualSize);
633}
634
635void
636IRExecutionUnit::MemoryManager::endExceptionTable(const llvm::Function *F,
637 uint8_t *TableStart,
638 uint8_t *TableEnd,
639 uint8_t* FrameRegister)
640{
641 m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
642}
643
644void
645IRExecutionUnit::MemoryManager::deallocateExceptionTable(void *ET)
646{
647 m_default_mm_ap->deallocateExceptionTable (ET);
648}
649
650lldb::addr_t
651IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
652{
653 for (Allocation &allocation : m_allocations)
654 {
655 if (local_address >= allocation.m_local_start &&
656 local_address < allocation.m_local_start + allocation.m_size)
657 return allocation.m_remote_start + (local_address - allocation.m_local_start);
658 }
659
660 return LLDB_INVALID_ADDRESS;
661}
662
663IRExecutionUnit::AddrRange
664IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
665{
666 for (Allocation &allocation : m_allocations)
667 {
668 if (local_address >= allocation.m_local_start &&
669 local_address < allocation.m_local_start + allocation.m_size)
670 return AddrRange(allocation.m_remote_start, allocation.m_size);
671 }
672
673 return AddrRange (0, 0);
674}
675
676bool
677IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
678{
679 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
680
681 bool ret = true;
682
683 for (Allocation &allocation : m_allocations)
684 {
685 if (allocation.m_allocated)
686 continue;
687
688 lldb_private::Error err;
689
690 size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
691
692 if (allocation_size == 0)
693 allocation_size = 1;
694
695 allocation.m_remote_allocation = process_sp->AllocateMemory(
696 allocation_size,
697 allocation.m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable)
698 : (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
699 err);
700
701 uint64_t mask = allocation.m_alignment - 1;
702
703 allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
704
705 if (!err.Success())
706 {
707 ret = false;
708 break;
709 }
710
711 allocation.m_allocated = true;
712
713 if (log)
714 {
715 log->Printf("IRExecutionUnit::CommitAllocations() committed an allocation");
716 allocation.dump(log);
717 }
718 }
719
720 if (!ret)
721 {
722 for (Allocation &allocation : m_allocations)
723 {
724 if (allocation.m_allocated)
725 process_sp->DeallocateMemory(allocation.m_remote_start);
726 }
727 }
728
729 return ret;
730}
731
732void
733IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
734{
735 for (Allocation &allocation : m_allocations)
736 {
737 if (!allocation.m_allocated)
738 continue;
739
Sean Callanan2c047352013-03-19 23:03:21 +0000740 if (allocation.m_section_id == Allocation::eSectionIDNone)
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000741 continue;
742
743 engine.mapSectionAddress((void*)allocation.m_local_start, allocation.m_remote_start);
744 }
745 // Trigger re-application of relocations.
746 engine.finalizeObject();
747}
748
749bool
750IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
751{
752 lldb::LogSP log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
753
754 for (Allocation &allocation : m_allocations)
755 {
756 if (!allocation.m_allocated)
757 return false;
758
759 if (allocation.m_local_start == LLDB_INVALID_ADDRESS)
760 continue;
761
762 lldb_private::Error err;
763
764 if (process_sp->WriteMemory(allocation.m_remote_start,
765 (void*)allocation.m_local_start,
766 allocation.m_size,
767 err) != allocation.m_size ||
768 !err.Success())
769 return false;
770
771 if (log)
772 {
773 log->Printf("IRExecutionUnit::CommitAllocations() wrote an allocation");
774 allocation.dump(log);
775 }
776 }
777
778 return true;
779}
780
781void
782IRExecutionUnit::Allocation::dump (lldb::LogSP log)
783{
784 if (!log)
785 return;
786
787 log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
788 (unsigned long long)m_local_start,
789 (unsigned long long)m_size,
790 (unsigned long long)m_remote_start,
791 (unsigned)m_alignment,
792 (unsigned)m_section_id);
793}