2013-08-23 13:46:38 -04:00
//===-- Materializer.cpp ----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
# include "lldb/Core/Log.h"
# include "lldb/Core/RegisterValue.h"
# include "lldb/Core/ValueObjectConstResult.h"
# include "lldb/Core/ValueObjectVariable.h"
# include "lldb/Expression/ClangExpressionVariable.h"
2015-07-03 12:57:06 -04:00
# include "lldb/Expression/ClangPersistentVariables.h"
2013-08-23 13:46:38 -04:00
# include "lldb/Expression/Materializer.h"
# include "lldb/Symbol/ClangASTContext.h"
# include "lldb/Symbol/Symbol.h"
# include "lldb/Symbol/Type.h"
# include "lldb/Symbol/Variable.h"
# include "lldb/Target/ExecutionContext.h"
# include "lldb/Target/RegisterContext.h"
# include "lldb/Target/StackFrame.h"
# include "lldb/Target/Target.h"
# include "lldb/Target/Thread.h"
using namespace lldb_private ;
uint32_t
Materializer : : AddStructMember ( Entity & entity )
{
uint32_t size = entity . GetSize ( ) ;
uint32_t alignment = entity . GetAlignment ( ) ;
uint32_t ret ;
if ( m_current_offset = = 0 )
m_struct_alignment = alignment ;
if ( m_current_offset % alignment )
m_current_offset + = ( alignment - ( m_current_offset % alignment ) ) ;
ret = m_current_offset ;
m_current_offset + = size ;
return ret ;
}
void
Materializer : : Entity : : SetSizeAndAlignmentFromType ( ClangASTType & type )
{
2015-02-08 20:44:09 -05:00
m_size = type . GetByteSize ( nullptr ) ;
2013-08-23 13:46:38 -04:00
uint32_t bit_alignment = type . GetTypeBitAlign ( ) ;
if ( bit_alignment % 8 )
{
bit_alignment + = 8 ;
bit_alignment & = ~ ( ( uint32_t ) 0x111u ) ;
}
m_alignment = bit_alignment / 8 ;
}
class EntityPersistentVariable : public Materializer : : Entity
{
public :
EntityPersistentVariable ( lldb : : ClangExpressionVariableSP & persistent_variable_sp ) :
Entity ( ) ,
m_persistent_variable_sp ( persistent_variable_sp )
{
// Hard-coding to maximum size of a pointer since persistent variables are materialized by reference
m_size = 8 ;
m_alignment = 8 ;
}
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 . SetErrorStringWithFormat ( " couldn't allocate a memory area to store %s: %s " , m_persistent_variable_sp - > GetName ( ) . GetCString ( ) , allocate_error . AsCString ( ) ) ;
return ;
}
if ( log )
2014-11-25 16:00:58 -05:00
log - > Printf ( " Allocated %s (0x% " PRIx64 " ) successfully " , m_persistent_variable_sp - > GetName ( ) . GetCString ( ) , mem ) ;
2013-08-23 13:46:38 -04:00
// 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 ( ) ,
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 )
{
Error leak_error ;
map . Leak ( mem , leak_error ) ;
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 . SetErrorStringWithFormat ( " couldn't write %s to the target: %s " , m_persistent_variable_sp - > GetName ( ) . AsCString ( ) ,
write_error . AsCString ( ) ) ;
return ;
}
}
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 ) ;
m_persistent_variable_sp - > m_live_sp . reset ( ) ;
if ( ! deallocate_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't deallocate memory for %s: %s " , m_persistent_variable_sp - > GetName ( ) . GetCString ( ) , deallocate_error . AsCString ( ) ) ;
}
}
void Materialize ( lldb : : StackFrameSP & frame_sp , IRMemoryMap & map , lldb : : addr_t process_address , Error & err )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntityPersistentVariable::Materialize [address = 0x% " PRIx64 " , m_name = %s, m_flags = 0x%hx] " ,
( uint64_t ) load_addr ,
m_persistent_variable_sp - > GetName ( ) . AsCString ( ) ,
m_persistent_variable_sp - > m_flags ) ;
}
if ( m_persistent_variable_sp - > m_flags & ClangExpressionVariable : : EVNeedsAllocation )
{
MakeAllocation ( map , err ) ;
m_persistent_variable_sp - > m_flags | = ClangExpressionVariable : : EVIsLLDBAllocated ;
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 ( load_addr ,
m_persistent_variable_sp - > m_live_sp - > GetValue ( ) . GetScalar ( ) ,
map . GetAddressByteSize ( ) ,
write_error ) ;
if ( ! write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the location of %s to memory: %s " , m_persistent_variable_sp - > GetName ( ) . AsCString ( ) , write_error . AsCString ( ) ) ;
}
}
else
{
err . SetErrorStringWithFormat ( " no materialization happened for persistent variable %s " , m_persistent_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
}
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 )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntityPersistentVariable::Dematerialize [address = 0x% " PRIx64 " , m_name = %s, m_flags = 0x%hx] " ,
( uint64_t ) process_address + m_offset ,
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.
lldb : : addr_t location ;
Error read_error ;
map . ReadPointerFromMemory ( & location , load_addr , read_error ) ;
if ( ! read_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't read the address of program-allocated variable %s: %s " , m_persistent_variable_sp - > GetName ( ) . GetCString ( ) , read_error . AsCString ( ) ) ;
return ;
}
m_persistent_variable_sp - > m_live_sp = ValueObjectConstResult : : Create ( map . GetBestExecutionContextScope ( ) ,
m_persistent_variable_sp - > GetTypeFromUser ( ) ,
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 . 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 . 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 . SetErrorStringWithFormat ( " no dematerialization happened for persistent variable %s " , m_persistent_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
lldb : : ProcessSP process_sp = map . GetBestExecutionContextScope ( ) - > CalculateProcess ( ) ;
if ( ! process_sp | |
! process_sp - > CanJIT ( ) )
{
// Allocations are not persistent so persistent variables cannot stay materialized.
m_persistent_variable_sp - > m_flags | = ClangExpressionVariable : : EVNeedsAllocation ;
DestroyAllocation ( map , err ) ;
if ( ! err . Success ( ) )
return ;
}
else if ( m_persistent_variable_sp - > m_flags & ClangExpressionVariable : : EVNeedsAllocation & &
! ( m_persistent_variable_sp - > m_flags & ClangExpressionVariable : : EVKeepInTarget ) )
{
DestroyAllocation ( map , err ) ;
if ( ! err . Success ( ) )
return ;
}
}
void DumpToLog ( IRMemoryMap & map , lldb : : addr_t process_address , Log * log )
{
StreamString dump_stream ;
Error err ;
const lldb : : addr_t load_addr = process_address + m_offset ;
dump_stream . Printf ( " 0x% " PRIx64 " : EntityPersistentVariable (%s) \n " , load_addr , m_persistent_variable_sp - > GetName ( ) . AsCString ( ) ) ;
{
dump_stream . Printf ( " Pointer: \n " ) ;
DataBufferHeap data ( m_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , load_addr , m_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
{
dump_stream . Printf ( " Target: \n " ) ;
lldb : : addr_t target_address ;
map . ReadPointerFromMemory ( & target_address , load_addr , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataBufferHeap data ( m_persistent_variable_sp - > GetByteSize ( ) , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , target_address , m_persistent_variable_sp - > GetByteSize ( ) , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , target_address ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
}
log - > PutCString ( dump_stream . GetData ( ) ) ;
}
void Wipe ( IRMemoryMap & map , lldb : : addr_t process_address )
{
}
private :
lldb : : ClangExpressionVariableSP m_persistent_variable_sp ;
} ;
uint32_t
Materializer : : AddPersistentVariable ( lldb : : ClangExpressionVariableSP & persistent_variable_sp , Error & err )
{
EntityVector : : iterator iter = m_entities . insert ( m_entities . end ( ) , EntityUP ( ) ) ;
iter - > reset ( new EntityPersistentVariable ( persistent_variable_sp ) ) ;
uint32_t ret = AddStructMember ( * * iter ) ;
( * iter ) - > SetOffset ( ret ) ;
return ret ;
}
class EntityVariable : public Materializer : : Entity
{
public :
EntityVariable ( lldb : : VariableSP & variable_sp ) :
Entity ( ) ,
m_variable_sp ( variable_sp ) ,
m_is_reference ( false ) ,
m_temporary_allocation ( LLDB_INVALID_ADDRESS ) ,
m_temporary_allocation_size ( 0 )
{
// Hard-coding to maximum size of a pointer since all variables are materialized by reference
m_size = 8 ;
m_alignment = 8 ;
m_is_reference = m_variable_sp - > GetType ( ) - > GetClangForwardType ( ) . IsReferenceType ( ) ;
}
void Materialize ( lldb : : StackFrameSP & frame_sp , IRMemoryMap & map , lldb : : addr_t process_address , Error & err )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntityVariable::Materialize [address = 0x% " PRIx64 " , m_variable_sp = %s] " ,
( uint64_t ) load_addr ,
m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
}
ExecutionContextScope * scope = frame_sp . get ( ) ;
if ( ! scope )
scope = map . GetBestExecutionContextScope ( ) ;
lldb : : ValueObjectSP valobj_sp = ValueObjectVariable : : Create ( scope , m_variable_sp ) ;
if ( ! valobj_sp )
{
err . SetErrorStringWithFormat ( " couldn't get a value object for variable %s " , m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
2014-11-25 16:00:58 -05:00
Error valobj_error = valobj_sp - > GetError ( ) ;
if ( valobj_error . Fail ( ) )
{
err . SetErrorStringWithFormat ( " couldn't get the value of variable %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , valobj_error . AsCString ( ) ) ;
return ;
}
2013-08-23 13:46:38 -04:00
if ( m_is_reference )
{
DataExtractor valobj_extractor ;
2014-11-25 16:00:58 -05:00
Error extract_error ;
valobj_sp - > GetData ( valobj_extractor , extract_error ) ;
if ( ! extract_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't read contents of reference variable %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , extract_error . AsCString ( ) ) ;
return ;
}
2013-08-23 13:46:38 -04:00
lldb : : offset_t offset = 0 ;
lldb : : addr_t reference_addr = valobj_extractor . GetAddress ( & offset ) ;
Error write_error ;
map . WritePointerToMemory ( load_addr , reference_addr , write_error ) ;
if ( ! write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the contents of reference variable %s to memory: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , write_error . AsCString ( ) ) ;
return ;
}
}
else
{
2014-02-18 11:23:10 -05:00
AddressType address_type = eAddressTypeInvalid ;
const bool scalar_is_load_address = false ;
lldb : : addr_t addr_of_valobj = valobj_sp - > GetAddressOf ( scalar_is_load_address , & address_type ) ;
2013-11-06 11:48:53 -05:00
if ( addr_of_valobj ! = LLDB_INVALID_ADDRESS )
2013-08-23 13:46:38 -04:00
{
Error write_error ;
2013-11-06 11:48:53 -05:00
map . WritePointerToMemory ( load_addr , addr_of_valobj , write_error ) ;
2013-08-23 13:46:38 -04:00
if ( ! write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the address of variable %s to memory: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , write_error . AsCString ( ) ) ;
return ;
}
}
else
{
DataExtractor data ;
2014-11-25 16:00:58 -05:00
Error extract_error ;
valobj_sp - > GetData ( data , extract_error ) ;
if ( ! extract_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't get the value of %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , extract_error . AsCString ( ) ) ;
return ;
}
2013-08-23 13:46:38 -04:00
if ( m_temporary_allocation ! = LLDB_INVALID_ADDRESS )
{
err . SetErrorStringWithFormat ( " trying to create a temporary region for %s but one exists " , m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
if ( data . GetByteSize ( ) ! = m_variable_sp - > GetType ( ) - > GetByteSize ( ) )
{
if ( data . GetByteSize ( ) = = 0 & & m_variable_sp - > LocationExpression ( ) . IsValid ( ) = = false )
{
err . SetErrorStringWithFormat ( " the variable '%s' has no location, it may have been optimized out " , m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
}
else
{
2013-12-03 13:51:59 -05:00
err . SetErrorStringWithFormat ( " size of variable %s (% " PRIu64 " ) disagrees with the ValueObject's size (% " PRIu64 " ) " ,
m_variable_sp - > GetName ( ) . AsCString ( ) ,
m_variable_sp - > GetType ( ) - > GetByteSize ( ) ,
data . GetByteSize ( ) ) ;
2013-08-23 13:46:38 -04:00
}
return ;
}
size_t bit_align = m_variable_sp - > GetType ( ) - > GetClangLayoutType ( ) . GetTypeBitAlign ( ) ;
size_t byte_align = ( bit_align + 7 ) / 8 ;
2014-02-18 11:23:10 -05:00
if ( ! byte_align )
byte_align = 1 ;
2013-08-23 13:46:38 -04:00
Error alloc_error ;
m_temporary_allocation = map . Malloc ( data . GetByteSize ( ) , byte_align , lldb : : ePermissionsReadable | lldb : : ePermissionsWritable , IRMemoryMap : : eAllocationPolicyMirror , alloc_error ) ;
m_temporary_allocation_size = data . GetByteSize ( ) ;
2014-11-25 16:00:58 -05:00
m_original_data . reset ( new DataBufferHeap ( data . GetDataStart ( ) , data . GetByteSize ( ) ) ) ;
2013-08-23 13:46:38 -04:00
if ( ! alloc_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't allocate a temporary region for %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , alloc_error . AsCString ( ) ) ;
return ;
}
Error write_error ;
map . WriteMemory ( m_temporary_allocation , data . GetDataStart ( ) , data . GetByteSize ( ) , write_error ) ;
if ( ! write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write to the temporary region for %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , write_error . AsCString ( ) ) ;
return ;
}
Error pointer_write_error ;
map . WritePointerToMemory ( load_addr , m_temporary_allocation , pointer_write_error ) ;
if ( ! pointer_write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the address of the temporary region for %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , pointer_write_error . AsCString ( ) ) ;
}
}
}
}
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 )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntityVariable::Dematerialize [address = 0x% " PRIx64 " , m_variable_sp = %s] " ,
( uint64_t ) load_addr ,
m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
}
if ( m_temporary_allocation ! = LLDB_INVALID_ADDRESS )
{
ExecutionContextScope * scope = frame_sp . get ( ) ;
if ( ! scope )
scope = map . GetBestExecutionContextScope ( ) ;
lldb : : ValueObjectSP valobj_sp = ValueObjectVariable : : Create ( scope , m_variable_sp ) ;
if ( ! valobj_sp )
{
err . SetErrorStringWithFormat ( " couldn't get a value object for variable %s " , m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
lldb_private : : DataExtractor data ;
Error extract_error ;
map . GetMemoryData ( data , m_temporary_allocation , valobj_sp - > GetByteSize ( ) , extract_error ) ;
if ( ! extract_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't get the data for variable %s " , m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
2014-11-25 16:00:58 -05:00
bool actually_write = true ;
2013-08-23 13:46:38 -04:00
2014-11-25 16:00:58 -05:00
if ( m_original_data )
{
if ( ( data . GetByteSize ( ) = = m_original_data - > GetByteSize ( ) ) & &
! memcmp ( m_original_data - > GetBytes ( ) , data . GetDataStart ( ) , data . GetByteSize ( ) ) )
{
actually_write = false ;
}
}
2013-08-23 13:46:38 -04:00
2014-11-25 16:00:58 -05:00
Error set_error ;
if ( actually_write )
2013-08-23 13:46:38 -04:00
{
2014-11-25 16:00:58 -05:00
valobj_sp - > SetData ( data , set_error ) ;
if ( ! set_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the new contents of %s back into the variable " , m_variable_sp - > GetName ( ) . AsCString ( ) ) ;
return ;
}
2013-08-23 13:46:38 -04:00
}
Error free_error ;
map . Free ( m_temporary_allocation , free_error ) ;
if ( ! free_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't free the temporary region for %s: %s " , m_variable_sp - > GetName ( ) . AsCString ( ) , free_error . AsCString ( ) ) ;
return ;
}
2014-11-25 16:00:58 -05:00
m_original_data . reset ( ) ;
2013-08-23 13:46:38 -04:00
m_temporary_allocation = LLDB_INVALID_ADDRESS ;
m_temporary_allocation_size = 0 ;
}
}
void DumpToLog ( IRMemoryMap & map , lldb : : addr_t process_address , Log * log )
{
StreamString dump_stream ;
const lldb : : addr_t load_addr = process_address + m_offset ;
dump_stream . Printf ( " 0x% " PRIx64 " : EntityVariable \n " , load_addr ) ;
Error err ;
lldb : : addr_t ptr = LLDB_INVALID_ADDRESS ;
{
dump_stream . Printf ( " Pointer: \n " ) ;
DataBufferHeap data ( m_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , load_addr , m_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
lldb : : offset_t offset ;
ptr = extractor . GetPointer ( & offset ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
if ( m_temporary_allocation = = LLDB_INVALID_ADDRESS )
{
dump_stream . Printf ( " Points to process memory: \n " ) ;
}
else
{
dump_stream . Printf ( " Temporary allocation: \n " ) ;
}
if ( ptr = = LLDB_INVALID_ADDRESS )
{
dump_stream . Printf ( " <could not be be found> \n " ) ;
}
else
{
DataBufferHeap data ( m_temporary_allocation_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , m_temporary_allocation , m_temporary_allocation_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
log - > PutCString ( dump_stream . GetData ( ) ) ;
}
void Wipe ( IRMemoryMap & map , lldb : : addr_t process_address )
{
if ( m_temporary_allocation ! = LLDB_INVALID_ADDRESS )
{
Error free_error ;
map . Free ( m_temporary_allocation , free_error ) ;
m_temporary_allocation = LLDB_INVALID_ADDRESS ;
m_temporary_allocation_size = 0 ;
}
}
private :
lldb : : VariableSP m_variable_sp ;
bool m_is_reference ;
lldb : : addr_t m_temporary_allocation ;
size_t m_temporary_allocation_size ;
2014-11-25 16:00:58 -05:00
lldb : : DataBufferSP m_original_data ;
2013-08-23 13:46:38 -04:00
} ;
uint32_t
Materializer : : AddVariable ( lldb : : VariableSP & variable_sp , Error & err )
{
EntityVector : : iterator iter = m_entities . insert ( m_entities . end ( ) , EntityUP ( ) ) ;
iter - > reset ( new EntityVariable ( variable_sp ) ) ;
uint32_t ret = AddStructMember ( * * iter ) ;
( * iter ) - > SetOffset ( ret ) ;
return ret ;
}
class EntityResultVariable : public Materializer : : Entity
{
public :
EntityResultVariable ( const TypeFromUser & type , bool is_program_reference , bool keep_in_memory ) :
Entity ( ) ,
m_type ( type ) ,
m_is_program_reference ( is_program_reference ) ,
m_keep_in_memory ( keep_in_memory ) ,
m_temporary_allocation ( LLDB_INVALID_ADDRESS ) ,
m_temporary_allocation_size ( 0 )
{
// Hard-coding to maximum size of a pointer since all results are materialized by reference
m_size = 8 ;
m_alignment = 8 ;
}
void Materialize ( lldb : : StackFrameSP & frame_sp , IRMemoryMap & map , lldb : : addr_t process_address , Error & err )
{
if ( ! m_is_program_reference )
{
if ( m_temporary_allocation ! = LLDB_INVALID_ADDRESS )
{
err . SetErrorString ( " Trying to create a temporary region for the result but one exists " ) ;
return ;
}
const lldb : : addr_t load_addr = process_address + m_offset ;
2015-02-08 20:44:09 -05:00
size_t byte_size = m_type . GetByteSize ( nullptr ) ;
2013-08-23 13:46:38 -04:00
size_t bit_align = m_type . GetTypeBitAlign ( ) ;
size_t byte_align = ( bit_align + 7 ) / 8 ;
2014-02-18 11:23:10 -05:00
if ( ! byte_align )
byte_align = 1 ;
2013-08-23 13:46:38 -04:00
Error alloc_error ;
m_temporary_allocation = map . Malloc ( byte_size , byte_align , lldb : : ePermissionsReadable | lldb : : ePermissionsWritable , IRMemoryMap : : eAllocationPolicyMirror , alloc_error ) ;
m_temporary_allocation_size = byte_size ;
if ( ! alloc_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't allocate a temporary region for the result: %s " , alloc_error . AsCString ( ) ) ;
return ;
}
Error pointer_write_error ;
map . WritePointerToMemory ( load_addr , m_temporary_allocation , pointer_write_error ) ;
if ( ! pointer_write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the address of the temporary region for the result: %s " , pointer_write_error . AsCString ( ) ) ;
}
}
}
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 )
{
err . SetErrorString ( " Tried to detmaterialize a result variable with the normal Dematerialize method " ) ;
}
void Dematerialize ( lldb : : ClangExpressionVariableSP & result_variable_sp ,
lldb : : StackFrameSP & frame_sp ,
IRMemoryMap & map ,
lldb : : addr_t process_address ,
lldb : : addr_t frame_top ,
lldb : : addr_t frame_bottom ,
Error & err )
{
err . Clear ( ) ;
ExecutionContextScope * exe_scope = map . GetBestExecutionContextScope ( ) ;
if ( ! exe_scope )
{
err . SetErrorString ( " Couldn't dematerialize a result variable: invalid execution context scope " ) ;
return ;
}
lldb : : addr_t address ;
Error read_error ;
const lldb : : addr_t load_addr = process_address + m_offset ;
map . ReadPointerFromMemory ( & address , load_addr , read_error ) ;
if ( ! read_error . Success ( ) )
{
err . SetErrorString ( " Couldn't dematerialize a result variable: couldn't read its address " ) ;
return ;
}
lldb : : TargetSP target_sp = exe_scope - > CalculateTarget ( ) ;
if ( ! target_sp )
{
err . SetErrorString ( " Couldn't dematerialize a result variable: no target " ) ;
return ;
}
ConstString name = target_sp - > GetPersistentVariables ( ) . GetNextPersistentVariableName ( ) ;
lldb : : ClangExpressionVariableSP ret ;
ret = target_sp - > GetPersistentVariables ( ) . CreateVariable ( exe_scope ,
name ,
m_type ,
map . GetByteOrder ( ) ,
map . GetAddressByteSize ( ) ) ;
if ( ! ret )
{
err . SetErrorStringWithFormat ( " couldn't dematerialize a result variable: failed to make persistent variable %s " , name . AsCString ( ) ) ;
return ;
}
lldb : : ProcessSP process_sp = map . GetBestExecutionContextScope ( ) - > CalculateProcess ( ) ;
bool can_persist = ( m_is_program_reference & & process_sp & & process_sp - > CanJIT ( ) & & ! ( address > = frame_bottom & & address < frame_top ) ) ;
if ( can_persist & & m_keep_in_memory )
{
ret - > m_live_sp = ValueObjectConstResult : : Create ( exe_scope ,
m_type ,
name ,
address ,
eAddressTypeLoad ,
2013-11-06 11:48:53 -05:00
map . GetAddressByteSize ( ) ) ;
2013-08-23 13:46:38 -04:00
}
ret - > ValueUpdated ( ) ;
const size_t pvar_byte_size = ret - > GetByteSize ( ) ;
uint8_t * pvar_data = ret - > GetValueBytes ( ) ;
map . ReadMemory ( pvar_data , address , pvar_byte_size , read_error ) ;
if ( ! read_error . Success ( ) )
{
err . SetErrorString ( " Couldn't dematerialize a result variable: couldn't read its memory " ) ;
return ;
}
result_variable_sp = ret ;
if ( ! can_persist | | ! m_keep_in_memory )
{
ret - > m_flags | = ClangExpressionVariable : : EVNeedsAllocation ;
if ( m_temporary_allocation ! = LLDB_INVALID_ADDRESS )
{
Error free_error ;
map . Free ( m_temporary_allocation , free_error ) ;
}
}
else
{
ret - > m_flags | = ClangExpressionVariable : : EVIsLLDBAllocated ;
}
m_temporary_allocation = LLDB_INVALID_ADDRESS ;
m_temporary_allocation_size = 0 ;
}
void DumpToLog ( IRMemoryMap & map , lldb : : addr_t process_address , Log * log )
{
StreamString dump_stream ;
const lldb : : addr_t load_addr = process_address + m_offset ;
dump_stream . Printf ( " 0x% " PRIx64 " : EntityResultVariable \n " , load_addr ) ;
Error err ;
lldb : : addr_t ptr = LLDB_INVALID_ADDRESS ;
{
dump_stream . Printf ( " Pointer: \n " ) ;
DataBufferHeap data ( m_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , load_addr , m_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
lldb : : offset_t offset ;
ptr = extractor . GetPointer ( & offset ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
if ( m_temporary_allocation = = LLDB_INVALID_ADDRESS )
{
dump_stream . Printf ( " Points to process memory: \n " ) ;
}
else
{
dump_stream . Printf ( " Temporary allocation: \n " ) ;
}
if ( ptr = = LLDB_INVALID_ADDRESS )
{
dump_stream . Printf ( " <could not be be found> \n " ) ;
}
else
{
DataBufferHeap data ( m_temporary_allocation_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , m_temporary_allocation , m_temporary_allocation_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
log - > PutCString ( dump_stream . GetData ( ) ) ;
}
void Wipe ( IRMemoryMap & map , lldb : : addr_t process_address )
{
if ( ! m_keep_in_memory & & m_temporary_allocation ! = LLDB_INVALID_ADDRESS )
{
Error free_error ;
map . Free ( m_temporary_allocation , free_error ) ;
}
m_temporary_allocation = LLDB_INVALID_ADDRESS ;
m_temporary_allocation_size = 0 ;
}
private :
TypeFromUser m_type ;
bool m_is_program_reference ;
bool m_keep_in_memory ;
lldb : : addr_t m_temporary_allocation ;
size_t m_temporary_allocation_size ;
} ;
uint32_t
Materializer : : AddResultVariable ( const TypeFromUser & type , bool is_program_reference , bool keep_in_memory , Error & err )
{
EntityVector : : iterator iter = m_entities . insert ( m_entities . end ( ) , EntityUP ( ) ) ;
iter - > reset ( new EntityResultVariable ( type , is_program_reference , keep_in_memory ) ) ;
uint32_t ret = AddStructMember ( * * iter ) ;
( * iter ) - > SetOffset ( ret ) ;
m_result_entity = iter - > get ( ) ;
return ret ;
}
class EntitySymbol : public Materializer : : Entity
{
public :
EntitySymbol ( const Symbol & symbol ) :
Entity ( ) ,
m_symbol ( symbol )
{
// Hard-coding to maximum size of a symbol
m_size = 8 ;
m_alignment = 8 ;
}
void Materialize ( lldb : : StackFrameSP & frame_sp , IRMemoryMap & map , lldb : : addr_t process_address , Error & err )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntitySymbol::Materialize [address = 0x% " PRIx64 " , m_symbol = %s] " ,
( uint64_t ) load_addr ,
m_symbol . GetName ( ) . AsCString ( ) ) ;
}
2015-07-03 12:57:06 -04:00
const Address sym_address = m_symbol . GetAddress ( ) ;
2013-08-23 13:46:38 -04:00
ExecutionContextScope * exe_scope = map . GetBestExecutionContextScope ( ) ;
lldb : : TargetSP target_sp ;
if ( exe_scope )
target_sp = map . GetBestExecutionContextScope ( ) - > CalculateTarget ( ) ;
if ( ! target_sp )
{
err . SetErrorStringWithFormat ( " couldn't resolve symbol %s because there is no target " , m_symbol . GetName ( ) . AsCString ( ) ) ;
return ;
}
lldb : : addr_t resolved_address = sym_address . GetLoadAddress ( target_sp . get ( ) ) ;
if ( resolved_address = = LLDB_INVALID_ADDRESS )
resolved_address = sym_address . GetFileAddress ( ) ;
Error pointer_write_error ;
map . WritePointerToMemory ( load_addr , resolved_address , pointer_write_error ) ;
if ( ! pointer_write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the address of symbol %s: %s " , m_symbol . GetName ( ) . AsCString ( ) , pointer_write_error . AsCString ( ) ) ;
return ;
}
}
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 )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntitySymbol::Dematerialize [address = 0x% " PRIx64 " , m_symbol = %s] " ,
( uint64_t ) load_addr ,
m_symbol . GetName ( ) . AsCString ( ) ) ;
}
// no work needs to be done
}
void DumpToLog ( IRMemoryMap & map , lldb : : addr_t process_address , Log * log )
{
StreamString dump_stream ;
Error err ;
const lldb : : addr_t load_addr = process_address + m_offset ;
dump_stream . Printf ( " 0x% " PRIx64 " : EntitySymbol (%s) \n " , load_addr , m_symbol . GetName ( ) . AsCString ( ) ) ;
{
dump_stream . Printf ( " Pointer: \n " ) ;
DataBufferHeap data ( m_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , load_addr , m_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
log - > PutCString ( dump_stream . GetData ( ) ) ;
}
void Wipe ( IRMemoryMap & map , lldb : : addr_t process_address )
{
}
private :
Symbol m_symbol ;
} ;
uint32_t
Materializer : : AddSymbol ( const Symbol & symbol_sp , Error & err )
{
EntityVector : : iterator iter = m_entities . insert ( m_entities . end ( ) , EntityUP ( ) ) ;
iter - > reset ( new EntitySymbol ( symbol_sp ) ) ;
uint32_t ret = AddStructMember ( * * iter ) ;
( * iter ) - > SetOffset ( ret ) ;
return ret ;
}
class EntityRegister : public Materializer : : Entity
{
public :
EntityRegister ( const RegisterInfo & register_info ) :
Entity ( ) ,
m_register_info ( register_info )
{
// Hard-coding alignment conservatively
m_size = m_register_info . byte_size ;
m_alignment = m_register_info . byte_size ;
}
void Materialize ( lldb : : StackFrameSP & frame_sp , IRMemoryMap & map , lldb : : addr_t process_address , Error & err )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntityRegister::Materialize [address = 0x% " PRIx64 " , m_register_info = %s] " ,
( uint64_t ) load_addr ,
m_register_info . name ) ;
}
RegisterValue reg_value ;
if ( ! frame_sp . get ( ) )
{
err . SetErrorStringWithFormat ( " couldn't materialize register %s without a stack frame " , m_register_info . name ) ;
return ;
}
lldb : : RegisterContextSP reg_context_sp = frame_sp - > GetRegisterContext ( ) ;
if ( ! reg_context_sp - > ReadRegister ( & m_register_info , reg_value ) )
{
err . SetErrorStringWithFormat ( " couldn't read the value of register %s " , m_register_info . name ) ;
return ;
}
DataExtractor register_data ;
if ( ! reg_value . GetData ( register_data ) )
{
err . SetErrorStringWithFormat ( " couldn't get the data for register %s " , m_register_info . name ) ;
return ;
}
if ( register_data . GetByteSize ( ) ! = m_register_info . byte_size )
{
err . SetErrorStringWithFormat ( " data for register %s had size %llu but we expected %llu " , m_register_info . name , ( unsigned long long ) register_data . GetByteSize ( ) , ( unsigned long long ) m_register_info . byte_size ) ;
return ;
}
m_register_contents . reset ( new DataBufferHeap ( register_data . GetDataStart ( ) , register_data . GetByteSize ( ) ) ) ;
Error write_error ;
map . WriteMemory ( load_addr , register_data . GetDataStart ( ) , register_data . GetByteSize ( ) , write_error ) ;
if ( ! write_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't write the contents of register %s: %s " , m_register_info . name , write_error . AsCString ( ) ) ;
return ;
}
}
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 )
{
Log * log ( lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) ) ;
const lldb : : addr_t load_addr = process_address + m_offset ;
if ( log )
{
log - > Printf ( " EntityRegister::Dematerialize [address = 0x% " PRIx64 " , m_register_info = %s] " ,
( uint64_t ) load_addr ,
m_register_info . name ) ;
}
Error extract_error ;
DataExtractor register_data ;
if ( ! frame_sp . get ( ) )
{
err . SetErrorStringWithFormat ( " couldn't dematerialize register %s without a stack frame " , m_register_info . name ) ;
return ;
}
lldb : : RegisterContextSP reg_context_sp = frame_sp - > GetRegisterContext ( ) ;
map . GetMemoryData ( register_data , load_addr , m_register_info . byte_size , extract_error ) ;
if ( ! extract_error . Success ( ) )
{
err . SetErrorStringWithFormat ( " couldn't get the data for register %s: %s " , m_register_info . name , extract_error . AsCString ( ) ) ;
return ;
}
if ( ! memcmp ( register_data . GetDataStart ( ) , m_register_contents - > GetBytes ( ) , register_data . GetByteSize ( ) ) )
{
// No write required, and in particular we avoid errors if the register wasn't writable
m_register_contents . reset ( ) ;
return ;
}
m_register_contents . reset ( ) ;
RegisterValue register_value ( const_cast < uint8_t * > ( register_data . GetDataStart ( ) ) , register_data . GetByteSize ( ) , register_data . GetByteOrder ( ) ) ;
if ( ! reg_context_sp - > WriteRegister ( & m_register_info , register_value ) )
{
err . SetErrorStringWithFormat ( " couldn't write the value of register %s " , m_register_info . name ) ;
return ;
}
}
void DumpToLog ( IRMemoryMap & map , lldb : : addr_t process_address , Log * log )
{
StreamString dump_stream ;
Error err ;
const lldb : : addr_t load_addr = process_address + m_offset ;
dump_stream . Printf ( " 0x% " PRIx64 " : EntityRegister (%s) \n " , load_addr , m_register_info . name ) ;
{
dump_stream . Printf ( " Value: \n " ) ;
DataBufferHeap data ( m_size , 0 ) ;
map . ReadMemory ( data . GetBytes ( ) , load_addr , m_size , err ) ;
if ( ! err . Success ( ) )
{
dump_stream . Printf ( " <could not be read> \n " ) ;
}
else
{
DataExtractor extractor ( data . GetBytes ( ) , data . GetByteSize ( ) , map . GetByteOrder ( ) , map . GetAddressByteSize ( ) ) ;
extractor . DumpHexBytes ( & dump_stream , data . GetBytes ( ) , data . GetByteSize ( ) , 16 , load_addr ) ;
dump_stream . PutChar ( ' \n ' ) ;
}
}
log - > PutCString ( dump_stream . GetData ( ) ) ;
}
void Wipe ( IRMemoryMap & map , lldb : : addr_t process_address )
{
}
private :
RegisterInfo m_register_info ;
lldb : : DataBufferSP m_register_contents ;
} ;
uint32_t
Materializer : : AddRegister ( const RegisterInfo & register_info , Error & err )
{
EntityVector : : iterator iter = m_entities . insert ( m_entities . end ( ) , EntityUP ( ) ) ;
iter - > reset ( new EntityRegister ( register_info ) ) ;
uint32_t ret = AddStructMember ( * * iter ) ;
( * iter ) - > SetOffset ( ret ) ;
return ret ;
}
Materializer : : Materializer ( ) :
m_dematerializer_wp ( ) ,
m_result_entity ( NULL ) ,
m_current_offset ( 0 ) ,
m_struct_alignment ( 8 )
{
}
Materializer : : ~ Materializer ( )
{
DematerializerSP dematerializer_sp = m_dematerializer_wp . lock ( ) ;
if ( dematerializer_sp )
dematerializer_sp - > Wipe ( ) ;
}
Materializer : : DematerializerSP
Materializer : : Materialize ( lldb : : StackFrameSP & frame_sp , IRMemoryMap & map , lldb : : addr_t process_address , Error & error )
{
ExecutionContextScope * exe_scope = frame_sp . get ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! exe_scope )
exe_scope = map . GetBestExecutionContextScope ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DematerializerSP dematerializer_sp = m_dematerializer_wp . lock ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( dematerializer_sp )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorString ( " Couldn't materialize: already materialized " ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
DematerializerSP ret ( new Dematerializer ( * this , frame_sp , map , process_address ) ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! exe_scope )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorString ( " Couldn't materialize: target doesn't exist " ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
for ( EntityUP & entity_up : m_entities )
{
entity_up - > Materialize ( frame_sp , map , process_address , error ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! error . Success ( ) )
return DematerializerSP ( ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( Log * log = lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) )
{
2014-11-25 16:00:58 -05:00
log - > Printf ( " Materializer::Materialize (frame_sp = %p, process_address = 0x% " PRIx64 " ) materialized: " ,
static_cast < void * > ( frame_sp . get ( ) ) , process_address ) ;
2013-08-23 13:46:38 -04:00
for ( EntityUP & entity_up : m_entities )
entity_up - > DumpToLog ( map , process_address , log ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
m_dematerializer_wp = ret ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
return ret ;
}
void
Materializer : : Dematerializer : : Dematerialize ( Error & error , lldb : : ClangExpressionVariableSP & result_sp , lldb : : addr_t frame_bottom , lldb : : addr_t frame_top )
{
lldb : : StackFrameSP frame_sp ;
lldb : : ThreadSP thread_sp = m_thread_wp . lock ( ) ;
if ( thread_sp )
frame_sp = thread_sp - > GetFrameWithStackID ( m_stack_id ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
ExecutionContextScope * exe_scope = m_map - > GetBestExecutionContextScope ( ) ;
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! IsValid ( ) )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorString ( " Couldn't dematerialize: invalid dematerializer " ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! exe_scope )
{
error . SetErrorToGenericError ( ) ;
error . SetErrorString ( " Couldn't dematerialize: target is gone " ) ;
}
else
{
if ( Log * log = lldb_private : : GetLogIfAllCategoriesSet ( LIBLLDB_LOG_EXPRESSIONS ) )
{
2014-11-25 16:00:58 -05:00
log - > Printf ( " Materializer::Dematerialize (frame_sp = %p, process_address = 0x% " PRIx64 " ) about to dematerialize: " ,
static_cast < void * > ( frame_sp . get ( ) ) , m_process_address ) ;
2013-08-23 13:46:38 -04:00
for ( EntityUP & entity_up : m_materializer - > m_entities )
entity_up - > DumpToLog ( * m_map , m_process_address , log ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
for ( EntityUP & entity_up : m_materializer - > m_entities )
{
if ( entity_up . get ( ) = = m_materializer - > m_result_entity )
{
static_cast < EntityResultVariable * > ( m_materializer - > m_result_entity ) - > Dematerialize ( result_sp , frame_sp , * m_map , m_process_address , frame_top , frame_bottom , error ) ;
}
else
{
entity_up - > Dematerialize ( frame_sp , * m_map , m_process_address , frame_top , frame_bottom , error ) ;
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
if ( ! error . Success ( ) )
break ;
}
}
2014-11-25 16:00:58 -05:00
2013-08-23 13:46:38 -04:00
Wipe ( ) ;
}
void
Materializer : : Dematerializer : : Wipe ( )
{
if ( ! IsValid ( ) )
return ;
for ( EntityUP & entity_up : m_materializer - > m_entities )
{
entity_up - > Wipe ( * m_map , m_process_address ) ;
}
m_materializer = NULL ;
m_map = NULL ;
m_process_address = LLDB_INVALID_ADDRESS ;
}