forked from OSchip/llvm-project
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:
parent
3b18fbd983
commit
9407302d37
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -180,6 +180,7 @@ protected:
|
|||
|
||||
private:
|
||||
friend class ValueObject;
|
||||
friend class ValueObjectConstResult;
|
||||
ValueObjectDynamicValue (ValueObject &parent, lldb::DynamicValueType use_dynamic);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue