mirror of
https://github.com/intel/llvm.git
synced 2026-01-25 10:55:58 +08:00
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
321 lines
8.8 KiB
C++
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);
|
|
}
|