Replicated the materialization logic for persistent

variables in the Materializer.  We don't use this
code yet, but will soon once the other materializers
are online.

llvm-svn: 179390
This commit is contained in:
Sean Callanan 2013-04-12 18:10:34 +00:00
parent e14b765a89
commit 35005f768e
5 changed files with 389 additions and 154 deletions

View File

@ -38,6 +38,7 @@ class IRMemoryMap
{
public:
IRMemoryMap (lldb::ProcessSP process_sp);
IRMemoryMap (lldb::TargetSP target_sp);
~IRMemoryMap ();
enum AllocationPolicy {
@ -53,7 +54,14 @@ public:
void Free (lldb::addr_t process_address, Error &error);
void WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, size_t size, Error &error);
void WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error);
void ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error);
void ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error);
lldb::ByteOrder GetByteOrder();
uint32_t GetAddressByteSize();
ExecutionContextScope *GetBestExecutionContextScope();
protected:
lldb::ProcessWP GetProcessWP ()
@ -76,6 +84,7 @@ private:
};
lldb::ProcessWP m_process_wp;
lldb::TargetWP m_target_wp;
typedef std::map<lldb::addr_t, Allocation> AllocationMap;
AllocationMap m_allocations;

View File

@ -29,7 +29,9 @@ public:
class Dematerializer
{
public:
void Dematerialize(Error &err);
void Dematerialize(Error &err,
lldb::addr_t frame_top,
lldb::addr_t frame_bottom);
private:
friend class Materializer;
@ -54,7 +56,7 @@ public:
uint32_t AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err);
uint32_t AddVariable (lldb::VariableSP &variable_sp, Error &err);
uint32_t AddResultVariable (const ClangASTType &type, Error &err);
uint32_t AddResultVariable (const ClangASTType &type, bool keep_in_memory, Error &err);
uint32_t AddSymbol (const Symbol &symbol_sp, Error &err);
uint32_t AddRegister (const RegisterInfo &register_info, Error &err);
@ -83,7 +85,8 @@ public:
}
virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0;
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0;
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err) = 0;
uint32_t GetAlignment ()
{
@ -250,138 +253,3 @@ private:
}
#endif
//===-- Materializer.h ------------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef lldb_Materializer_h
#define lldb_Materializer_h
#include "lldb/lldb-private-types.h"
#include "lldb/Core/Error.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Host/Mutex.h"
#include "lldb/Symbol/SymbolContext.h"
#include <vector>
namespace lldb_private
{
class Materializer
{
public:
Materializer ();
class Dematerializer
{
public:
void Dematerialize(Error &err);
private:
friend class Materializer;
Dematerializer (Materializer &materializer,
lldb::StackFrameSP &frame_sp,
IRMemoryMap &map,
lldb::addr_t process_address) :
m_materializer(materializer),
m_frame_wp(frame_sp),
m_map(map),
m_process_address(process_address)
{
}
Materializer &m_materializer;
lldb::StackFrameWP m_frame_wp;
IRMemoryMap &m_map;
lldb::addr_t m_process_address;
};
Dematerializer Materialize (lldb::StackFrameSP &frame_sp, lldb::ClangExpressionVariableSP &result_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err);
uint32_t AddPersistentVariable (lldb::ClangExpressionVariableSP &persistent_variable_sp, Error &err);
uint32_t AddVariable (lldb::VariableSP &variable_sp, Error &err);
uint32_t AddResultVariable (const ClangASTType &type, Error &err);
uint32_t AddSymbol (const Symbol &symbol_sp, Error &err);
uint32_t AddRegister (const RegisterInfo &register_info, Error &err);
uint32_t GetStructAlignment ()
{
return m_struct_alignment;
}
uint32_t GetStructSize ()
{
return m_current_offset;
}
uint32_t GetNumEntities ()
{
return m_entities.size();
}
class Entity
{
public:
Entity () :
m_alignment(1),
m_size(0),
m_offset(0)
{
}
virtual ~Entity ()
{
}
virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0;
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err) = 0;
uint32_t GetAlignment ()
{
return m_alignment;
}
uint32_t GetSize ()
{
return m_size;
}
uint32_t GetOffset ()
{
return m_offset;
}
void SetOffset (uint32_t offset)
{
m_offset = offset;
}
protected:
void SetSizeAndAlignmentFromType (ClangASTType &type);
uint32_t m_alignment;
uint32_t m_size;
uint32_t m_offset;
};
private:
uint32_t AddStructMember (Entity &entity);
typedef std::unique_ptr<Entity> EntityUP;
typedef std::vector<EntityUP> EntityVector;
unsigned m_result_index;
Mutex m_needs_dematerialize;
EntityVector m_entities;
uint32_t m_current_offset;
uint32_t m_struct_alignment;
};
}
#endif

View File

@ -510,6 +510,11 @@ ClangExpressionDeclMap::AddPersistentVariable
var_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
}
if (m_keep_result_in_memory)
{
var_sp->m_flags |= ClangExpressionVariable::EVKeepInTarget;
}
if (log)
log->Printf("Created persistent variable with flags 0x%hx", var_sp->m_flags);
@ -523,7 +528,7 @@ ClangExpressionDeclMap::AddPersistentVariable
if (m_parser_vars->m_materializer)
{
Error err;
m_parser_vars->m_materializer->AddResultVariable(user_type, err);
m_parser_vars->m_materializer->AddResultVariable(user_type, m_keep_result_in_memory, err);
}
return true;

View File

@ -7,15 +7,26 @@
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/DataBufferHeap.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Error.h"
#include "lldb/Core/Log.h"
#include "lldb/Core/Scalar.h"
#include "lldb/Expression/IRMemoryMap.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/Target.h"
using namespace lldb_private;
IRMemoryMap::IRMemoryMap (lldb::ProcessSP process_sp) :
m_process_wp(process_sp)
m_process_wp(process_sp),
m_target_wp(process_sp->GetTarget().shared_from_this())
{
}
IRMemoryMap::IRMemoryMap (lldb::TargetSP target_sp) :
m_process_wp(),
m_target_wp(target_sp)
{
}
@ -97,6 +108,54 @@ IRMemoryMap::FindAllocation (lldb::addr_t addr, size_t size)
return m_allocations.end();
}
lldb::ByteOrder
IRMemoryMap::GetByteOrder()
{
lldb::ProcessSP process_sp = m_process_wp.lock();
if (process_sp)
return process_sp->GetByteOrder();
lldb::TargetSP target_sp = m_target_wp.lock();
if (target_sp)
return target_sp->GetDefaultArchitecture().GetByteOrder();
return lldb::eByteOrderInvalid;
}
uint32_t
IRMemoryMap::GetAddressByteSize()
{
lldb::ProcessSP process_sp = m_process_wp.lock();
if (process_sp)
return process_sp->GetAddressByteSize();
lldb::TargetSP target_sp = m_target_wp.lock();
if (target_sp)
return target_sp->GetDefaultArchitecture().GetAddressByteSize();
return UINT32_MAX;
}
ExecutionContextScope *
IRMemoryMap::GetBestExecutionContextScope()
{
lldb::ProcessSP process_sp = m_process_wp.lock();
if (process_sp)
return process_sp.get();
lldb::TargetSP target_sp = m_target_wp.lock();
if (target_sp)
return target_sp.get();
return NULL;
}
lldb::addr_t
IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
{
@ -335,6 +394,34 @@ IRMemoryMap::WriteMemory (lldb::addr_t process_address, const uint8_t *bytes, si
}
}
void
IRMemoryMap::WriteScalarToMemory (lldb::addr_t process_address, Scalar &scalar, size_t size, Error &error)
{
if (size == UINT32_MAX)
size = scalar.GetByteSize();
if (size > 0)
{
uint8_t buf[32];
const size_t mem_size = scalar.GetAsMemoryData (buf, size, GetByteOrder(), error);
if (mem_size > 0)
{
return WriteMemory(process_address, buf, mem_size, error);
}
else
{
error.SetErrorToGenericError();
error.SetErrorString ("Couldn't write scalar: failed to get scalar as memory data");
}
}
else
{
error.SetErrorToGenericError();
error.SetErrorString ("Couldn't write scalar: its size was zero");
}
return;
}
void
IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t size, Error &error)
{
@ -408,3 +495,39 @@ IRMemoryMap::ReadMemory (uint8_t *bytes, lldb::addr_t process_address, size_t si
(uint64_t)allocation.m_process_start + (uint64_t)allocation.m_size);
}
}
void
IRMemoryMap::ReadScalarFromMemory (Scalar &scalar, lldb::addr_t process_address, size_t size, Error &error)
{
if (size > 0)
{
DataBufferHeap buf(size, 0);
ReadMemory(buf.GetBytes(), process_address, size, error);
if (!error.Success())
return;
DataExtractor extractor(buf.GetBytes(), buf.GetByteSize(), GetByteOrder(), GetAddressByteSize());
lldb::offset_t offset = 0;
switch (size)
{
default:
error.SetErrorToGenericError();
error.SetErrorStringWithFormat("Couldn't read scalar: unsupported size %lld", (unsigned long long)size);
return;
case 1: scalar = extractor.GetU8(&offset); break;
case 2: scalar = extractor.GetU16(&offset); break;
case 4: scalar = extractor.GetU32(&offset); break;
case 8: scalar = extractor.GetU64(&offset); break;
}
}
else
{
error.SetErrorToGenericError();
error.SetErrorString ("Couldn't write scalar: its size was zero");
}
return;
}

View File

@ -7,6 +7,8 @@
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/Log.h"
#include "lldb/Core/ValueObjectConstResult.h"
#include "lldb/Expression/ClangExpressionVariable.h"
#include "lldb/Expression/Materializer.h"
#include "lldb/Symbol/ClangASTContext.h"
@ -67,12 +69,234 @@ public:
SetSizeAndAlignmentFromType(type);
}
virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
void MakeAllocation (IRMemoryMap &map, Error &err)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
// Allocate a spare memory area to store the persistent variable's contents.
Error allocate_error;
lldb::addr_t mem = map.Malloc(m_persistent_variable_sp->GetByteSize(),
8,
lldb::ePermissionsReadable | lldb::ePermissionsWritable,
IRMemoryMap::eAllocationPolicyMirror,
allocate_error);
if (!allocate_error.Success())
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't allocate a memory area to store %s: %s", m_persistent_variable_sp->GetName().GetCString(), allocate_error.AsCString());
return;
}
if (log)
log->Printf("Allocated %s (0x%" PRIx64 ") sucessfully", m_persistent_variable_sp->GetName().GetCString(), mem);
// Put the location of the spare memory into the live data of the ValueObject.
m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope(),
m_persistent_variable_sp->GetTypeFromUser().GetASTContext(),
m_persistent_variable_sp->GetTypeFromUser().GetOpaqueQualType(),
m_persistent_variable_sp->GetName(),
mem,
eAddressTypeLoad,
m_persistent_variable_sp->GetByteSize());
// Clear the flag if the variable will never be deallocated.
if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsAllocation;
// Write the contents of the variable to the area.
Error write_error;
map.WriteMemory (mem,
m_persistent_variable_sp->GetValueBytes(),
m_persistent_variable_sp->GetByteSize(),
write_error);
if (!write_error.Success())
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat ("Couldn't write %s to the target: %s", m_persistent_variable_sp->GetName().AsCString(),
write_error.AsCString());
return;
}
}
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
void DestroyAllocation (IRMemoryMap &map, Error &err)
{
Error deallocate_error;
map.Free((lldb::addr_t)m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong(), deallocate_error);
if (!deallocate_error.Success())
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat ("Couldn't deallocate memory for %s: %s", m_persistent_variable_sp->GetName().GetCString(), deallocate_error.AsCString());
}
}
virtual void Materialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
{
log->Printf("EntityPersistentVariable::Materialize [process_address = 0x%llx, m_name = %s, m_flags = 0x%hx]",
(uint64_t)process_address,
m_persistent_variable_sp->GetName().AsCString(),
m_persistent_variable_sp->m_flags);
}
if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation)
{
MakeAllocation(map, err);
if (!err.Success())
return;
}
if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference && m_persistent_variable_sp->m_live_sp) ||
m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated)
{
Error write_error;
map.WriteScalarToMemory(process_address + m_offset,
m_persistent_variable_sp->m_live_sp->GetValue().GetScalar(),
m_persistent_variable_sp->m_live_sp->GetProcessSP()->GetAddressByteSize(),
write_error);
if (!write_error.Success())
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't write the location of %s to memory: %s", m_persistent_variable_sp->GetName().AsCString(), write_error.AsCString());
}
}
else
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("No materialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
return;
}
}
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, lldb::addr_t process_address, Error &err)
{
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
if (log)
{
log->Printf("EntityPersistentVariable::Dematerialize [process_address = 0x%llx, m_name = %s, m_flags = 0x%hx]",
(uint64_t)process_address,
m_persistent_variable_sp->GetName().AsCString(),
m_persistent_variable_sp->m_flags);
}
if ((m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsLLDBAllocated) ||
(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference))
{
if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVIsProgramReference &&
!m_persistent_variable_sp->m_live_sp)
{
// If the reference comes from the program, then the ClangExpressionVariable's
// live variable data hasn't been set up yet. Do this now.
Scalar location_scalar;
Error read_error;
map.ReadScalarFromMemory(location_scalar, process_address + m_offset, map.GetAddressByteSize(), read_error);
if (!read_error.Success())
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't read the address of program-allocated variable %s: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
return;
}
lldb::addr_t location = location_scalar.ULongLong();
m_persistent_variable_sp->m_live_sp = ValueObjectConstResult::Create (map.GetBestExecutionContextScope (),
m_persistent_variable_sp->GetTypeFromUser().GetASTContext(),
m_persistent_variable_sp->GetTypeFromUser().GetOpaqueQualType(),
m_persistent_variable_sp->GetName(),
location,
eAddressTypeLoad,
m_persistent_variable_sp->GetByteSize());
if (frame_top != LLDB_INVALID_ADDRESS &&
frame_bottom != LLDB_INVALID_ADDRESS &&
location >= frame_bottom &&
location <= frame_top)
{
// If the variable is resident in the stack frame created by the expression,
// then it cannot be relied upon to stay around. We treat it as needing
// reallocation.
m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVIsLLDBAllocated;
m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsAllocation;
m_persistent_variable_sp->m_flags |= ClangExpressionVariable::EVNeedsFreezeDry;
m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVIsProgramReference;
}
}
lldb::addr_t mem = m_persistent_variable_sp->m_live_sp->GetValue().GetScalar().ULongLong();
if (!m_persistent_variable_sp->m_live_sp)
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("Couldn't find the memory area used to store %s", m_persistent_variable_sp->GetName().GetCString());
return;
}
if (m_persistent_variable_sp->m_live_sp->GetValue().GetValueAddressType() != eAddressTypeLoad)
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("The address of the memory area for %s is in an incorrect format", m_persistent_variable_sp->GetName().GetCString());
return;
}
if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsFreezeDry ||
m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget)
{
if (log)
log->Printf("Dematerializing %s from 0x%" PRIx64 " (size = %llu)", m_persistent_variable_sp->GetName().GetCString(), (uint64_t)mem, (unsigned long long)m_persistent_variable_sp->GetByteSize());
// Read the contents of the spare memory area
m_persistent_variable_sp->ValueUpdated ();
Error read_error;
map.ReadMemory(m_persistent_variable_sp->GetValueBytes(),
mem,
m_persistent_variable_sp->GetByteSize(),
read_error);
if (!read_error.Success())
{
err.SetErrorStringWithFormat ("Couldn't read the contents of %s from memory: %s", m_persistent_variable_sp->GetName().GetCString(), read_error.AsCString());
return;
}
m_persistent_variable_sp->m_flags &= ~ClangExpressionVariable::EVNeedsFreezeDry;
}
}
else
{
err.SetErrorToGenericError();
err.SetErrorStringWithFormat("No dematerialization happened for persistent variable %s", m_persistent_variable_sp->GetName().AsCString());
return;
}
if (m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVNeedsAllocation &&
!(m_persistent_variable_sp->m_flags & ClangExpressionVariable::EVKeepInTarget))
{
DestroyAllocation(map, err);
if (!err.Success())
return;
}
}
private:
lldb::ClangExpressionVariableSP m_persistent_variable_sp;
@ -104,7 +328,8 @@ public:
{
}
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
{
}
private:
@ -124,9 +349,10 @@ Materializer::AddVariable (lldb::VariableSP &variable_sp, Error &err)
class EntityResultVariable : public Materializer::Entity
{
public:
EntityResultVariable (const ClangASTType &type) :
EntityResultVariable (const ClangASTType &type, bool keep_in_memory) :
Entity(),
m_type(type)
m_type(type),
m_keep_in_memory(keep_in_memory)
{
SetSizeAndAlignmentFromType(m_type);
}
@ -135,18 +361,20 @@ public:
{
}
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
{
}
private:
ClangASTType m_type;
ClangASTType m_type;
bool m_keep_in_memory;
};
uint32_t
Materializer::AddResultVariable (const ClangASTType &type, Error &err)
Materializer::AddResultVariable (const ClangASTType &type, bool keep_in_memory, Error &err)
{
EntityVector::iterator iter = m_entities.insert(m_entities.end(), EntityUP());
iter->reset (new EntityResultVariable (type));
iter->reset (new EntityResultVariable (type, keep_in_memory));
uint32_t ret = AddStructMember(**iter);
(*iter)->SetOffset(ret);
return ret;
@ -168,7 +396,8 @@ public:
{
}
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
{
}
private:
@ -201,7 +430,8 @@ public:
{
}
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address, Error &err)
virtual void Dematerialize (lldb::StackFrameSP &frame_sp, IRMemoryMap &map, lldb::addr_t process_address,
lldb::addr_t frame_top, lldb::addr_t frame_bottom, Error &err)
{
}
private:
@ -243,7 +473,7 @@ Materializer::Materialize (lldb::StackFrameSP &frame_sp, lldb::ClangExpressionVa
}
void
Materializer::Dematerializer::Dematerialize (Error &error)
Materializer::Dematerializer::Dematerialize (Error &error, lldb::addr_t frame_top, lldb::addr_t frame_bottom)
{
lldb::StackFrameSP frame_sp = m_frame_wp.lock();
@ -256,7 +486,7 @@ Materializer::Dematerializer::Dematerialize (Error &error)
{
for (EntityUP &entity_up : m_materializer.m_entities)
{
entity_up->Dematerialize (frame_sp, m_map, m_process_address, error);
entity_up->Dematerialize (frame_sp, m_map, m_process_address, frame_top, frame_bottom, error);
if (!error.Success())
break;