forked from OSchip/llvm-project
341 lines
9.3 KiB
C++
341 lines
9.3 KiB
C++
//===-- 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=%llu, 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%llx, 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)
|
|
{
|
|
uint8_t *return_value = m_default_mm_ap->allocateDataSection(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;
|
|
|
|
if (m_log)
|
|
{
|
|
m_log->Printf("RecordingMemoryManager::allocateDataSection(Size=0x%llx, 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%llx, 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);
|
|
}
|