Make const result value objects able to return dynamic types.

Modified the heap.py to be able to correctly indentify the exact ivar for the "ptr_refs" command no matter how deep the ivar is in a class hierarchy. Also fixed the ability for the heap command to symbolicate the stack backtrace when MallocStackLogging is set in the environment and the "--stack" option was specified.

llvm-svn: 159883
This commit is contained in:
Greg Clayton 2012-07-07 01:22:45 +00:00
parent 3b18fbd983
commit 9407302d37
6 changed files with 110 additions and 77 deletions

View File

@ -77,6 +77,41 @@ def load_dylib():
if lldb.target.FindModule(libheap_dylib_spec):
return None # success, 'libheap.dylib' already loaded
return 'error: failed to load "%s"' % libheap_dylib_path
def get_member_types_for_offset(value_type, offset, member_list):
member = value_type.GetFieldAtIndex(0)
search_bases = False
if member:
if member.GetOffsetInBytes() <= offset:
for field_idx in range (value_type.GetNumberOfFields()):
member = value_type.GetFieldAtIndex(field_idx)
member_byte_offset = member.GetOffsetInBytes()
member_end_byte_offset = member_byte_offset + member.type.size
if member_byte_offset <= offset and offset < member_end_byte_offset:
member_list.append(member)
get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
return
else:
search_bases = True
else:
search_bases = True
if search_bases:
for field_idx in range (value_type.GetNumberOfDirectBaseClasses()):
member = value_type.GetDirectBaseClassAtIndex(field_idx)
member_byte_offset = member.GetOffsetInBytes()
member_end_byte_offset = member_byte_offset + member.type.size
if member_byte_offset <= offset and offset < member_end_byte_offset:
member_list.append(member)
get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
return
for field_idx in range (value_type.GetNumberOfVirtualBaseClasses()):
member = value_type.GetVirtualBaseClassAtIndex(field_idx)
member_byte_offset = member.GetOffsetInBytes()
member_end_byte_offset = member_byte_offset + member.type.size
if member_byte_offset <= offset and offset < member_end_byte_offset:
member_list.append(member)
get_member_types_for_offset (member.type, offset - member_byte_offset, member_list)
return
def add_common_options(parser):
parser.add_option('-v', '--verbose', action='store_true', dest='verbose', help='display verbose debug info', default=False)
@ -179,15 +214,13 @@ def heap_search(options, arg_str):
break
malloc_size = int(match_entry.size)
offset = int(match_entry.offset)
match_addr = malloc_addr + offset
dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
# If the type is still 'void *' then we weren't able to figure
# out a dynamic type for the malloc_addr
type_name = dynamic_value.type.name
description = '[%u] %s: addr = 0x%x' % (i, arg_str_description, malloc_addr)
if offset != 0:
description += ' + %u' % (offset)
description += ', size = %u' % (malloc_size)
if type_name == 'void *':
if dynamic_value.type.name == 'void *':
if options.type == 'pointer' and malloc_size == 4096:
error = lldb.SBError()
data = bytearray(lldb.process.ReadMemory(malloc_addr, 16, error))
@ -195,50 +228,32 @@ def heap_search(options, arg_str):
description += ', type = (AUTORELEASE!)'
print description
else:
description += ', type = %s' % (type_name)
derefed_dynamic_value = dynamic_value.deref
ivar_member = None
if derefed_dynamic_value:
if derefed_dynamic_value:
derefed_dynamic_type = derefed_dynamic_value.type
member = derefed_dynamic_type.GetFieldAtIndex(0)
search_bases = False
if member:
if member.GetOffsetInBytes() <= offset:
for field_idx in range (derefed_dynamic_type.GetNumberOfFields()):
member = derefed_dynamic_type.GetFieldAtIndex(field_idx)
member_byte_offset = member.GetOffsetInBytes()
if member_byte_offset == offset:
ivar_member = member
break
else:
search_bases = True
else:
search_bases = True
if not ivar_member and search_bases:
for field_idx in range (derefed_dynamic_type.GetNumberOfDirectBaseClasses()):
member = derefed_dynamic_type.GetDirectBaseClassAtIndex(field_idx)
member_byte_offset = member.GetOffsetInBytes()
if member_byte_offset == offset:
ivar_member = member
break
if not ivar_member:
for field_idx in range (derefed_dynamic_type.GetNumberOfVirtualBaseClasses()):
member = derefed_dynamic_type.GetVirtualBaseClassAtIndex(field_idx)
member_byte_offset = member.GetOffsetInBytes()
if member_byte_offset == offset:
ivar_member = member
break
if ivar_member:
description +=', ivar = %s' % (ivar_member.name)
print description
if derefed_dynamic_value:
print derefed_dynamic_value
if options.print_object_description:
desc = dynamic_value.GetObjectDescription()
if desc:
print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
derefed_dynamic_type_size = derefed_dynamic_type.size
derefed_dynamic_type_name = derefed_dynamic_type.name
description += ', type = %s <%u>' % (derefed_dynamic_type_name, derefed_dynamic_type_size)
if offset < derefed_dynamic_type_size:
member_list = list();
get_member_types_for_offset (derefed_dynamic_type, offset, member_list)
if member_list:
member_path = ''
for member in member_list:
member_name = member.name
if member_name:
if member_path:
member_path += '.'
member_path += member_name
if member_path:
description += ', ivar = %s' % (member_path)
print description
if derefed_dynamic_value:
print derefed_dynamic_value
if options.print_object_description:
desc = dynamic_value.GetObjectDescription()
if desc:
print ' (%s) 0x%x %s\n' % (type_name, malloc_addr, desc)
if options.memory:
memory_format = options.format
if not memory_format:

View File

@ -408,31 +408,30 @@ class Symbolicator:
image = self.find_image_containing_load_addr (load_addr)
if image:
image.add_module (self.target)
symbolicated_address = Address(self.target, load_addr)
if symbolicated_address.symbolicate (verbose):
if symbolicated_address.so_addr:
symbolicated_addresses = list()
symbolicated_addresses.append(symbolicated_address)
# See if we were able to reconstruct anything?
while 1:
inlined_parent_so_addr = lldb.SBAddress()
inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope (symbolicated_address.so_addr, inlined_parent_so_addr)
if not inlined_parent_sym_ctx:
break
if not inlined_parent_so_addr:
break
symbolicated_address = Address(self.target, load_addr)
if symbolicated_address.symbolicate (verbose):
if symbolicated_address.so_addr:
symbolicated_addresses = list()
symbolicated_addresses.append(symbolicated_address)
# See if we were able to reconstruct anything?
while 1:
inlined_parent_so_addr = lldb.SBAddress()
inlined_parent_sym_ctx = symbolicated_address.sym_ctx.GetParentOfInlinedScope (symbolicated_address.so_addr, inlined_parent_so_addr)
if not inlined_parent_sym_ctx:
break
if not inlined_parent_so_addr:
break
symbolicated_address = Address(self.target, inlined_parent_so_addr.GetLoadAddress(self.target))
symbolicated_address.sym_ctx = inlined_parent_sym_ctx
symbolicated_address.so_addr = inlined_parent_so_addr
symbolicated_address.symbolicate (verbose)
# push the new frame onto the new frame stack
symbolicated_addresses.append (symbolicated_address)
symbolicated_address = Address(self.target, inlined_parent_so_addr.GetLoadAddress(self.target))
symbolicated_address.sym_ctx = inlined_parent_sym_ctx
symbolicated_address.so_addr = inlined_parent_so_addr
symbolicated_address.symbolicate (verbose)
if symbolicated_addresses:
return symbolicated_addresses
# push the new frame onto the new frame stack
symbolicated_addresses.append (symbolicated_address)
if symbolicated_addresses:
return symbolicated_addresses
else:
print 'error: no target in Symbolicator'
return None

View File

@ -823,7 +823,7 @@ public:
virtual lldb::ValueObjectSP
GetSyntheticChildAtOffset(uint32_t offset, const ClangASTType& type, bool can_create);
lldb::ValueObjectSP
virtual lldb::ValueObjectSP
GetDynamicValue (lldb::DynamicValueType valueType);
virtual lldb::ValueObjectSP

View File

@ -131,6 +131,9 @@ public:
m_impl.SetLiveAddress(addr,
address_type);
}
virtual lldb::ValueObjectSP
GetDynamicValue (lldb::DynamicValueType valueType);
protected:
virtual bool
@ -142,13 +145,6 @@ protected:
virtual lldb::clang_type_t
GetClangTypeImpl ();
// CalculateDynamicValue doesn't change the dynamic value, since this can get
// called at any time and you can't reliably fetch the dynamic value at any time.
// If we want to have dynamic values for ConstResults, then we'll need to make them
// up when we make the const result & stuff them in by hand.
virtual void
CalculateDynamicValue (lldb::DynamicValueType use_dynamic) {}
clang::ASTContext *m_clang_ast; // The clang AST that the clang type comes from
ConstString m_type_name;
uint32_t m_byte_size;

View File

@ -180,6 +180,7 @@ protected:
private:
friend class ValueObject;
friend class ValueObjectConstResult;
ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic);
//------------------------------------------------------------------

View File

@ -13,6 +13,7 @@
#include "lldb/Core/ValueObjectConstResultChild.h"
#include "lldb/Core/DataExtractor.h"
#include "lldb/Core/Module.h"
#include "lldb/Core/ValueObjectDynamicValue.h"
#include "lldb/Core/ValueObjectList.h"
#include "lldb/Symbol/ClangASTType.h"
@ -375,3 +376,24 @@ ValueObjectConstResult::GetPointeeData (DataExtractor& data,
{
return m_impl.GetPointeeData(data, item_idx, item_count);
}
lldb::ValueObjectSP
ValueObjectConstResult::GetDynamicValue (lldb::DynamicValueType use_dynamic)
{
// Always recalculate dynamic values for const results as the memory that
// they might point to might have changed at any time.
if (use_dynamic != eNoDynamicValues)
{
if (!IsDynamic())
{
ExecutionContext exe_ctx (GetExecutionContextRef());
Process *process = exe_ctx.GetProcessPtr();
if (process && process->IsPossibleDynamicValue(*this))
m_dynamic_value = new ValueObjectDynamicValue (*this, use_dynamic);
}
if (m_dynamic_value)
return m_dynamic_value->GetSP();
}
return ValueObjectSP();
}