summaryrefslogtreecommitdiffstats
path: root/lldb/examples
diff options
context:
space:
mode:
authorGreg Clayton <gclayton@apple.com>2012-09-11 18:10:27 +0000
committerGreg Clayton <gclayton@apple.com>2012-09-11 18:10:27 +0000
commit4b963415c20bc38b5c0ae0fdbcfa4e94050ab150 (patch)
tree78791c625bea525bbdd8e3db84d32b0a34ffedf2 /lldb/examples
parent571d9e4b804701593b6c0a5fb7a0d3beff9923dd (diff)
downloadbcm5719-llvm-4b963415c20bc38b5c0ae0fdbcfa4e94050ab150.tar.gz
bcm5719-llvm-4b963415c20bc38b5c0ae0fdbcfa4e94050ab150.zip
Added "heap" command to get info on all allocations on the heap. Currently only objective C objects are supported since they are easy to detect.
llvm-svn: 163637
Diffstat (limited to 'lldb/examples')
-rw-r--r--lldb/examples/darwin/heap_find/heap.py42
-rw-r--r--lldb/examples/darwin/heap_find/heap/heap_find.cpp110
2 files changed, 113 insertions, 39 deletions
diff --git a/lldb/examples/darwin/heap_find/heap.py b/lldb/examples/darwin/heap_find/heap.py
index 4e002cfb4ab..8aed86aab0a 100644
--- a/lldb/examples/darwin/heap_find/heap.py
+++ b/lldb/examples/darwin/heap_find/heap.py
@@ -282,6 +282,7 @@ def heap_search(result, options, arg_str):
result.AppendMessage(dylid_load_err)
return
expr = None
+ print_no_matches = True
arg_str_description = arg_str
if options.type == 'pointer':
expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
@@ -301,6 +302,10 @@ def heap_search(result, options, arg_str):
elif options.type == 'addr':
expr = 'find_block_for_address((void *)%s)' % arg_str
arg_str_description = 'malloc block for %s' % arg_str
+ elif options.type == 'all':
+ expr = 'get_heap_info(1)'
+ arg_str_description = None
+ print_no_matches = False
else:
result.AppendMessage('error: invalid type "%s"\nvalid values are "pointer", "cstr"' % options.type)
return
@@ -378,29 +383,24 @@ def malloc_info(debugger, command, result, dict):
else:
result.AppendMessage('error: no c string arguments were given to search for')
-def malloc_history(debugger, command, result, dict):
+def heap(debugger, command, result, dict):
command_args = shlex.split(command)
usage = "usage: %prog [options] <EXPR> [EXPR ...]"
- description='''Gets the allocation history for an expression whose result is an address.
+ description='''Traverse all allocations on the heap and report statistics.
- Programs should set the MallocStackLogging=1 in the environment to enable stack history. This can be done
- with "process launch -v MallocStackLogging=1 -- [arg1 ...]"'''
-
- dylid_load_err = load_dylib()
- if dylid_load_err:
- result.AppendMessage(dylid_load_err)
+ If programs set the MallocStackLogging=1 in the environment, then stack
+ history is available for any allocations. '''
+ parser = optparse.OptionParser(description=description, prog='cstr_refs',usage=usage)
+ add_common_options(parser)
+ try:
+ (options, args) = parser.parse_args(command_args)
+ except:
+ return
+ options.type = 'all'
+ if args:
+ result.AppendMessage('error: heap command takes no arguments, only options')
else:
- if command_args:
- for addr_expr_str in command_args:
- expr_sbvalue = lldb.frame.EvaluateExpression (addr_expr_str)
- if expr_sbvalue.error.Success():
- addr = expr_sbvalue.unsigned
- if addr != 0:
- dump_stack_history_entries (addr, 1)
- else:
- result.AppendMessage('error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error))
- else:
- result.AppendMessage('error: no address expressions were specified')
+ heap_search (result, options, None)
def section_ptr_refs(debugger, command, result, dict):
command_args = shlex.split(command)
@@ -490,10 +490,10 @@ if __name__ == '__main__':
lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.ptr_refs ptr_refs')
lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.cstr_refs cstr_refs')
lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_info malloc_info')
-lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.malloc_history malloc_history')
+lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.heap heap')
lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.section_ptr_refs section_ptr_refs')
lldb.debugger.HandleCommand('command script add -f lldb.macosx.heap.objc_refs objc_refs')
-print '"ptr_refs", "cstr_refs", "malloc_info", "malloc_history" and "section_ptr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
+print '"ptr_refs", "cstr_refs", "malloc_info", "heap" and "section_ptr_refs" commands have been installed, use the "--help" options on these commands for detailed help.'
diff --git a/lldb/examples/darwin/heap_find/heap/heap_find.cpp b/lldb/examples/darwin/heap_find/heap/heap_find.cpp
index b6663d84866..96872864dde 100644
--- a/lldb/examples/darwin/heap_find/heap/heap_find.cpp
+++ b/lldb/examples/darwin/heap_find/heap/heap_find.cpp
@@ -159,7 +159,8 @@ enum data_type_t
{
eDataTypeAddress,
eDataTypeContainsData,
- eDataTypeObjC
+ eDataTypeObjC,
+ eDataTypeHeapInfo
};
struct aligned_data_t
@@ -205,6 +206,14 @@ struct malloc_stack_entry
mach_vm_address_t frames[MAX_FRAMES];
};
+struct malloc_block_contents
+{
+ union {
+ Class isa;
+ void *pointers[2];
+ };
+};
+
static int
compare_void_ptr (const void *a, const void *b)
{
@@ -418,6 +427,14 @@ ObjCClasses g_objc_classes;
//----------------------------------------------------------------------
// ObjCClassInfo
//----------------------------------------------------------------------
+
+enum HeapInfoSortType
+{
+ eSortTypeNone,
+ eSortTypeBytes,
+ eSortTypeCount
+};
+
class ObjCClassInfo
{
public:
@@ -529,15 +546,9 @@ private:
return 0;
}
- enum SortType
- {
- eSortTypeNone,
- eSortTypeBytes,
- eSortTypeCount
- };
Entry *m_entries;
uint32_t m_size;
- SortType m_sort_type;
+ HeapInfoSortType m_sort_type;
};
ObjCClassInfo g_objc_class_snapshot;
@@ -667,16 +678,15 @@ range_info_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr,
// of any sort where the first pointer in the object is an OBJC class
// pointer (an isa)
{
- struct objc_class *objc_object_ptr = NULL;
- if (task_peek (task, ptr_addr, sizeof(void *), (void **)&objc_object_ptr) == KERN_SUCCESS)
+ malloc_block_contents *block_contents = NULL;
+ if (task_peek (task, ptr_addr, sizeof(void *), (void **)&block_contents) == KERN_SUCCESS)
{
// We assume that g_objc_classes is up to date
// that the class list was verified to have some classes in it
// before calling this function
- const uint32_t objc_class_idx = g_objc_classes.FindClassIndex (objc_object_ptr->isa);
+ const uint32_t objc_class_idx = g_objc_classes.FindClassIndex (block_contents->isa);
if (objc_class_idx != UINT32_MAX)
{
- g_objc_class_snapshot.AddInstance (objc_class_idx, ptr_size);
bool match = false;
if (info->objc.match_isa == 0)
{
@@ -687,11 +697,11 @@ range_info_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr,
{
// Only match exact isa values in the current class or
// optionally in the super classes
- if (info->objc.match_isa == objc_object_ptr->isa)
+ if (info->objc.match_isa == block_contents->isa)
match = true;
else if (info->objc.match_superclasses)
{
- Class super = class_getSuperclass(objc_object_ptr->isa);
+ Class super = class_getSuperclass(block_contents->isa);
while (super)
{
match = super == info->objc.match_isa;
@@ -721,6 +731,32 @@ range_info_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr,
}
}
break;
+
+ case eDataTypeHeapInfo:
+ // Check if the current malloc block contains an objective C object
+ // of any sort where the first pointer in the object is an OBJC class
+ // pointer (an isa)
+ {
+ malloc_block_contents *block_contents = NULL;
+ if (task_peek (task, ptr_addr, sizeof(void *), (void **)&block_contents) == KERN_SUCCESS)
+ {
+ // We assume that g_objc_classes is up to date
+ // that the class list was verified to have some classes in it
+ // before calling this function
+ const uint32_t objc_class_idx = g_objc_classes.FindClassIndex (block_contents->isa);
+ if (objc_class_idx != UINT32_MAX)
+ {
+ // This is an objective C object
+ g_objc_class_snapshot.AddInstance (objc_class_idx, ptr_size);
+ }
+ else
+ {
+ // Classify other heap info
+ }
+ }
+ }
+ break;
+
}
}
@@ -851,8 +887,6 @@ find_objc_objects_in_memory (void *isa)
g_matches.clear();
if (g_objc_classes.Update())
{
- // Reset all stats
- g_objc_class_snapshot.Reset ();
// Setup "info" to look for a malloc block that contains data
// that is the a pointer
range_contains_data_callback_info_t data_info;
@@ -863,11 +897,51 @@ find_objc_objects_in_memory (void *isa)
data_info.done = false; // Set done to false so searching doesn't stop
range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
foreach_zone_in_this_process (&info);
+ }
+ return g_matches.data();
+}
+
+//----------------------------------------------------------------------
+// get_heap_info
+//
+// Gather information for all allocations on the heap and report
+// statistics.
+//----------------------------------------------------------------------
+
+void
+get_heap_info (int sort_type)
+{
+ if (g_objc_classes.Update())
+ {
+ // Reset all stats
+ g_objc_class_snapshot.Reset ();
+ // Setup "info" to look for a malloc block that contains data
+ // that is the a pointer
+ range_contains_data_callback_info_t data_info;
+ data_info.type = eDataTypeHeapInfo; // Check each block for data
+ data_info.match_count = 0; // Initialize the match count to zero
+ data_info.done = false; // Set done to false so searching doesn't stop
+ range_callback_info_t info = { enumerate_range_in_zone, range_info_callback, &data_info };
+ foreach_zone_in_this_process (&info);
// Sort and print byte total bytes
- g_objc_class_snapshot.SortByTotalBytes(g_objc_classes, true);
+ switch (sort_type)
+ {
+ case eSortTypeNone:
+ default:
+ case eSortTypeBytes:
+ g_objc_class_snapshot.SortByTotalBytes(g_objc_classes, true);
+ break;
+
+ case eSortTypeCount:
+ g_objc_class_snapshot.SortByTotalCount(g_objc_classes, true);
+ break;
+ }
+ }
+ else
+ {
+ printf ("error: no objective C classes\n");
}
- return g_matches.data();
}
//----------------------------------------------------------------------
OpenPOWER on IntegriCloud