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