IRExecutionUnit.cpp revision 952e9dc874944fcdbbb224f3ec4fc2c859376f64
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
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()),
35    m_cpu_features(cpu_features),
36    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{
41}
42
43lldb::addr_t
44IRExecutionUnit::WriteNow (const uint8_t *bytes,
45                           size_t size,
46                           Error &error)
47{
48    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
49
50    auto iter = m_allocations.insert(m_allocations.end(), Allocation());
51
52    Allocation &allocation(*iter);
53
54    allocation.m_size = size;
55    allocation.m_alignment = 8;
56    allocation.m_data.reset(new DataBufferHeap(bytes, size));
57    allocation.m_local_start = (uintptr_t)allocation.m_data->GetBytes();
58    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");
73        return LLDB_INVALID_ADDRESS;
74    }
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    }
103
104    return allocation.m_remote_start;
105}
106
107void
108IRExecutionUnit::FreeNow (lldb::addr_t allocation)
109{
110    Log *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    Log *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,
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
258static 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
269void
270IRExecutionUnit::GetRunnableInfo(Error &error,
271                                 lldb::addr_t &func_addr,
272                                 lldb::addr_t &func_end)
273{
274    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
307        Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
308
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
340        m_module_ap->getContext().setInlineAsmDiagnosticHandler(ReportInlineAsmError, &error);
341
342        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
384        if (!error.Success())
385        {
386            // We got an error through our callback!
387            return;
388        }
389
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{
482    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
483
484    uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment);
485
486    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
487
488    Allocation &allocation(*iter);
489
490    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    }
500
501    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{
515    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
516
517    uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment);
518
519    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
520
521    Allocation &allocation(*iter);
522
523    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    }
533
534    return return_value;
535}
536
537uint8_t *
538IRExecutionUnit::MemoryManager::allocateCodeSection(uintptr_t Size,
539                                                    unsigned Alignment,
540                                                    unsigned SectionID)
541{
542    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
543
544    uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID);
545
546    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
547
548    Allocation &allocation(*iter);
549
550    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    }
562
563    return return_value;
564}
565
566uint8_t *
567IRExecutionUnit::MemoryManager::allocateDataSection(uintptr_t Size,
568                                                    unsigned Alignment,
569                                                    unsigned SectionID,
570                                                    bool IsReadOnly)
571{
572    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
573
574    uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly);
575
576    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
577
578    Allocation &allocation(*iter);
579
580    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    }
591
592    return return_value;
593}
594
595uint8_t *
596IRExecutionUnit::MemoryManager::allocateGlobal(uintptr_t Size,
597                                               unsigned Alignment)
598{
599    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
600
601    uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment);
602
603    auto iter = m_parent.m_allocations.insert(m_parent.m_allocations.end(), Allocation());
604
605    Allocation &allocation(*iter);
606
607    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
618    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{
678    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
679
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
739        if (allocation.m_section_id == Allocation::eSectionIDNone)
740            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{
751    Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
752
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
781IRExecutionUnit::Allocation::dump (Log *log)
782{
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}
793