[Lldb-commits] [lldb] r163135 - in /lldb/trunk/examples/darwin/heap_find: heap.py heap/Makefile heap/heap_find.cpp
Greg Clayton
gclayton at apple.com
Tue Sep 4 07:09:21 PDT 2012
Author: gclayton
Date: Tue Sep 4 09:09:21 2012
New Revision: 163135
URL: http://llvm.org/viewvc/llvm-project?rev=163135&view=rev
Log:
Improved "objc_refs" a bit to be able to find all instances of a class'
superclasses on top of finding the exact class. The current attempt is still
too slow, but it lays the groundwork.
Modified:
lldb/trunk/examples/darwin/heap_find/heap.py
lldb/trunk/examples/darwin/heap_find/heap/Makefile
lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp
Modified: lldb/trunk/examples/darwin/heap_find/heap.py
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap.py?rev=163135&r1=163134&r2=163135&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap.py (original)
+++ lldb/trunk/examples/darwin/heap_find/heap.py Tue Sep 4 09:09:21 2012
@@ -249,14 +249,17 @@
description += ', ivar = %s' % (member_path)
if print_entry:
match_idx += 1
+ result_output = ''
if description:
- result.AppendMessage(description)
+ result_output += description
if options.print_type and derefed_dynamic_value:
- result.AppendMessage('%s' % (derefed_dynamic_value))
+ result_output += '%s' % (derefed_dynamic_value)
if options.print_object_description and dynamic_value:
desc = dynamic_value.GetObjectDescription()
if desc:
- result.AppendMessage(', po=%s' % (desc))
+ result_output += ', po=%s' % (desc)
+ if result_output:
+ result.AppendMessage(result_output)
if options.memory:
cmd_result = lldb.SBCommandReturnObject()
memory_command = "memory read -f %s 0x%x 0x%x" % (options.format, malloc_addr, malloc_addr + malloc_size)
@@ -270,7 +273,7 @@
elif print_no_matches:
result.AppendMessage('no matches found for %s' % (arg_str_description))
else:
- result.AppendMessage(expr_sbvalue.error )
+ result.AppendMessage(str(expr_sbvalue.error))
return 0
def heap_search(result, options, arg_str):
@@ -286,7 +289,8 @@
if options.format == None:
options.format = "A" # 'A' is "address" format
elif options.type == 'isa':
- expr = 'find_pointer_in_heap((void *)%s)' % (arg_str)
+ expr = 'find_objc_objects_in_memory ((void *)%s)' % (arg_str)
+ #result.AppendMessage ('expr -u0 -- %s' % expr) # REMOVE THIS LINE
arg_str_description = 'objective C classes with isa %s' % arg_str
options.offset = 0
if options.format == None:
@@ -473,7 +477,9 @@
else:
result.AppendMessage('error: expression error for "%s": %s' % (addr_expr_str, expr_sbvalue.error))
else:
- result.AppendMessage('error: no address expressions were specified')
+ # Find all objective C objects by not specifying an isa
+ options.type = 'isa'
+ heap_search (result, options, '0x0')
if __name__ == '__main__':
lldb.debugger = lldb.SBDebugger.Create()
Modified: lldb/trunk/examples/darwin/heap_find/heap/Makefile
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap/Makefile?rev=163135&r1=163134&r2=163135&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap/Makefile (original)
+++ lldb/trunk/examples/darwin/heap_find/heap/Makefile Tue Sep 4 09:09:21 2012
@@ -18,7 +18,7 @@
# dsym file.
#----------------------------------------------------------------------
$(EXE) : heap_find.cpp
- $(CXX) $(CFLAGS) -install_name "@executable_path/libheap.dylib" -dynamiclib heap_find.cpp -o "$(EXE)"
+ $(CXX) $(CFLAGS) -install_name "@executable_path/libheap.dylib" -dynamiclib -lobjc heap_find.cpp -o "$(EXE)"
#----------------------------------------------------------------------
# Include all of the makefiles for each source file so we don't have
Modified: lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp?rev=163135&r1=163134&r2=163135&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp (original)
+++ lldb/trunk/examples/darwin/heap_find/heap/heap_find.cpp Tue Sep 4 09:09:21 2012
@@ -66,8 +66,10 @@
#include <assert.h>
#include <ctype.h>
+#include <dlfcn.h>
#include <mach/mach.h>
#include <malloc/malloc.h>
+#include <objc/objc-runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <vector>
@@ -126,6 +128,8 @@
uint32_t *count
);
+extern "C" void *gdb_class_getClass (void *objc_class);
+
//----------------------------------------------------------------------
// Redefine private gloval variables prototypes from
// "/usr/local/include/stack_logging.h"
@@ -154,7 +158,8 @@
enum data_type_t
{
eDataTypeAddress,
- eDataTypeContainsData
+ eDataTypeContainsData,
+ eDataTypeObjC
};
struct aligned_data_t
@@ -164,6 +169,12 @@
uint32_t align;
};
+struct objc_data_t
+{
+ Class match_isa; // Set to NULL for all objective C objects
+ bool match_superclasses;
+};
+
struct range_contains_data_callback_info_t
{
data_type_t type;
@@ -172,6 +183,7 @@
{
uintptr_t addr;
aligned_data_t data;
+ objc_data_t objc;
};
uint32_t match_count;
bool done;
@@ -196,7 +208,6 @@
// Local global variables
//----------------------------------------------------------------------
std::vector<malloc_match> g_matches;
-const void *g_lookup_addr = 0;
std::vector<malloc_stack_entry> g_malloc_stack_history;
mach_vm_address_t g_stack_frames[MAX_FRAMES];
char g_error_string[PATH_MAX];
@@ -280,6 +291,7 @@
switch (info->type)
{
case eDataTypeAddress:
+ // Check if the current malloc block contains an address specified by "info->addr"
if (ptr_addr <= info->addr && info->addr < end_addr)
{
++info->match_count;
@@ -289,6 +301,7 @@
break;
case eDataTypeContainsData:
+ // Check if the current malloc block contains data specified in "info->data"
{
const uint32_t size = info->data.size;
if (size < ptr_size) // Make sure this block can contain this data
@@ -318,6 +331,82 @@
}
}
break;
+
+ case eDataTypeObjC:
+ // 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)
+ {
+ struct objc_class *objc_object_ptr = NULL;
+ if (task_peek (task, ptr_addr, sizeof(void *), (void **)&objc_object_ptr) == KERN_SUCCESS)
+ {
+ const uint64_t isa_bits = (uintptr_t)objc_object_ptr->isa;
+ //printf ("objc: addr = 0x%16.16llx, size = %6llu, isa = 0x%16.16llx", ptr_addr, ptr_size, isa_bits);
+ Dl_info dl_info;
+
+ if (isa_bits == 0 || isa_bits % sizeof(void*))
+ {
+ //printf (" error: invalid pointer\n");
+ return;
+ }
+ if (dladdr(objc_object_ptr->isa, &dl_info) == 0)
+ {
+ //printf (" error: symbol lookup failed\n");
+ return;
+ }
+ if (dl_info.dli_sname == NULL)
+ {
+ //printf (" error: no symbol name\n");
+ return;
+ }
+
+ if ((dl_info.dli_sname[0] == 'O' && strncmp("OBJC_CLASS_$_" , dl_info.dli_sname, 13) == 0) ||
+ (dl_info.dli_sname[0] == '.' && strncmp(".objc_class_name_", dl_info.dli_sname, 17) == 0))
+ {
+ bool match = false;
+ if (info->objc.match_isa == 0)
+ {
+ // Match any objective C object
+ match = true;
+ }
+ else
+ {
+ // Only match exact isa values in the current class or
+ // optionally in the super classes
+ if (info->objc.match_isa == objc_object_ptr->isa)
+ match = true;
+ else if (info->objc.match_superclasses)
+ {
+ Class super = class_getSuperclass(objc_object_ptr->isa);
+ while (super)
+ {
+ match = super == info->objc.match_isa;
+ if (match)
+ break;
+ super = class_getSuperclass(super);
+ }
+ }
+ }
+ if (match)
+ {
+ //printf (" success\n");
+ ++info->match_count;
+ malloc_match match = { (void *)ptr_addr, ptr_size, 0 };
+ g_matches.push_back(match);
+ }
+ else
+ {
+ //printf (" error: wrong class: %s\n", dl_info.dli_sname);
+ }
+ }
+ else
+ {
+ //printf ("\terror: symbol not objc class: %s\n", dl_info.dli_sname);
+ return;
+ }
+ }
+ }
+ break;
}
}
@@ -399,7 +488,6 @@
{
range_contains_data_callback_info_t data_info;
data_info.type = eDataTypeContainsData; // Check each block for data
- g_lookup_addr = addr;
data_info.data.buffer = (uint8_t *)&addr; // What data? The pointer value passed in
data_info.data.size = sizeof(addr); // How many bytes? The byte size of a pointer
data_info.data.align = sizeof(addr); // Align to a pointer byte size
@@ -429,7 +517,6 @@
// that is the a pointer
range_contains_data_callback_info_t data_info;
data_info.type = eDataTypeContainsData; // Check each block for data
- g_lookup_addr = addr;
data_info.data.buffer = (uint8_t *)&addr; // What data? The pointer value passed in
data_info.data.size = sizeof(addr); // How many bytes? The byte size of a pointer
data_info.data.align = sizeof(addr); // Align to a pointer byte size
@@ -444,6 +531,34 @@
}
//----------------------------------------------------------------------
+// find_objc_objects_in_memory
+//
+// Find all instances of ObjC classes 'c', or all ObjC classes if 'c' is
+// NULL. If 'c' is non NULL, then also check objects to see if they
+// inherit from 'c'
+//----------------------------------------------------------------------
+malloc_match *
+find_objc_objects_in_memory (void *isa)
+{
+ g_matches.clear();
+ // 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 = eDataTypeObjC; // Check each block for data
+ data_info.objc.match_isa = (Class)isa;
+ data_info.objc.match_superclasses = true;
+ 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);
+ if (g_matches.empty())
+ return NULL;
+ malloc_match match = { NULL, 0, 0 };
+ g_matches.push_back(match);
+ return g_matches.data();
+}
+
+//----------------------------------------------------------------------
// find_cstring_in_heap
//
// Finds a C string inside one or more currently valid malloc blocks.
@@ -461,7 +576,6 @@
// that is the C string passed in aligned on a 1 byte boundary
range_contains_data_callback_info_t data_info;
data_info.type = eDataTypeContainsData; // Check each block for data
- g_lookup_addr = s; // If an expression was used, then fill in the resolved address we are looking up
data_info.data.buffer = (uint8_t *)s; // What data? The C string passed in
data_info.data.size = strlen(s); // How many bytes? The length of the C string
data_info.data.align = 1; // Data doesn't need to be aligned, so set the alignment to 1
@@ -488,7 +602,6 @@
// Setup "info" to look for a malloc block that contains data
// that is the C string passed in aligned on a 1 byte boundary
range_contains_data_callback_info_t data_info;
- g_lookup_addr = addr; // If an expression was used, then fill in the resolved address we are looking up
data_info.type = eDataTypeAddress; // Check each block to see if the block contains the address passed in
data_info.addr = (uintptr_t)addr; // What data? The C string passed in
data_info.match_count = 0; // Initialize the match count to zero
More information about the lldb-commits
mailing list