diff options
| -rw-r--r-- | lldb/examples/darwin/heap_find/heap.py | 47 | ||||
| -rw-r--r-- | lldb/examples/darwin/heap_find/heap/heap_find.cpp | 56 |
2 files changed, 101 insertions, 2 deletions
diff --git a/lldb/examples/darwin/heap_find/heap.py b/lldb/examples/darwin/heap_find/heap.py index 27f27811cc2..9f68497dd6b 100644 --- a/lldb/examples/darwin/heap_find/heap.py +++ b/lldb/examples/darwin/heap_find/heap.py @@ -79,7 +79,48 @@ def add_common_options(parser): parser.add_option('-m', '--memory', action='store_true', dest='memory', help='dump the memory for each matching block', default=False) parser.add_option('-f', '--format', type='string', dest='format', help='the format to use when dumping memory if --memory is specified', default=None) parser.add_option('-s', '--stack', action='store_true', dest='stack', help='gets the stack that allocated each malloc block if MallocStackLogging is enabled', default=False) - #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('-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) + +type_flag_strings = [ 'free', 'generic', 'alloc', 'dealloc' ]; + +def dump_stack_history_entry(stack_history_entry, idx): + if stack_history_entry.addr != 0: + symbolicator = lldb.utils.symbolication.Symbolicator() + symbolicator.target = lldb.target + global type_flag_strings + print 'stack_history_entry[%u]: addr = 0x%x, type=%s, arg=%u, frames=' % (idx, stack_history_entry.address, type_flag_strings[stack_history_entry.type_flags], stack_history_entry.argument) + frame_idx = 0 + pc = int(stack_history_entry.frames[frame_idx]) + while pc != 0: + if pc >= 0x1000: + frames = symbolicator.symbolicate(pc) + if frames: + for frame in frames: + print '[%3u] %s' % (frame_idx, frame) + frame_idx += 1 + else: + print '[%3u] 0x%x' % (frame_idx, pc) + frame_idx += 1 + frame_idx = frame_idx + 1 + pc = int(stack_history_entry.frames[frame_idx]) + else: + pc = 0 + +def dump_stack_history_entries(addr): + # malloc_stack_entry *get_stack_history_for_address (const void * addr) + + expr = 'get_stack_history_for_address((void *)%s)' % addr + expr_sbvalue = lldb.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 stack_history_entry.address: + dump_stack_history_entry(stack_history_entry, idx) + idx = idx + 1 + stack_history_entry = expr_value[idx] + def heap_search(options, arg_str): dylid_load_err = load_dylib() @@ -186,7 +227,9 @@ def heap_search(options, arg_str): memory_command = "memory read -f %s 0x%x 0x%x" % (memory_format, malloc_addr, malloc_addr + malloc_size) lldb.debugger.GetCommandInterpreter().HandleCommand(memory_command, cmd_result) print cmd_result.GetOutput() - if options.stack: + if options.stack_history: + dump_stack_history_entries(malloc_addr) + elif options.stack: symbolicator = lldb.utils.symbolication.Symbolicator() symbolicator.target = lldb.target expr_str = "g_stack_frames_count = sizeof(g_stack_frames)/sizeof(uint64_t); (int)__mach_stack_logging_get_frames((unsigned)mach_task_self(), 0x%xull, g_stack_frames, g_stack_frames_count, &g_stack_frames_count)" % (malloc_addr) diff --git a/lldb/examples/darwin/heap_find/heap/heap_find.cpp b/lldb/examples/darwin/heap_find/heap/heap_find.cpp index 85c3b7628bc..4432d5b830c 100644 --- a/lldb/examples/darwin/heap_find/heap/heap_find.cpp +++ b/lldb/examples/darwin/heap_find/heap/heap_find.cpp @@ -68,7 +68,9 @@ #include <ctype.h> #include <mach/mach.h> #include <malloc/malloc.h> +extern "C" { #include <stack_logging.h> +} #include <stdio.h> #include <stdlib.h> #include <vector> @@ -117,8 +119,18 @@ struct malloc_match intptr_t offset; }; +struct malloc_stack_entry +{ + void *address; + uint64_t argument; + uint32_t type_flags; + std::vector<mach_vm_address_t> frames; +}; + + 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]; uint32_t g_stack_frames_count = 0; @@ -242,6 +254,50 @@ range_info_callback (task_t task, void *baton, unsigned type, uint64_t ptr_addr, } } +static void +get_stack_for_address_enumerator(mach_stack_logging_record_t stack_record, void *task_ptr) +{ + uint32_t num_frames = 0; + kern_return_t err = __mach_stack_logging_frames_for_uniqued_stack (*(task_t *)task_ptr, + stack_record.stack_identifier, + g_stack_frames, + MAX_FRAMES, + &num_frames); + g_malloc_stack_history.resize(g_malloc_stack_history.size() + 1); + g_malloc_stack_history.back().addr = (void *)stack_record.address; + g_malloc_stack_history.back().type_flags = stack_record.type_flags; + g_malloc_stack_history.back().argument = stack_record.argument; + if (num_frames > 0) + g_malloc_stack_history.back().frames.assign(g_stack_frames, g_stack_frames + num_frames); + g_malloc_stack_history.back().frames.push_back(0); // Terminate the frames with zero +} + +malloc_stack_entry * +get_stack_history_for_address (const void * addr) +{ + // typedef struct { + // uint32_t type_flags; + // uint64_t stack_identifier; + // uint64_t argument; + // mach_vm_address_t address; + // } mach_stack_logging_record_t; + std::vector<malloc_stack_entry> empty; + g_malloc_stack_history.swap(empty); + task_t task = mach_task_self(); + kern_return_t err = __mach_stack_logging_enumerate_records (task, + (mach_vm_address_t)addr, + get_stack_for_address_enumerator, + &task); + // Append an empty entry + if (g_malloc_stack_history.empty()) + return NULL; + g_malloc_stack_history.resize(g_malloc_stack_history.size() + 1); + g_malloc_stack_history.back().addr = 0; + g_malloc_stack_history.back().type_flags = 0; + g_malloc_stack_history.back().argument = 0; + return g_malloc_stack_history.data(); +} + //---------------------------------------------------------------------- // find_pointer_in_heap // |

