//===-- RecordingMemoryManager.cpp ------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // C Includes // C++ Includes // Other libraries and framework includes #include "llvm/ExecutionEngine/ExecutionEngine.h" // Project includes #include "lldb/Expression/RecordingMemoryManager.h" using namespace lldb_private; RecordingMemoryManager::RecordingMemoryManager () : llvm::JITMemoryManager(), m_default_mm_ap (llvm::JITMemoryManager::CreateDefaultMemManager()), m_log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS)) { } RecordingMemoryManager::~RecordingMemoryManager () { } void RecordingMemoryManager::setMemoryWritable () { m_default_mm_ap->setMemoryWritable(); } void RecordingMemoryManager::setMemoryExecutable () { m_default_mm_ap->setMemoryExecutable(); } uint8_t * RecordingMemoryManager::startFunctionBody(const llvm::Function *F, uintptr_t &ActualSize) { return m_default_mm_ap->startFunctionBody(F, ActualSize); } uint8_t * RecordingMemoryManager::allocateStub(const llvm::GlobalValue* F, unsigned StubSize, unsigned Alignment) { uint8_t *return_value = m_default_mm_ap->allocateStub(F, StubSize, Alignment); Allocation allocation; allocation.m_size = StubSize; allocation.m_alignment = Alignment; allocation.m_local_start = (uintptr_t)return_value; if (m_log) { m_log->Printf("RecordingMemoryManager::allocateStub (F=%p, StubSize=%u, Alignment=%u) = %p", F, StubSize, Alignment, return_value); allocation.dump(m_log); } m_allocations.push_back(allocation); return return_value; } void RecordingMemoryManager::endFunctionBody(const llvm::Function *F, uint8_t *FunctionStart, uint8_t *FunctionEnd) { m_default_mm_ap->endFunctionBody(F, FunctionStart, FunctionEnd); } uint8_t * RecordingMemoryManager::allocateSpace(intptr_t Size, unsigned Alignment) { uint8_t *return_value = m_default_mm_ap->allocateSpace(Size, Alignment); Allocation allocation; allocation.m_size = Size; allocation.m_alignment = Alignment; allocation.m_local_start = (uintptr_t)return_value; if (m_log) { m_log->Printf("RecordingMemoryManager::allocateSpace(Size=%" PRIu64 ", Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); allocation.dump(m_log); } m_allocations.push_back(allocation); return return_value; } uint8_t * RecordingMemoryManager::allocateCodeSection(uintptr_t Size, unsigned Alignment, unsigned SectionID) { uint8_t *return_value = m_default_mm_ap->allocateCodeSection(Size, Alignment, SectionID); Allocation allocation; allocation.m_size = Size; allocation.m_alignment = Alignment; allocation.m_local_start = (uintptr_t)return_value; allocation.m_section_id = SectionID; allocation.m_executable = true; if (m_log) { m_log->Printf("RecordingMemoryManager::allocateCodeSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, return_value); allocation.dump(m_log); } m_allocations.push_back(allocation); return return_value; } uint8_t * RecordingMemoryManager::allocateDataSection(uintptr_t Size, unsigned Alignment, unsigned SectionID, bool IsReadOnly) { uint8_t *return_value = m_default_mm_ap->allocateDataSection(Size, Alignment, SectionID, IsReadOnly); Allocation allocation; allocation.m_size = Size; allocation.m_alignment = Alignment; allocation.m_local_start = (uintptr_t)return_value; allocation.m_section_id = SectionID; if (m_log) { m_log->Printf("RecordingMemoryManager::allocateDataSection(Size=0x%" PRIx64 ", Alignment=%u, SectionID=%u) = %p", (uint64_t)Size, Alignment, SectionID, return_value); allocation.dump(m_log); } m_allocations.push_back(allocation); return return_value; } uint8_t * RecordingMemoryManager::allocateGlobal(uintptr_t Size, unsigned Alignment) { uint8_t *return_value = m_default_mm_ap->allocateGlobal(Size, Alignment); Allocation allocation; allocation.m_size = Size; allocation.m_alignment = Alignment; allocation.m_local_start = (uintptr_t)return_value; if (m_log) { m_log->Printf("RecordingMemoryManager::allocateGlobal(Size=0x%" PRIx64 ", Alignment=%u) = %p", (uint64_t)Size, Alignment, return_value); allocation.dump(m_log); } m_allocations.push_back(allocation); return return_value; } void RecordingMemoryManager::deallocateFunctionBody(void *Body) { m_default_mm_ap->deallocateFunctionBody(Body); } uint8_t* RecordingMemoryManager::startExceptionTable(const llvm::Function* F, uintptr_t &ActualSize) { return m_default_mm_ap->startExceptionTable(F, ActualSize); } void RecordingMemoryManager::endExceptionTable(const llvm::Function *F, uint8_t *TableStart, uint8_t *TableEnd, uint8_t* FrameRegister) { m_default_mm_ap->endExceptionTable(F, TableStart, TableEnd, FrameRegister); } void RecordingMemoryManager::deallocateExceptionTable(void *ET) { m_default_mm_ap->deallocateExceptionTable (ET); } lldb::addr_t RecordingMemoryManager::GetRemoteAddressForLocal (lldb::addr_t local_address) { for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); ai != ae; ++ai) { if (local_address >= ai->m_local_start && local_address < ai->m_local_start + ai->m_size) return ai->m_remote_start + (local_address - ai->m_local_start); } return LLDB_INVALID_ADDRESS; } RecordingMemoryManager::AddrRange RecordingMemoryManager::GetRemoteRangeForLocal (lldb::addr_t local_address) { for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); ai != ae; ++ai) { if (local_address >= ai->m_local_start && local_address < ai->m_local_start + ai->m_size) return AddrRange(ai->m_remote_start, ai->m_size); } return AddrRange (0, 0); } bool RecordingMemoryManager::CommitAllocations (Process &process) { bool ret = true; for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); ai != ae; ++ai) { if (ai->m_allocated) continue; lldb_private::Error err; size_t allocation_size = (ai->m_size ? ai->m_size : 1) + ai->m_alignment - 1; if (allocation_size == 0) allocation_size = 1; ai->m_remote_allocation = process.AllocateMemory( allocation_size, ai->m_executable ? (lldb::ePermissionsReadable | lldb::ePermissionsExecutable) : (lldb::ePermissionsReadable | lldb::ePermissionsWritable), err); uint64_t mask = ai->m_alignment - 1; ai->m_remote_start = (ai->m_remote_allocation + mask) & (~mask); if (!err.Success()) { ret = false; break; } ai->m_allocated = true; if (m_log) { m_log->Printf("RecordingMemoryManager::CommitAllocations() committed an allocation"); ai->dump(m_log); } } if (!ret) { for (AllocationList::iterator ai = m_allocations.end(), ae = m_allocations.end(); ai != ae; ++ai) { if (ai->m_allocated) process.DeallocateMemory(ai->m_remote_start); } } return ret; } void RecordingMemoryManager::ReportAllocations (llvm::ExecutionEngine &engine) { for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); ai != ae; ++ai) { if (!ai->m_allocated) continue; engine.mapSectionAddress((void*)ai->m_local_start, ai->m_remote_start); } } bool RecordingMemoryManager::WriteData (Process &process) { for (AllocationList::iterator ai = m_allocations.begin(), ae = m_allocations.end(); ai != ae; ++ai) { if (!ai->m_allocated) return false; lldb_private::Error err; if (process.WriteMemory(ai->m_remote_start, (void*)ai->m_local_start, ai->m_size, err) != ai->m_size || !err.Success()) return false; if (m_log) { m_log->Printf("RecordingMemoryManager::CommitAllocations() wrote an allocation"); ai->dump(m_log); } } return true; } void RecordingMemoryManager::Allocation::dump (lldb::LogSP log) { if (!log) return; log->Printf("[0x%llx+0x%llx]->0x%llx (alignment %d, section ID %d)", (unsigned long long)m_local_start, (unsigned long long)m_size, (unsigned long long)m_remote_start, (unsigned)m_alignment, (unsigned)m_section_id); }