[Lldb-commits] [lldb] r174045 - Added the ability to search segments for data. Currently __TEXT, __LINKEDIT and __PAGEZERO are excluded.
Greg Clayton
gclayton at apple.com
Wed Jan 30 22:38:10 PST 2013
Author: gclayton
Date: Thu Jan 31 00:38:09 2013
New Revision: 174045
URL: http://llvm.org/viewvc/llvm-project?rev=174045&view=rev
Log:
Added the ability to search segments for data. Currently __TEXT, __LINKEDIT and __PAGEZERO are excluded.
Added many more cleanups to the output.
Modified:
lldb/trunk/examples/darwin/heap_find/heap.py
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=174045&r1=174044&r2=174045&view=diff
==============================================================================
--- lldb/trunk/examples/darwin/heap_find/heap.py (original)
+++ lldb/trunk/examples/darwin/heap_find/heap.py Thu Jan 31 00:38:09 2013
@@ -22,7 +22,9 @@ import lldb.utils.symbolication
g_libheap_dylib_dir = None
g_libheap_dylib_dict = dict()
-g_iterate_malloc_blocks_expr = '''typedef unsigned natural_t;
+def get_iterate_memory_expr(process, user_init_code, user_return_code):
+ return '''
+typedef unsigned natural_t;
typedef uintptr_t vm_size_t;
typedef uintptr_t vm_address_t;
typedef natural_t task_t;
@@ -50,6 +52,8 @@ memory_reader_t task_peek = [](task_t ta
vm_address_t *zones = 0;
unsigned int num_zones = 0;
%s
+%s
+%s
task_t task = 0;
kern_return_t err = (kern_return_t)malloc_get_all_zones (task, task_peek, &zones, &num_zones);
if (KERN_SUCCESS == err)
@@ -73,64 +77,13 @@ if (KERN_SUCCESS == err)
});
}
}
-%s
-'''
-def load_dylib():
- target = lldb.debugger.GetSelectedTarget()
- if target:
- global g_libheap_dylib_dir
- global g_libheap_dylib_dict
- triple = target.triple
- if triple in g_libheap_dylib_dict:
- libheap_dylib_path = g_libheap_dylib_dict[triple]
- else:
- if not g_libheap_dylib_dir:
- g_libheap_dylib_dir = tempfile.gettempdir() + '/lldb-dylibs'
- triple_dir = g_libheap_dylib_dir + '/' + triple + '/' + __name__
- if not os.path.exists(triple_dir):
- os.makedirs(triple_dir)
- libheap_dylib_path = triple_dir + '/libheap.dylib'
- g_libheap_dylib_dict[triple] = libheap_dylib_path
- heap_code_directory = os.path.dirname(__file__) + '/heap'
- heap_source_file = heap_code_directory + '/heap_find.cpp'
- # Check if the dylib doesn't exist, or if "heap_find.cpp" is newer than the dylib
- if not os.path.exists(libheap_dylib_path) or os.stat(heap_source_file).st_mtime > os.stat(libheap_dylib_path).st_mtime:
- # Remake the dylib
- make_command = '(cd "%s" ; make EXE="%s" ARCH=%s)' % (heap_code_directory, libheap_dylib_path, string.split(triple, '-')[0])
- (make_exit_status, make_output) = commands.getstatusoutput(make_command)
- if make_exit_status != 0:
- return 'error: make failed: %s' % (make_output)
- if os.path.exists(libheap_dylib_path):
- libheap_dylib_spec = lldb.SBFileSpec(libheap_dylib_path)
- if target.FindModule(libheap_dylib_spec):
- return None # success, 'libheap.dylib' already loaded
- process = target.GetProcess()
- if process:
- state = process.state
- if state == lldb.eStateStopped:
- (libheap_dylib_path)
- error = lldb.SBError()
- image_idx = process.LoadImage(libheap_dylib_spec, error)
- if error.Success():
- return None
- else:
- if error:
- return 'error: %s' % error
- else:
- return 'error: "process load \'%s\'" failed' % libheap_dylib_spec
- else:
- return 'error: process is not stopped'
- else:
- return 'error: invalid process'
- else:
- return 'error: file does not exist "%s"' % libheap_dylib_path
- else:
- return 'error: invalid target'
-
- debugger.HandleCommand('process load "%s"' % libheap_dylib_path)
- if target.FindModule(libheap_dylib_spec):
- return None # success, 'libheap.dylib' already loaded
- return 'error: failed to load "%s"' % libheap_dylib_path
+// Call the callback for the thread stack ranges
+for (uint32_t i=0; i<NUM_STACKS; ++i)
+ range_callback(task, &baton, 8, stacks[i].base, stacks[i].size);
+// Call the callback for all segments
+for (uint32_t i=0; i<NUM_SEGMENTS; ++i)
+ range_callback(task, &baton, 16, segments[i].base, segments[i].size);
+%s''' % (get_thread_stack_ranges_struct (process), get_sections_ranges_struct(process), user_init_code, user_return_code)
def get_member_types_for_offset(value_type, offset, member_list):
member = value_type.GetFieldAtIndex(0)
@@ -187,7 +140,7 @@ def add_common_options(parser):
parser.add_option('-S', '--stack-history', action='store_true', dest='stack_history', help='gets the stack history for all allocations whose start address matches each malloc block if MallocStackLogging is enabled', default=False)
parser.add_option('-F', '--max-frames', type='int', dest='max_frames', help='the maximum number of stack frames to print when using the --stack or --stack-history options (default=128)', default=128)
parser.add_option('-H', '--max-history', type='int', dest='max_history', help='the maximum number of stack history backtraces to print for each allocation when using the --stack-history option (default=16)', default=16)
- parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=256)
+ parser.add_option('-M', '--max-matches', type='int', dest='max_matches', help='the maximum number of matches to print', default=32)
parser.add_option('-O', '--offset', type='int', dest='offset', help='the matching data must be at this offset', default=-1)
parser.add_option('-V', '--vm-regions', action='store_true', dest='check_vm_regions', help='Also check the VM regions', default=False)
@@ -202,19 +155,29 @@ def type_flags_to_string(type_flags):
type_str = 'generic'
elif type_flags & 8:
type_str = 'stack'
+ elif type_flags & 16:
+ type_str = 'segment'
else:
type_str = hex(type_flags)
return type_str
-def type_flags_to_description(type_flags, addr, ptr_addr, ptr_size):
+def type_flags_to_description(type_flags, ptr_addr, ptr_size, offset):
+ show_offset = False
if type_flags == 0 or type_flags & 4:
type_str = 'free(%#x)' % (ptr_addr,)
elif type_flags & 2 or type_flags & 1:
- type_str = 'malloc(%5u) -> %#x' % (ptr_size, ptr_addr)
+ type_str = 'malloc(%6u) -> %#x' % (ptr_size, ptr_addr)
+ show_offset = True
elif type_flags & 8:
- type_str = 'stack @ %#x' % (addr,)
- else:
- type_str = hex(type_flags)
+ type_str = 'stack'
+ elif type_flags & 16:
+ sb_addr = lldb.debugger.GetSelectedTarget().ResolveLoadAddress(ptr_addr + offset)
+ type_str = 'segment [%#x - %#x), %s + %u, %s' % (ptr_addr, ptr_addr + ptr_size, sb_addr.section.name, sb_addr.offset, sb_addr)
+ else:
+ type_str = '%#x' % (ptr_addr,)
+ show_offset = True
+ if show_offset and offset != 0:
+ type_str += ' + %-6u' % (offset,)
return type_str
def dump_stack_history_entry(options, result, stack_history_entry, idx):
@@ -249,26 +212,8 @@ def dump_stack_history_entry(options, re
def dump_stack_history_entries(options, result, addr, history):
# malloc_stack_entry *get_stack_history_for_address (const void * addr)
- expr = 'get_stack_history_for_address((void *)0x%x, %u)' % (addr, history)
- frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
- expr_sbvalue = frame.EvaluateExpression (expr)
- if expr_sbvalue.error.Success():
- if expr_sbvalue.unsigned:
- expr_value = lldb.value(expr_sbvalue)
- idx = 0;
- stack_history_entry = expr_value[idx]
- while int(stack_history_entry.address) != 0:
- dump_stack_history_entry(options, result, stack_history_entry, idx)
- idx = idx + 1
- stack_history_entry = expr_value[idx]
- else:
- result.AppendMessage('"%s" returned zero' % (expr))
- else:
- result.AppendMessage('error: expression failed "%s" => %s' % (expr, expr_sbvalue.error))
-
-def dump_stack_history_entries2(options, result, addr, history):
- # malloc_stack_entry *get_stack_history_for_address (const void * addr)
- single_expr = '''typedef int kern_return_t;
+ single_expr = '''
+typedef int kern_return_t;
#define MAX_FRAMES %u
typedef struct $malloc_stack_entry {
uint64_t address;
@@ -297,7 +242,8 @@ else
stack.frames[MAX_FRAMES-1] = 0;
stack''' % (options.max_frames, addr);
- history_expr = '''typedef int kern_return_t;
+ history_expr = '''
+typedef int kern_return_t;
typedef unsigned task_t;
#define MAX_FRAMES %u
#define MAX_HISTORY %u
@@ -413,17 +359,11 @@ def display_match_results (result, optio
match_addr = malloc_addr + offset
dynamic_value = match_entry.addr.sbvalue.GetDynamicValue(lldb.eDynamicCanRunTarget)
type_flags = int(match_entry.type)
- description = '%#16.16x: %s ' % (match_addr, type_flags_to_description(type_flags, match_addr, malloc_addr, malloc_size))
+ description = '%#16.16x: %s' % (match_addr, type_flags_to_description(type_flags, malloc_addr, malloc_size, offset))
if options.show_size:
- description += '<%5u> ' % (malloc_size)
+ description += ' <%5u>' % (malloc_size)
if options.show_range:
- if offset > 0:
- description += '[%#x - %#x) + %-6u ' % (malloc_addr, malloc_addr + malloc_size, offset)
- else:
- description += '[%#x - %#x)' % (malloc_addr, malloc_addr + malloc_size)
- else:
- if options.type != 'isa':
- description += ' + %-6u ' % (offset,)
+ description += ' [%#x - %#x)' % (malloc_addr, malloc_addr + malloc_size)
derefed_dynamic_value = None
if dynamic_value.type.name == 'void *':
if options.type == 'pointer' and malloc_size == 4096:
@@ -442,17 +382,18 @@ def display_match_results (result, optio
# ptr bytes next hotter page
# 4 bytes this page's depth in the list
# 4 bytes high-water mark
- description += 'AUTORELEASE! for pthread_t %#x' % (thread)
- else:
- description += 'malloc(%u)' % (malloc_size)
- else:
- description += 'malloc(%u)' % (malloc_size)
+ description += ' AUTORELEASE! for pthread_t %#x' % (thread)
+ # else:
+ # description += 'malloc(%u)' % (malloc_size)
+ # else:
+ # description += 'malloc(%u)' % (malloc_size)
else:
derefed_dynamic_value = dynamic_value.deref
if derefed_dynamic_value:
derefed_dynamic_type = derefed_dynamic_value.type
derefed_dynamic_type_size = derefed_dynamic_type.size
derefed_dynamic_type_name = derefed_dynamic_type.name
+ description += ' '
description += derefed_dynamic_type_name
if offset < derefed_dynamic_type_size:
member_list = list();
@@ -482,7 +423,7 @@ def display_match_results (result, optio
if description:
result_output += description
if options.print_type and derefed_dynamic_value:
- result_output += '%s' % (derefed_dynamic_value)
+ result_output += ' %s' % (derefed_dynamic_value)
if options.print_object_description and dynamic_value:
desc = dynamic_value.GetObjectDescription()
if desc:
@@ -500,9 +441,9 @@ def display_match_results (result, optio
lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result)
result.AppendMessage(cmd_result.GetOutput())
if options.stack_history:
- dump_stack_history_entries2(options, result, malloc_addr, 1)
+ dump_stack_history_entries(options, result, malloc_addr, 1)
elif options.stack:
- dump_stack_history_entries2(options, result, malloc_addr, 0)
+ dump_stack_history_entries(options, result, malloc_addr, 0)
return i
elif print_no_matches:
result.AppendMessage('no matches found for %s' % (arg_str_description))
@@ -510,44 +451,6 @@ def display_match_results (result, optio
result.AppendMessage(str(expr_sbvalue.error))
return 0
-def heap_search(result, options, arg_str):
- dylid_load_err = load_dylib()
- if dylid_load_err:
- 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, (int)%u)' % (arg_str, options.check_vm_regions)
- arg_str_description = 'malloc block containing pointer %s' % arg_str
- if options.format == None:
- options.format = "A" # 'A' is "address" format
- elif options.type == 'isa':
- expr = 'find_objc_objects_in_memory ((void *)%s, (int)%u)' % (arg_str, options.check_vm_regions)
- #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:
- options.format = "A" # 'A' is "address" format
- elif options.type == 'cstr':
- expr = 'find_cstring_in_heap("%s", (int)%u)' % (arg_str, options.check_vm_regions)
- arg_str_description = 'malloc block containing "%s"' % arg_str
- elif options.type == 'addr':
- expr = 'find_block_for_address((void *)%s, (int)%u)' % (arg_str, options.check_vm_regions)
- 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
- if options.format == None:
- options.format = "Y" # 'Y' is "bytes with ASCII" format
-
- display_match_results (result, options, arg_str_description, expr)
-
def get_ptr_refs_options ():
usage = "usage: %prog [options] <EXPR> [EXPR ...]"
description='''Searches all allocations on the heap for pointer values on
@@ -589,7 +492,8 @@ def ptr_refs(debugger, command, result,
# a member named "callback" whose type is "range_callback_t". This
# will be used by our zone callbacks to call the range callback for
# each malloc range.
- init_expr_format = '''
+ user_init_code_format = '''
+#define MAX_MATCHES %u
struct $malloc_match {
void *addr;
uintptr_t size;
@@ -599,7 +503,7 @@ struct $malloc_match {
typedef struct callback_baton_t {
range_callback_t callback;
unsigned num_matches;
- $malloc_match matches[%u];
+ $malloc_match matches[MAX_MATCHES];
void *ptr;
} callback_baton_t;
range_callback_t range_callback = [](task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size) -> void {
@@ -609,7 +513,7 @@ range_callback_t range_callback = [](tas
T *array = (T*)ptr_addr;
for (unsigned idx = 0; ((idx + 1) * sizeof(T)) <= ptr_size; ++idx) {
if (array[idx] == info->ptr) {
- if (info->num_matches < sizeof(info->matches)/sizeof($malloc_match)) {
+ if (info->num_matches < MAX_MATCHES) {
info->matches[info->num_matches].addr = (void*)ptr_addr;
info->matches[info->num_matches].size = ptr_size;
info->matches[info->num_matches].offset = idx*sizeof(T);
@@ -626,17 +530,13 @@ callback_baton_t baton = { range_callbac
# Here we return NULL if our pointer was not found in any malloc blocks,
# and we return the address of the matches array so we can then access
# the matching results
- return_expr = '''
-for (uint32_t i=0; i<NUM_STACKS; ++i)
- range_callback (task, &baton, 8, stacks[i].base, stacks[i].size);
+ user_return_code = '''if (baton.num_matches < MAX_MATCHES)
+ baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
baton.matches'''
# Iterate through all of our pointer expressions and display the results
for ptr_expr in args:
- init_expr = init_expr_format % (options.max_matches, ptr_expr)
- stack_info = get_thread_stack_ranges_struct (process)
- if stack_info:
- init_expr += stack_info
- expr = g_iterate_malloc_blocks_expr % (init_expr, return_expr)
+ user_init_code = user_init_code_format % (options.max_matches, ptr_expr)
+ expr = get_iterate_memory_expr(process, user_init_code, user_return_code)
arg_str_description = 'malloc block containing pointer %s' % ptr_expr
display_match_results (result, options, arg_str_description, expr)
else:
@@ -661,11 +561,16 @@ def cstr_refs(debugger, command, result,
except:
return
- frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
+ process = lldb.debugger.GetSelectedTarget().GetProcess()
+ if not process:
+ result.AppendMessage('error: invalid process')
+ return
+ frame = process.GetSelectedThread().GetSelectedFrame()
if not frame:
result.AppendMessage('error: invalid frame')
return
+
options.type = 'cstr'
if options.format == None:
options.format = "Y" # 'Y' is "bytes with ASCII" format
@@ -679,7 +584,9 @@ def cstr_refs(debugger, command, result,
# a member named "callback" whose type is "range_callback_t". This
# will be used by our zone callbacks to call the range callback for
# each malloc range.
- init_expr_format = '''struct $malloc_match {
+ user_init_code_format = '''
+#define MAX_MATCHES %u
+struct $malloc_match {
void *addr;
uintptr_t size;
uintptr_t offset;
@@ -688,7 +595,7 @@ def cstr_refs(debugger, command, result,
typedef struct callback_baton_t {
range_callback_t callback;
unsigned num_matches;
- $malloc_match matches[%u];
+ $malloc_match matches[MAX_MATCHES];
const char *cstr;
unsigned cstr_len;
} callback_baton_t;
@@ -699,7 +606,7 @@ range_callback_t range_callback = [](tas
const char *end = begin + ptr_size - info->cstr_len;
for (const char *s = begin; s < end; ++s) {
if ((int)memcmp(s, info->cstr, info->cstr_len) == 0) {
- if (info->num_matches < sizeof(info->matches)/sizeof($malloc_match)) {
+ if (info->num_matches < MAX_MATCHES) {
info->matches[info->num_matches].addr = (void*)ptr_addr;
info->matches[info->num_matches].size = ptr_size;
info->matches[info->num_matches].offset = s - begin;
@@ -717,11 +624,13 @@ callback_baton_t baton = { range_callbac
# Here we return NULL if our pointer was not found in any malloc blocks,
# and we return the address of the matches array so we can then access
# the matching results
- return_expr = '$malloc_match *result = baton.num_matches ? baton.matches : ($malloc_match *)0; result'
+ user_return_code = '''if (baton.num_matches < MAX_MATCHES)
+ baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
+baton.matches'''
# Iterate through all of our pointer expressions and display the results
for cstr in args:
- init_expr = init_expr_format % (options.max_matches, cstr)
- expr = g_iterate_malloc_blocks_expr % (init_expr, return_expr)
+ user_init_code = user_init_code_format % (options.max_matches, cstr)
+ expr = get_iterate_memory_expr(process, user_init_code, user_return_code)
arg_str_description = 'malloc block containing "%s"' % cstr
display_match_results (result, options, arg_str_description, expr)
else:
@@ -747,8 +656,18 @@ def malloc_info(debugger, command, resul
except:
return
options.type = 'addr'
+
+ process = lldb.debugger.GetSelectedTarget().GetProcess()
+ if not process:
+ result.AppendMessage('error: invalid process')
+ return
+ frame = process.GetSelectedThread().GetSelectedFrame()
+ if not frame:
+ result.AppendMessage('error: invalid frame')
+ return
- init_expr_format = '''struct $malloc_match {
+ user_init_code_format = '''
+struct $malloc_match {
void *addr;
uintptr_t size;
uintptr_t offset;
@@ -776,40 +695,21 @@ range_callback_t range_callback = [](tas
}
};
callback_baton_t baton = { range_callback, 0, {0}, (void *)%s };
+baton.matches[0].addr = 0;
baton.matches[1].addr = 0;'''
if args:
- frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
- if frame:
- for ptr_expr in args:
- init_expr = init_expr_format % (ptr_expr)
- expr = g_iterate_malloc_blocks_expr % (init_expr, 'baton.matches')
- arg_str_description = 'malloc block that contains %s' % ptr_expr
- display_match_results (result, options, arg_str_description, expr)
- else:
- result.AppendMessage('error: invalid frame')
+ for ptr_expr in args:
+ user_init_code = user_init_code_format % (ptr_expr)
+ expr = get_iterate_memory_expr(process, user_init_code, 'baton.matches')
+ arg_str_description = 'malloc block that contains %s' % ptr_expr
+ display_match_results (result, options, arg_str_description, expr)
else:
result.AppendMessage('error: command takes one or more pointer expressions')
-def heap(debugger, command, result, dict):
- command_args = shlex.split(command)
- usage = "usage: %prog [options] <EXPR> [EXPR ...]"
- description='''Traverse all allocations on the heap and report statistics.
-
- If programs set the MallocStackLogging=1 in the environment, then stack
- history is available for any allocations. '''
- parser = optparse.OptionParser(description=description, prog='heap',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:
- heap_search (result, options, None)
-
def get_thread_stack_ranges_struct (process):
+ '''Create code that defines a structure that represents threads stack bounds
+ for all threads. It returns a static sized array initialized with all of
+ the tid, base, size structs for all the threads.'''
stack_dicts = list()
if process:
i = 0;
@@ -825,70 +725,50 @@ def get_thread_stack_ranges_struct (proc
i += 1
stack_dicts_len = len(stack_dicts)
if stack_dicts_len > 0:
- result = '''#define NUM_STACKS %u
+ result = '''
+#define NUM_STACKS %u
typedef struct thread_stack_t { uint64_t tid, base, size; } thread_stack_t;
-thread_stack_t stacks[NUM_STACKS];
-''' % (stack_dicts_len,)
+thread_stack_t stacks[NUM_STACKS];''' % (stack_dicts_len,)
for stack_dict in stack_dicts:
- result += '''stacks[%(index)u].tid = 0x%(tid)x;
+ result += '''
+stacks[%(index)u].tid = 0x%(tid)x;
stacks[%(index)u].base = 0x%(base)x;
-stacks[%(index)u].size = 0x%(size)x;
-''' % stack_dict
+stacks[%(index)u].size = 0x%(size)x;''' % stack_dict
return result
else:
return None
-
-def stack_ptr_refs(debugger, command, result, dict):
- command_args = shlex.split(command)
- usage = "usage: %prog [options] <EXPR> [EXPR ...]"
- description='''Searches thread stack contents for pointer values in darwin user space programs.'''
- parser = optparse.OptionParser(description=description, prog='stack_ptr_refs',usage=usage)
- add_common_options(parser)
- try:
- (options, args) = parser.parse_args(command_args)
- except:
- return
- options.type = 'pointer'
-
- stack_threads = list()
- stack_bases = list()
- stack_sizes = list()
- process = lldb.debugger.GetSelectedTarget().GetProcess()
- for thread in process:
- min_sp = thread.frame[0].sp
- max_sp = min_sp
- for frame in thread.frames:
- sp = frame.sp
- if sp < min_sp: min_sp = sp
- if sp > max_sp: max_sp = sp
- result.AppendMessage ('%s stack [%#x - %#x)' % (thread, min_sp, max_sp))
- if min_sp < max_sp:
- stack_threads.append (thread)
- stack_bases.append (min_sp)
- stack_sizes.append (max_sp-min_sp)
-
- if stack_bases:
- dylid_load_err = load_dylib()
- if dylid_load_err:
- result.AppendMessage(dylid_load_err)
- return
- frame = process.GetSelectedThread().GetSelectedFrame()
- for expr_str in args:
- for (idx, stack_base) in enumerate(stack_bases):
- stack_size = stack_sizes[idx]
- expr = 'find_pointer_in_memory(0x%xllu, %ullu, (void *)%s)' % (stack_base, stack_size, expr_str)
- arg_str_description = 'thead %s stack containing "%s"' % (stack_threads[idx], expr_str)
- num_matches = display_match_results (result, options, arg_str_description, expr, False)
- if num_matches:
- if num_matches < options.max_matches:
- options.max_matches = options.max_matches - num_matches
- else:
- options.max_matches = 0
- if options.max_matches == 0:
- return
+def get_sections_ranges_struct (process):
+ '''Create code that defines a structure that represents all segments that
+ can contain data for all images in "target". It returns a static sized
+ array initialized with all of base, size structs for all the threads.'''
+ target = process.target
+ segment_dicts = list()
+ for (module_idx, module) in enumerate(target.modules):
+ for sect_idx in range(module.GetNumSections()):
+ section = module.GetSectionAtIndex(sect_idx)
+ if not section:
+ break
+ name = section.name
+ if name != '__TEXT' and name != '__LINKEDIT' and name != '__PAGEZERO':
+ base = section.GetLoadAddress(target)
+ size = section.GetByteSize()
+ if base != lldb.LLDB_INVALID_ADDRESS and size > 0:
+ segment_dicts.append ({ 'base' : base, 'size' : size })
+ segment_dicts_len = len(segment_dicts)
+ if segment_dicts_len > 0:
+ result = '''
+#define NUM_SEGMENTS %u
+typedef struct segment_range_t { uint64_t base; uint32_t size; } segment_range_t;
+segment_range_t segments[NUM_SEGMENTS];''' % (segment_dicts_len,)
+ for (idx, segment_dict) in enumerate(segment_dicts):
+ segment_dict['index'] = idx
+ result += '''
+segments[%(index)u].base = 0x%(base)x;
+segments[%(index)u].size = 0x%(size)x;''' % segment_dict
+ return result
else:
- result.AppendMessage('error: no thread stacks were found that match any of %s' % (', '.join(options.section_names)))
+ return None
def section_ptr_refs(debugger, command, result, dict):
command_args = shlex.split(command)
@@ -958,7 +838,11 @@ def objc_refs(debugger, command, result,
except:
return
- frame = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame()
+ process = lldb.debugger.GetSelectedTarget().GetProcess()
+ if not process:
+ result.AppendMessage('error: invalid process')
+ return
+ frame = process.GetSelectedThread().GetSelectedFrame()
if not frame:
result.AppendMessage('error: invalid frame')
return
@@ -986,7 +870,8 @@ def objc_refs(debugger, command, result,
# a member named "callback" whose type is "range_callback_t". This
# will be used by our zone callbacks to call the range callback for
# each malloc range.
- init_expr_format = '''struct $malloc_match {
+ user_init_code_format = '''#define MAX_MATCHES %u
+struct $malloc_match {
void *addr;
uintptr_t size;
uintptr_t offset;
@@ -997,7 +882,7 @@ typedef struct callback_baton_t {
range_callback_t callback;
compare_callback_t compare_callback;
unsigned num_matches;
- $malloc_match matches[%u];
+ $malloc_match matches[MAX_MATCHES];
void *isa;
Class classes[%u];
} callback_baton_t;
@@ -1037,7 +922,7 @@ range_callback_t range_callback = [](tas
else
match = true;
if (match) {
- if (info->num_matches < sizeof(info->matches)/sizeof($malloc_match)) {
+ if (info->num_matches < MAX_MATCHES) {
info->matches[info->num_matches].addr = (void*)ptr_addr;
info->matches[info->num_matches].size = ptr_size;
info->matches[info->num_matches].offset = 0;
@@ -1056,7 +941,9 @@ int nc = (int)objc_getClassList(baton.cl
# Here we return NULL if our pointer was not found in any malloc blocks,
# and we return the address of the matches array so we can then access
# the matching results
- return_expr = '$malloc_match *result = baton.num_matches ? baton.matches : ($malloc_match *)0; result'
+ user_return_code = '''if (baton.num_matches < MAX_MATCHES)
+ baton.matches[baton.num_matches].addr = 0; // Terminate the matches array
+ baton.matches'''
# Iterate through all of our ObjC class name arguments
for class_name in args:
addr_expr_str = "(void *)[%s class]" % class_name
@@ -1065,9 +952,9 @@ int nc = (int)objc_getClassList(baton.cl
isa = expr_sbvalue.unsigned
if isa:
options.type = 'isa'
- result.AppendMessage('Searching for all instances of classes or subclasses of %s (isa=0x%x)' % (class_name, isa))
- init_expr = init_expr_format % (options.max_matches, num_objc_classes, isa)
- expr = g_iterate_malloc_blocks_expr % (init_expr, return_expr)
+ result.AppendMessage('Searching for all instances of classes or subclasses of "%s" (isa=0x%x)' % (class_name, isa))
+ user_init_code = user_init_code_format % (options.max_matches, num_objc_classes, isa)
+ expr = get_iterate_memory_expr(process, user_init_code, user_return_code)
arg_str_description = 'objective C classes with isa 0x%x' % isa
display_match_results (result, options, arg_str_description, expr)
else:
More information about the lldb-commits
mailing list