]> CyberLeo.Net >> Repos - FreeBSD/releng/10.2.git/blob - contrib/llvm/tools/lldb/source/Expression/IRExecutionUnit.cpp
- Copy stable/10@285827 to releng/10.2 in preparation for 10.2-RC1
[FreeBSD/releng/10.2.git] / contrib / llvm / tools / lldb / source / Expression / IRExecutionUnit.cpp
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 // C Includes
11 // C++ Includes
12 // Other libraries and framework includes
13 #include "llvm/ExecutionEngine/ExecutionEngine.h"
14 #include "llvm/IR/LLVMContext.h"
15 #include "llvm/IR/Module.h"
16 #include "llvm/Support/SourceMgr.h"
17 // 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
26 using namespace lldb_private;
27
28 IRExecutionUnit::IRExecutionUnit (std::unique_ptr<llvm::LLVMContext> &context_ap,
29                                   std::unique_ptr<llvm::Module> &module_ap,
30                                   ConstString &name,
31                                   const lldb::TargetSP &target_sp,
32                                   std::vector<std::string> &cpu_features) :
33     IRMemoryMap(target_sp),
34     m_context_ap(context_ap.release()),
35     m_module_ap(module_ap.release()),
36     m_module(m_module_ap.get()),
37     m_cpu_features(cpu_features),
38     m_name(name),
39     m_did_jit(false),
40     m_function_load_addr(LLDB_INVALID_ADDRESS),
41     m_function_end_load_addr(LLDB_INVALID_ADDRESS)
42 {
43 }
44
45 lldb::addr_t
46 IRExecutionUnit::WriteNow (const uint8_t *bytes,
47                            size_t size,
48                            Error &error)
49 {    
50     lldb::addr_t allocation_process_addr = Malloc (size,
51                                                    8,
52                                                    lldb::ePermissionsWritable | lldb::ePermissionsReadable,
53                                                    eAllocationPolicyMirror,
54                                                    error);
55     
56     if (!error.Success())
57         return LLDB_INVALID_ADDRESS;
58     
59     WriteMemory(allocation_process_addr, bytes, size, error);
60     
61     if (!error.Success())
62     {
63         Error err;
64         Free (allocation_process_addr, err);
65         
66         return LLDB_INVALID_ADDRESS;
67     }
68     
69     if (Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
70     {
71         DataBufferHeap my_buffer(size, 0);
72         Error err;
73         ReadMemory(my_buffer.GetBytes(), allocation_process_addr, size, err);
74         
75         if (err.Success())
76         {
77             DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
78             my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), allocation_process_addr, 16, DataExtractor::TypeUInt8);
79         }
80     }
81     
82     return allocation_process_addr;
83 }
84
85 void
86 IRExecutionUnit::FreeNow (lldb::addr_t allocation)
87 {
88     if (allocation == LLDB_INVALID_ADDRESS)
89         return;
90     
91     Error err;
92     
93     Free(allocation, err);
94 }
95
96 Error
97 IRExecutionUnit::DisassembleFunction (Stream &stream,
98                                       lldb::ProcessSP &process_wp)
99 {
100     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
101     
102     ExecutionContext exe_ctx(process_wp);
103         
104     Error ret;
105     
106     ret.Clear();
107     
108     lldb::addr_t func_local_addr = LLDB_INVALID_ADDRESS;
109     lldb::addr_t func_remote_addr = LLDB_INVALID_ADDRESS;
110         
111     for (JittedFunction &function : m_jitted_functions)
112     {
113         if (strstr(function.m_name.c_str(), m_name.AsCString()))
114         {
115             func_local_addr = function.m_local_addr;
116             func_remote_addr = function.m_remote_addr;
117         }
118     }
119     
120     if (func_local_addr == LLDB_INVALID_ADDRESS)
121     {
122         ret.SetErrorToGenericError();
123         ret.SetErrorStringWithFormat("Couldn't find function %s for disassembly", m_name.AsCString());
124         return ret;
125     }
126     
127     if (log)
128         log->Printf("Found function, has local address 0x%" PRIx64 " and remote address 0x%" PRIx64, (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     {
136         ret.SetErrorToGenericError();
137         ret.SetErrorStringWithFormat("Couldn't find code range for function %s", m_name.AsCString());
138         return ret;
139     }
140     
141     if (log)
142         log->Printf("Function's code range is [0x%" PRIx64 "+0x%" PRIx64 "]", func_range.first, func_range.second);
143     
144     Target *target = exe_ctx.GetTargetPtr();
145     if (!target)
146     {
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     Error err;
156     process->ReadMemory(func_remote_addr, buffer_sp->GetBytes(), buffer_sp->GetByteSize(), err);
157     
158     if (!err.Success())
159     {
160         ret.SetErrorToGenericError();
161         ret.SetErrorStringWithFormat("Couldn't read from process: %s", err.AsCString("unknown error"));
162         return ret;
163     }
164     
165     ArchSpec arch(target->GetArchitecture());
166     
167     const char *plugin_name = NULL;
168     const char *flavor_string = NULL;
169     lldb::DisassemblerSP disassembler_sp = Disassembler::FindPlugin(arch, flavor_string, plugin_name);
170     
171     if (!disassembler_sp)
172     {
173         ret.SetErrorToGenericError();
174         ret.SetErrorStringWithFormat("Unable to find disassembler plug-in for %s architecture.", arch.GetArchitectureName());
175         return ret;
176     }
177     
178     if (!process)
179     {
180         ret.SetErrorToGenericError();
181         ret.SetErrorString("Couldn't find the process");
182         return ret;
183     }
184     
185     DataExtractor extractor(buffer_sp,
186                             process->GetByteOrder(),
187                             target->GetArchitecture().GetAddressByteSize());
188     
189     if (log)
190     {
191         log->Printf("Function data has contents:");
192         extractor.PutToLog (log,
193                             0,
194                             extractor.GetByteSize(),
195                             func_remote_addr,
196                             16,
197                             DataExtractor::TypeUInt8);
198     }
199     
200     disassembler_sp->DecodeInstructions (Address (func_remote_addr), extractor, 0, UINT32_MAX, false, false);
201     
202     InstructionList &instruction_list = disassembler_sp->GetInstructionList();
203     const uint32_t max_opcode_byte_size = instruction_list.GetMaxOpcocdeByteSize();
204     
205     for (size_t instruction_index = 0, num_instructions = instruction_list.GetSize();
206          instruction_index < num_instructions;
207          ++instruction_index)
208     {
209         Instruction *instruction = instruction_list.GetInstructionAtIndex(instruction_index).get();
210         instruction->Dump (&stream,
211                            max_opcode_byte_size,
212                            true,
213                            true,
214                            &exe_ctx);
215         stream.PutChar('\n');
216     }
217     // FIXME: The DisassemblerLLVMC has a reference cycle and won't go away if it has any active instructions.
218     // I'll fix that but for now, just clear the list and it will go away nicely.
219     disassembler_sp->GetInstructionList().Clear();
220     return ret;
221 }
222
223 static void ReportInlineAsmError(const llvm::SMDiagnostic &diagnostic, void *Context, unsigned LocCookie)
224 {
225     Error *err = static_cast<Error*>(Context);
226     
227     if (err && err->Success())
228     {
229         err->SetErrorToGenericError();
230         err->SetErrorStringWithFormat("Inline assembly error: %s", diagnostic.getMessage().str().c_str());
231     }
232 }
233
234 void
235 IRExecutionUnit::GetRunnableInfo(Error &error,
236                                  lldb::addr_t &func_addr,
237                                  lldb::addr_t &func_end)
238 {
239     lldb::ProcessSP process_sp(GetProcessWP().lock());
240     
241     static Mutex s_runnable_info_mutex(Mutex::Type::eMutexTypeRecursive);
242     
243     func_addr = LLDB_INVALID_ADDRESS;
244     func_end = LLDB_INVALID_ADDRESS;
245     
246     if (!process_sp)
247     {
248         error.SetErrorToGenericError();
249         error.SetErrorString("Couldn't write the JIT compiled code into the process because the process is invalid");
250         return;
251     }
252     
253     if (m_did_jit)
254     {
255         func_addr = m_function_load_addr;
256         func_end = m_function_end_load_addr;
257         
258         return;
259     };
260     
261     Mutex::Locker runnable_info_mutex_locker(s_runnable_info_mutex);
262     
263     m_did_jit = true;
264     
265     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
266     
267     std::string error_string;
268     
269     if (log)
270     {
271         std::string s;
272         llvm::raw_string_ostream oss(s);
273         
274         m_module->print(oss, NULL);
275         
276         oss.flush();
277         
278         log->Printf ("Module being sent to JIT: \n%s", s.c_str());
279     }
280     
281     llvm::Triple triple(m_module->getTargetTriple());
282     llvm::Function *function = m_module->getFunction (m_name.AsCString());
283     llvm::Reloc::Model relocModel;
284     llvm::CodeModel::Model codeModel;
285     
286     if (triple.isOSBinFormatELF())
287     {
288         relocModel = llvm::Reloc::Static;
289         // This will be small for 32-bit and large for 64-bit.
290         codeModel = llvm::CodeModel::JITDefault;
291     }
292     else
293     {
294         relocModel = llvm::Reloc::PIC_;
295         codeModel = llvm::CodeModel::Small;
296     }
297     
298     m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
299     
300     llvm::EngineBuilder builder(m_module_ap.get());
301     
302     builder.setEngineKind(llvm::EngineKind::JIT)
303     .setErrorStr(&error_string)
304     .setRelocationModel(relocModel)
305     .setJITMemoryManager(new MemoryManager(*this))
306     .setOptLevel(llvm::CodeGenOpt::Less)
307     .setAllocateGVsWithCode(true)
308     .setCodeModel(codeModel)
309     .setUseMCJIT(true);
310     
311     llvm::StringRef mArch;
312     llvm::StringRef mCPU;
313     llvm::SmallVector<std::string, 0> mAttrs;
314     
315     for (std::string &feature : m_cpu_features)
316         mAttrs.push_back(feature);
317     
318     llvm::TargetMachine *target_machine = builder.selectTarget(triple,
319                                                                mArch,
320                                                                mCPU,
321                                                                mAttrs);
322     
323     m_execution_engine_ap.reset(builder.create(target_machine));
324     
325     if (!m_execution_engine_ap.get())
326     {
327         error.SetErrorToGenericError();
328         error.SetErrorStringWithFormat("Couldn't JIT the function: %s", error_string.c_str());
329         return;
330     }
331     else
332     {
333         m_module_ap.release(); // ownership was transferred
334     }
335     
336     m_execution_engine_ap->DisableLazyCompilation();
337     
338     // We don't actually need the function pointer here, this just forces it to get resolved.
339     
340     void *fun_ptr = m_execution_engine_ap->getPointerToFunction(function);
341     
342     if (!error.Success())
343     {
344         // We got an error through our callback!
345         return;
346     }
347     
348     if (!function)
349     {
350         error.SetErrorToGenericError();
351         error.SetErrorStringWithFormat("Couldn't find '%s' in the JITted module", m_name.AsCString());
352         return;
353     }
354     
355     if (!fun_ptr)
356     {
357         error.SetErrorToGenericError();
358         error.SetErrorStringWithFormat("'%s' was in the JITted module but wasn't lowered", m_name.AsCString());
359         return;
360     }
361     
362     m_jitted_functions.push_back (JittedFunction(m_name.AsCString(), (lldb::addr_t)fun_ptr));
363     
364     CommitAllocations(process_sp);
365     ReportAllocations(*m_execution_engine_ap);
366     WriteData(process_sp);
367             
368     for (JittedFunction &jitted_function : m_jitted_functions)
369     {
370         jitted_function.m_remote_addr = GetRemoteAddressForLocal (jitted_function.m_local_addr);
371         
372         if (!jitted_function.m_name.compare(m_name.AsCString()))
373         {
374             AddrRange func_range = GetRemoteRangeForLocal(jitted_function.m_local_addr);
375             m_function_end_load_addr = func_range.first + func_range.second;
376             m_function_load_addr = jitted_function.m_remote_addr;
377         }
378     }
379     
380     if (log)
381     {
382         log->Printf("Code can be run in the target.");
383         
384         StreamString disassembly_stream;
385         
386         Error err = DisassembleFunction(disassembly_stream, process_sp);
387         
388         if (!err.Success())
389         {
390             log->Printf("Couldn't disassemble function : %s", err.AsCString("unknown error"));
391         }
392         else
393         {
394             log->Printf("Function disassembly:\n%s", disassembly_stream.GetData());
395         }
396         
397         log->Printf("Sections: ");
398         for (AllocationRecord &record : m_records)
399         {
400             if (record.m_process_address != LLDB_INVALID_ADDRESS)
401             {
402                 record.dump(log);
403                 
404                 DataBufferHeap my_buffer(record.m_size, 0);
405                 Error err;
406                 ReadMemory(my_buffer.GetBytes(), record.m_process_address, record.m_size, err);
407                 
408                 if (err.Success())
409                 {
410                     DataExtractor my_extractor(my_buffer.GetBytes(), my_buffer.GetByteSize(), lldb::eByteOrderBig, 8);
411                     my_extractor.PutToLog(log, 0, my_buffer.GetByteSize(), record.m_process_address, 16, DataExtractor::TypeUInt8);
412                 }
413             }
414         }
415     }
416     
417     func_addr = m_function_load_addr;
418     func_end = m_function_end_load_addr;
419     
420     return;
421 }
422
423 IRExecutionUnit::~IRExecutionUnit ()
424 {
425     m_module_ap.reset();
426     m_execution_engine_ap.reset();
427     m_context_ap.reset();
428 }
429
430 IRExecutionUnit::MemoryManager::MemoryManager (IRExecutionUnit &parent) :
431     m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()),
432     m_parent (parent)
433 {
434 }
435
436 void
437 IRExecutionUnit::MemoryManager::setMemoryWritable ()
438 {
439     m_default_mm_ap->setMemoryWritable();
440 }
441
442 void
443 IRExecutionUnit::MemoryManager::setMemoryExecutable ()
444 {
445     m_default_mm_ap->setMemoryExecutable();
446 }
447
448
449 uint8_t *
450 IRExecutionUnit::MemoryManager::startFunctionBody(const llvm::Function *F,
451                                                   uintptr_t &ActualSize)
452 {
453     return m_default_mm_ap->startFunctionBody(F, ActualSize);
454 }
455
456 uint8_t *
457 IRExecutionUnit::MemoryManager::allocateStub(const llvm::GlobalValue* F,
458                                              unsigned StubSize,
459                                              unsigned Alignment)
460 {
461     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
462
463     uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
464
465     m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
466                                                   lldb::ePermissionsReadable | lldb::ePermissionsWritable,
467                                                   StubSize,
468                                                   Alignment));
469
470     if (log)
471     {
472         log->Printf("IRExecutionUnit::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p",
473                     F, StubSize, Alignment, return_value);
474     }
475         
476     return return_value;
477 }
478
479 void
480 IRExecutionUnit::MemoryManager::endFunctionBody(const llvm::Function *F,
481                                                 uint8_t *FunctionStart,
482                                                 uint8_t *FunctionEnd)
483 {
484     m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd);
485 }
486
487 uint8_t *
488 IRExecutionUnit::MemoryManager::allocateSpace(intptr_t Size, unsigned Alignment)
489 {
490     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
491
492     uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
493     
494     m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
495                                                   lldb::ePermissionsReadable | lldb::ePermissionsWritable,
496                                                   Size,
497                                                   Alignment));
498     
499     if (log)
500     {
501         log->Printf("IRExecutionUnit::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p",
502                                (uint64_t)Size, Alignment, return_value);
503     }
504         
505     return return_value;
506 }
507
508 uint8_t *
509 IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
510                                                     unsigned Alignment,
511                                                     unsigned SectionID,
512                                                     llvm::StringRef SectionName)
513 {
514     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
515     
516     uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID, SectionName);
517     
518     m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
519                                                   lldb::ePermissionsReadable | lldb::ePermissionsExecutable,
520                                                   Size,
521                                                   Alignment,
522                                                   SectionID));
523     
524     if (log)
525     {
526         log->Printf("IRExecutionUnit::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
527                     (uint64_t)Size, Alignment, SectionID, return_value);
528     }
529         
530     return return_value;
531 }
532
533 uint8_t *
534 IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
535                                                     unsigned Alignment,
536                                                     unsigned SectionID,
537                                                     llvm::StringRef SectionName,
538                                                     bool IsReadOnly)
539 {
540     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
541
542     uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, SectionName, IsReadOnly);
543     
544     m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
545                                                   lldb::ePermissionsReadable | lldb::ePermissionsWritable,
546                                                   Size,
547                                                   Alignment,
548                                                   SectionID));
549     if (log)
550     {
551         log->Printf("IRExecutionUnit::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p",
552                     (uint64_t)Size, Alignment, SectionID, return_value);
553     }
554         
555     return return_value; 
556 }
557
558 uint8_t *
559 IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
560                                                unsigned Alignment)
561 {
562     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
563
564     uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
565     
566     m_parent.m_records.push_back(AllocationRecord((uintptr_t)return_value,
567                                                   lldb::ePermissionsReadable | lldb::ePermissionsWritable,
568                                                   Size,
569                                                   Alignment));
570     
571     if (log)
572     {
573         log->Printf("IRExecutionUnit::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p",
574                     (uint64_t)Size, Alignment, return_value);
575     }
576     
577     return return_value;
578 }
579
580 void
581 IRExecutionUnit::MemoryManager::deallocateFunctionBody(void *Body)
582 {
583     m_default_mm_ap->deallocateFunctionBody(Body);
584 }
585
586 lldb::addr_t
587 IRExecutionUnit::GetRemoteAddressForLocal (lldb::addr_t local_address)
588 {
589     Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
590
591     for (AllocationRecord &record : m_records)
592     {
593         if (local_address >= record.m_host_address &&
594             local_address < record.m_host_address + record.m_size)
595         {
596             if (record.m_process_address == LLDB_INVALID_ADDRESS)
597                 return LLDB_INVALID_ADDRESS;
598             
599             lldb::addr_t ret = record.m_process_address + (local_address - record.m_host_address);
600             
601             if (log)
602             {
603                 log->Printf("IRExecutionUnit::GetRemoteAddressForLocal() found 0x%" PRIx64 " in [0x%" PRIx64 "..0x%" PRIx64 "], and returned 0x%" PRIx64 " from [0x%" PRIx64 "..0x%" PRIx64 "].",
604                             local_address,
605                             (uint64_t)record.m_host_address,
606                             (uint64_t)record.m_host_address + (uint64_t)record.m_size,
607                             ret,
608                             record.m_process_address,
609                             record.m_process_address + record.m_size);
610             }
611             
612             return ret;
613         }
614     }
615
616     return LLDB_INVALID_ADDRESS;
617 }
618
619 IRExecutionUnit::AddrRange
620 IRExecutionUnit::GetRemoteRangeForLocal (lldb::addr_t local_address)
621 {
622     for (AllocationRecord &record : m_records)
623     {
624         if (local_address >= record.m_host_address &&
625             local_address < record.m_host_address + record.m_size)
626         {
627             if (record.m_process_address == LLDB_INVALID_ADDRESS)
628                 return AddrRange(0, 0);
629             
630             return AddrRange(record.m_process_address, record.m_size);
631         }
632     }
633     
634     return AddrRange (0, 0);
635 }
636
637 bool
638 IRExecutionUnit::CommitAllocations (lldb::ProcessSP &process_sp)
639 {
640     bool ret = true;
641     
642     lldb_private::Error err;
643     
644     for (AllocationRecord &record : m_records)
645     {
646         if (record.m_process_address != LLDB_INVALID_ADDRESS)
647             continue;
648         
649         
650         record.m_process_address = Malloc(record.m_size,
651                                           record.m_alignment,
652                                           record.m_permissions,
653                                           eAllocationPolicyProcessOnly,
654                                           err);
655         
656         if (!err.Success())
657         {
658             ret = false;
659             break;
660         }
661     }
662     
663     if (!ret)
664     {
665         for (AllocationRecord &record : m_records)
666         {
667             if (record.m_process_address != LLDB_INVALID_ADDRESS)
668             {
669                 Free(record.m_process_address, err);
670                 record.m_process_address = LLDB_INVALID_ADDRESS;
671             }
672         }
673     }
674     
675     return ret;
676 }
677
678 void
679 IRExecutionUnit::ReportAllocations (llvm::ExecutionEngine &engine)
680 {
681     for (AllocationRecord &record : m_records)
682     {
683         if (record.m_process_address == LLDB_INVALID_ADDRESS)
684             continue;
685         
686         if (record.m_section_id == eSectionIDInvalid)
687             continue;
688         
689         engine.mapSectionAddress((void*)record.m_host_address, record.m_process_address);
690     }
691     
692     // Trigger re-application of relocations.
693     engine.finalizeObject();
694 }
695
696 bool
697 IRExecutionUnit::WriteData (lldb::ProcessSP &process_sp)
698 {
699     for (AllocationRecord &record : m_records)
700     {
701         if (record.m_process_address == LLDB_INVALID_ADDRESS)
702             return false;
703         
704         lldb_private::Error err;
705
706         WriteMemory (record.m_process_address, (uint8_t*)record.m_host_address, record.m_size, err);
707     }
708     
709     return true;
710 }
711
712 void 
713 IRExecutionUnit::AllocationRecord::dump (Log *log)
714 {
715     if (!log)
716         return;
717     
718     log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)",
719                 (unsigned long long)m_host_address,
720                 (unsigned long long)m_size,
721                 (unsigned long long)m_process_address,
722                 (unsigned)m_alignment,
723                 (unsigned)m_section_id);
724 }