Files
llvm/lldb/source/Expression/RecordingMemoryManager.cpp
Sean Callanan 5b26f27f46 I have brought LLDB up-to-date with top of tree
LLVM/Clang.  This brings in several fixes, including:

- Improvements in the Just-In-Time compiler's
  allocation of memory: the JIT now allocates
  memory in chunks of sections, improving its
  ability to generate relocations.  I have
  revamped the RecordingMemoryManager to reflect
  these changes, as well as to get the memory
  allocation and data copying out fo the
  ClangExpressionParser code.  Jim Grosbach wrote
  the updates to the JIT on the LLVM side.

- A new ExternalASTSource interface to allow LLDB to
  report accurate structure layout information to
  Clang.  Previously we could only report the sizes
  of fields, not their offsets.  This meant that if
  data structures included field alignment
  directives, we could not communicate the necessary
  alignment to Clang and accesses to the data would
  fail.  Now we can (and I have update the relevant
  test case).  Thanks to Doug Gregor for implementing
  the Clang side of this fix.

- The way Objective-C interfaces are completed by
  Clang has been made consistent with RecordDecls;
  with help from Doug Gregor and Greg Clayton I have
  ensured that this still works.

- I have eliminated all local LLVM and Clang patches,
  committing the ones that are still relevant to LLVM
  and Clang as needed.

I have tested the changes extensively locally, but
please let me know if they cause any trouble for you.

llvm-svn: 149775
2012-02-04 08:49:35 +00:00

321 lines
8.8 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
// 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;
ai->m_remote_allocation = process.AllocateMemory(
ai->m_size + ai->m_alignment - 1,
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;
}
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);
}