blob: 25fb157040c63583bb7bdd860a052f1955c6f2d6 [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{
Greg Clayton5160ce52013-03-27 23:08:40 +000048 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +000049
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{
Greg Clayton5160ce52013-03-27 23:08:40 +0000110 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000111
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{
Greg Clayton5160ce52013-03-27 23:08:40 +0000137 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000138
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:");
Greg Clayton5160ce52013-03-27 23:08:40 +0000229 extractor.PutToLog (log,
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000230 0,
231 extractor.GetByteSize(),
232 func_remote_addr,
233 16,
234 DataExtractor::TypeUInt8);
235 }
236
Greg Clayton3faf47c2013-03-28 23:42:53 +0000237 disassembler->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000238
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{
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000274 lldb::ProcessSP process_sp(m_process_wp.lock());
275
276 func_addr = LLDB_INVALID_ADDRESS;
277 func_end = LLDB_INVALID_ADDRESS;
278
279 if (!process_sp)
280 {
281 error.SetErrorToGenericError();
282 error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
283 return;
284 }
285
286 if (m_did_jit)
287 {
288 func_addr = m_function_load_addr;
289 func_end = m_function_end_load_addr;
290
291 return;
292 }; // someone else may have gotten the mutex first
293
294 {
295 Mutex::Locker jit_mutex_locker(m_jit_mutex);
296
297 if (m_did_jit)
298 {
299 func_addr = m_function_load_addr;
300 func_end = m_function_end_load_addr;
301
302 return;
303 }; // someone else may have gotten the mutex first
304
305 m_did_jit = true;
306
Greg Clayton5160ce52013-03-27 23:08:40 +0000307 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000308
309 std::string error_string;
310
311 if (log)
312 {
313 std::string s;
314 llvm::raw_string_ostream oss(s);
315
316 m_module->print(oss, NULL);
317
318 oss.flush();
319
320 log->Printf ("Module being sent to JIT: \n%s", s.c_str());
321 }
322
323 llvm::Triple triple(m_module->getTargetTriple());
324 llvm::Function *function = m_module->getFunction (m_name.AsCString());
325 llvm::Reloc::Model relocModel;
326 llvm::CodeModel::Model codeModel;
327
328 if (triple.isOSBinFormatELF())
329 {
330 relocModel = llvm::Reloc::Static;
331 // This will be small for 32-bit and large for 64-bit.
332 codeModel = llvm::CodeModel::JITDefault;
333 }
334 else
335 {
336 relocModel = llvm::Reloc::PIC_;
337 codeModel = llvm::CodeModel::Small;
338 }
339
Sean Callanan44bc6572013-03-27 03:09:55 +0000340 m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
341
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000342 llvm::EngineBuilder builder(m_module_ap.get());
343
344 builder.setEngineKind(llvm::EngineKind::JIT)
345 .setErrorStr(&error_string)
346 .setRelocationModel(relocModel)
347 .setJITMemoryManager(new MemoryManager(*this))
348 .setOptLevel(llvm::CodeGenOpt::Less)
349 .setAllocateGVsWithCode(true)
350 .setCodeModel(codeModel)
351 .setUseMCJIT(true);
352
353 llvm::StringRef mArch;
354 llvm::StringRef mCPU;
355 llvm::SmallVector<std::string, 0> mAttrs;
356
357 for (std::string &feature : m_cpu_features)
358 mAttrs.push_back(feature);
359
360 llvm::TargetMachine *target_machine = builder.selectTarget(triple,
361 mArch,
362 mCPU,
363 mAttrs);
364
365 m_execution_engine_ap.reset(builder.create(target_machine));
366
367 if (!m_execution_engine_ap.get())
368 {
369 error.SetErrorToGenericError();
370 error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
371 return;
372 }
373 else
374 {
375 m_module_ap.release(); // ownership was transferred
376 }
377
378 m_execution_engine_ap->DisableLazyCompilation();
379
380 // We don't actually need the function pointer here, this just forces it to get resolved.
381
382 void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
383
Sean Callanan44bc6572013-03-27 03:09:55 +0000384 if (!error.Success())
385 {
386 // We got an error through our callback!
387 return;
388 }
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000389
390 if (!function)
391 {
392 error.SetErrorToGenericError();
393 error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
394 return;
395 }
396
397 if (!fun_ptr)
398 {
399 error.SetErrorToGenericError();
400 error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
401 return;
402 }
403
404 m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
405
406 CommitAllocations(process_sp);
407 ReportAllocations(*m_execution_engine_ap);
408 WriteData(process_sp);
409
410 for (JittedFunction &jitted_function : m_jitted_functions)
411 {
412 jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
413
414 if (!jitted_function.m_name.compare(m_name.AsCString()))
415 {
416 AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
417 m_function_end_load_addr = func_range.first + func_range.second;
418 m_function_load_addr = jitted_function.m_remote_addr;
419 }
420 }
421
422 if (log)
423 {
424 log->Printf("Code can be run in the target.");
425
426 StreamString disassembly_stream;
427
428 Error err = DisassembleFunction(disassembly_stream, process_sp);
429
430 if (!err.Success())
431 {
432 log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
433 }
434 else
435 {
436 log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
437 }
438 }
439
440 func_addr = m_function_load_addr;
441 func_end = m_function_end_load_addr;
442
443 return;
444 }
445}
446
447IRExecutionUnit::~IRExecutionUnit ()
448{
449}
450
451IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
452 m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()),
453 m_parent (parent)
454{
455}
456
457void
458IRExecutionUnit::MemoryManager::setMemoryWritable ()
459{
460 m_default_mm_ap->setMemoryWritable();
461}
462
463void
464IRExecutionUnit::MemoryManager::setMemoryExecutable ()
465{
466 m_default_mm_ap->setMemoryExecutable();
467}
468
469
470uint8_t *
471IRExecutionUnit::MemoryManager::startFunctionBody(const llvm::Function *F,
472 uintptr_t &ActualSize)
473{
474 return m_default_mm_ap->startFunctionBody(F, ActualSize);
475}
476
477uint8_t *
478IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
479 unsigned StubSize,
480 unsigned Alignment)
481{
Greg Clayton5160ce52013-03-27 23:08:40 +0000482 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000483
484 uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
485
Sean Callanan2c047352013-03-19 23:03:21 +0000486 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
487
488 Allocation &allocation(*iter);
489
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000490 allocation.m_size = StubSize;
491 allocation.m_alignment = Alignment;
492 allocation.m_local_start = (uintptr_t)return_value;
493
494 if (log)
495 {
496 log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
497 F, StubSize, Alignment, return_value);
498 allocation.dump(log);
499 }
Sean Callanan2c047352013-03-19 23:03:21 +0000500
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000501 return return_value;
502}
503
504void
505IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F,
506 uint8_t *FunctionStart,
507 uint8_t *FunctionEnd)
508{
509 m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
510}
511
512uint8_t *
513IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
514{
Greg Clayton5160ce52013-03-27 23:08:40 +0000515 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000516
517 uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
518
Sean Callanan2c047352013-03-19 23:03:21 +0000519 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
520
521 Allocation &allocation(*iter);
522
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000523 allocation.m_size = Size;
524 allocation.m_alignment = Alignment;
525 allocation.m_local_start = (uintptr_t)return_value;
526
527 if (log)
528 {
529 log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
530 (uint64_t)Size, Alignment, return_value);
531 allocation.dump(log);
532 }
Sean Callanan2c047352013-03-19 23:03:21 +0000533
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000534 return return_value;
535}
536
537uint8_t *
538IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
539 unsigned Alignment,
540 unsigned SectionID)
541{
Greg Clayton5160ce52013-03-27 23:08:40 +0000542 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000543
544 uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
545
Sean Callanan2c047352013-03-19 23:03:21 +0000546 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
547
548 Allocation &allocation(*iter);
549
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000550 allocation.m_size = Size;
551 allocation.m_alignment = Alignment;
552 allocation.m_local_start = (uintptr_t)return_value;
553 allocation.m_section_id = SectionID;
554 allocation.m_executable = true;
555
556 if (log)
557 {
558 log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
559 (uint64_t)Size, Alignment, SectionID, return_value);
560 allocation.dump(log);
561 }
Sean Callanan2c047352013-03-19 23:03:21 +0000562
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000563 return return_value;
564}
565
566uint8_t *
567IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
568 unsigned Alignment,
569 unsigned SectionID,
570 bool IsReadOnly)
571{
Greg Clayton5160ce52013-03-27 23:08:40 +0000572 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000573
574 uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
575
Sean Callanan2c047352013-03-19 23:03:21 +0000576 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
577
578 Allocation &allocation(*iter);
579
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000580 allocation.m_size = Size;
581 allocation.m_alignment = Alignment;
582 allocation.m_local_start = (uintptr_t)return_value;
583 allocation.m_section_id = SectionID;
584
585 if (log)
586 {
587 log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
588 (uint64_t)Size, Alignment, SectionID, return_value);
589 allocation.dump(log);
590 }
Sean Callanan2c047352013-03-19 23:03:21 +0000591
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000592 return return_value;
593}
594
595uint8_t *
596IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
597 unsigned Alignment)
598{
Greg Clayton5160ce52013-03-27 23:08:40 +0000599 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000600
601 uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
602
Sean Callanan2c047352013-03-19 23:03:21 +0000603 auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
604
605 Allocation &allocation(*iter);
606
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000607 allocation.m_size = Size;
608 allocation.m_alignment = Alignment;
609 allocation.m_local_start = (uintptr_t)return_value;
610
611 if (log)
612 {
613 log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
614 (uint64_t)Size, Alignment, return_value);
615 allocation.dump(log);
616 }
617
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000618 return return_value;
619}
620
621void
622IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body)
623{
624 m_default_mm_ap->deallocateFunctionBody(Body);
625}
626
627uint8_t*
628IRExecutionUnit::MemoryManager::startExceptionTable(const llvm::Function* F,
629 uintptr_t &ActualSize)
630{
631 return m_default_mm_ap->startExceptionTable(F, ActualSize);
632}
633
634void
635IRExecutionUnit::MemoryManager::endExceptionTable(const llvm::Function *F,
636 uint8_t *TableStart,
637 uint8_t *TableEnd,
638 uint8_t* FrameRegister)
639{
640 m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister);
641}
642
643void
644IRExecutionUnit::MemoryManager::deallocateExceptionTable(void *ET)
645{
646 m_default_mm_ap->deallocateExceptionTable (ET);
647}
648
649lldb::addr_t
650IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
651{
652 for (Allocation &allocation : m_allocations)
653 {
654 if (local_address >= allocation.m_local_start &&
655 local_address < allocation.m_local_start + allocation.m_size)
656 return allocation.m_remote_start + (local_address - allocation.m_local_start);
657 }
658
659 return LLDB_INVALID_ADDRESS;
660}
661
662IRExecutionUnit::AddrRange
663IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
664{
665 for (Allocation &allocation : m_allocations)
666 {
667 if (local_address >= allocation.m_local_start &&
668 local_address < allocation.m_local_start + allocation.m_size)
669 return AddrRange(allocation.m_remote_start, allocation.m_size);
670 }
671
672 return AddrRange (0, 0);
673}
674
675bool
676IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
677{
Greg Clayton5160ce52013-03-27 23:08:40 +0000678 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000679
680 bool ret = true;
681
682 for (Allocation &allocation : m_allocations)
683 {
684 if (allocation.m_allocated)
685 continue;
686
687 lldb_private::Error err;
688
689 size_t allocation_size = (allocation.m_size ? allocation.m_size : 1) + allocation.m_alignment - 1;
690
691 if (allocation_size == 0)
692 allocation_size = 1;
693
694 allocation.m_remote_allocation = process_sp->AllocateMemory(
695 allocation_size,
696 allocation.m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable)
697 : (lldb::ePermissionsReadable | lldb::ePermissionsWritable),
698 err);
699
700 uint64_t mask = allocation.m_alignment - 1;
701
702 allocation.m_remote_start = (allocation.m_remote_allocation + mask) & (~mask);
703
704 if (!err.Success())
705 {
706 ret = false;
707 break;
708 }
709
710 allocation.m_allocated = true;
711
712 if (log)
713 {
714 log->Printf("IRExecutionUnit::CommitAllocations() committed an allocation");
715 allocation.dump(log);
716 }
717 }
718
719 if (!ret)
720 {
721 for (Allocation &allocation : m_allocations)
722 {
723 if (allocation.m_allocated)
724 process_sp->DeallocateMemory(allocation.m_remote_start);
725 }
726 }
727
728 return ret;
729}
730
731void
732IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
733{
734 for (Allocation &allocation : m_allocations)
735 {
736 if (!allocation.m_allocated)
737 continue;
738
Sean Callanan2c047352013-03-19 23:03:21 +0000739 if (allocation.m_section_id == Allocation::eSectionIDNone)
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000740 continue;
741
742 engine.mapSectionAddress((void*)allocation.m_local_start, allocation.m_remote_start);
743 }
744 // Trigger re-application of relocations.
745 engine.finalizeObject();
746}
747
748bool
749IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
750{
Greg Clayton5160ce52013-03-27 23:08:40 +0000751 Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000752
753 for (Allocation &allocation : m_allocations)
754 {
755 if (!allocation.m_allocated)
756 return false;
757
758 if (allocation.m_local_start == LLDB_INVALID_ADDRESS)
759 continue;
760
761 lldb_private::Error err;
762
763 if (process_sp->WriteMemory(allocation.m_remote_start,
764 (void*)allocation.m_local_start,
765 allocation.m_size,
766 err) != allocation.m_size ||
767 !err.Success())
768 return false;
769
770 if (log)
771 {
772 log->Printf("IRExecutionUnit::CommitAllocations() wrote an allocation");
773 allocation.dump(log);
774 }
775 }
776
777 return true;
778}
779
780void
Greg Clayton5160ce52013-03-27 23:08:40 +0000781IRExecutionUnit::Allocation::dump (Log *log)
Sean Callanan8dfb68e2013-03-19 00:10:07 +0000782{
783 if (!log)
784 return;
785
786 log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
787 (unsigned long long)m_local_start,
788 (unsigned long long)m_size,
789 (unsigned long long)m_remote_start,
790 (unsigned)m_alignment,
791 (unsigned)m_section_id);
792}