From: Greg Clayton Date: Fri, 1 Feb 2013 00:47:49 +0000 (+0000) Subject: Allow the target to give out the size of the red zone for given ABIs. X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=13fbb991077f389d2b3cbb5f5673ad0d815af709;p=platform%2Fupstream%2Fllvm.git Allow the target to give out the size of the red zone for given ABIs. A bit of cleanup in the heap module. llvm-svn: 174129 --- diff --git a/lldb/examples/darwin/heap_find/heap.py b/lldb/examples/darwin/heap_find/heap.py index 2155683..c3bf76e 100644 --- a/lldb/examples/darwin/heap_find/heap.py +++ b/lldb/examples/darwin/heap_find/heap.py @@ -22,14 +22,93 @@ import lldb.utils.symbolication g_libheap_dylib_dir = None g_libheap_dylib_dict = dict() -def get_iterate_memory_expr(process, user_init_code, user_return_code): - return ''' +def get_iterate_memory_expr(options, process, user_init_code, user_return_code): + expr = ''' typedef unsigned natural_t; typedef uintptr_t vm_size_t; typedef uintptr_t vm_address_t; typedef natural_t task_t; typedef int kern_return_t; #define KERN_SUCCESS 0 +typedef void (*range_callback_t)(task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size); +'''; + if options.search_vm_regions: + expr += ''' +typedef int vm_prot_t; +typedef unsigned int vm_inherit_t; +typedef unsigned long long memory_object_offset_t; +typedef unsigned int boolean_t; +typedef int vm_behavior_t; +typedef uint32_t vm32_object_id_t; +typedef natural_t mach_msg_type_number_t; +typedef uint64_t mach_vm_address_t; +typedef uint64_t mach_vm_offset_t; +typedef uint64_t mach_vm_size_t; +typedef uint64_t vm_map_offset_t; +typedef uint64_t vm_map_address_t; +typedef uint64_t vm_map_size_t; +#define VM_PROT_NONE ((vm_prot_t) 0x00) +#define VM_PROT_READ ((vm_prot_t) 0x01) +#define VM_PROT_WRITE ((vm_prot_t) 0x02) +#define VM_PROT_EXECUTE ((vm_prot_t) 0x04) +typedef struct vm_region_submap_short_info_data_64_t { + vm_prot_t protection; + vm_prot_t max_protection; + vm_inherit_t inheritance; + memory_object_offset_t offset; // offset into object/map + unsigned int user_tag; // user tag on map entry + unsigned int ref_count; // obj/map mappers, etc + unsigned short shadow_depth; // only for obj + unsigned char external_pager; // only for obj + unsigned char share_mode; // see enumeration + boolean_t is_submap; // submap vs obj + vm_behavior_t behavior; // access behavior hint + vm32_object_id_t object_id; // obj/map name, not a handle + unsigned short user_wired_count; +} vm_region_submap_short_info_data_64_t; +#define VM_REGION_SUBMAP_SHORT_INFO_COUNT_64 ((mach_msg_type_number_t)(sizeof(vm_region_submap_short_info_data_64_t)/sizeof(int)))'''; + if user_init_code: + expr += user_init_code; + expr += ''' +task_t task = (task_t)mach_task_self(); +mach_vm_address_t vm_region_base_addr; +mach_vm_size_t vm_region_size; +natural_t vm_region_depth; +vm_region_submap_short_info_data_64_t vm_region_info; +kern_return_t err; +for (vm_region_base_addr = 0, vm_region_size = 1; vm_region_size != 0; vm_region_base_addr += vm_region_size) +{ + mach_msg_type_number_t vm_region_info_size = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64; + err = (kern_return_t)mach_vm_region_recurse (task, + &vm_region_base_addr, + &vm_region_size, + &vm_region_depth, + &vm_region_info, + &vm_region_info_size); + if (err) + break; + // Check all read + write regions. This will cover the thread stacks + // and any regions of memory like __DATA segments, that might contain + // data we are looking for + if (vm_region_info.protection & VM_PROT_WRITE && + vm_region_info.protection & VM_PROT_READ) + { + baton.callback (task, + &baton, + 64, + vm_region_base_addr, + vm_region_size); + } +}''' + else: + if options.search_stack: + expr += get_thread_stack_ranges_struct (process) + if options.search_segments: + expr += get_sections_ranges_struct (process) + if user_init_code: + expr += user_init_code + if options.search_heap: + expr += ''' #define MALLOC_PTR_IN_USE_RANGE_TYPE 1 typedef struct vm_range_t { vm_address_t address; @@ -37,7 +116,6 @@ typedef struct vm_range_t { } vm_range_t; typedef kern_return_t (*memory_reader_t)(task_t task, vm_address_t remote_address, vm_size_t size, void **local_memory); typedef void (*vm_range_recorder_t)(task_t task, void *baton, unsigned type, vm_range_t *range, unsigned size); -typedef void (*range_callback_t)(task_t task, void *baton, unsigned type, uintptr_t ptr_addr, uintptr_t ptr_size); typedef struct malloc_introspection_t { kern_return_t (*enumerator)(task_t task, void *, unsigned type_mask, vm_address_t zone_address, memory_reader_t reader, vm_range_recorder_t recorder); /* enumerates all the malloc pointers in use */ } malloc_introspection_t; @@ -50,11 +128,7 @@ memory_reader_t task_peek = [](task_t task, vm_address_t remote_address, vm_size return KERN_SUCCESS; }; vm_address_t *zones = 0; -unsigned int num_zones = 0; -%s -%s -%s -task_t task = 0; +unsigned int num_zones = 0;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) { @@ -76,14 +150,29 @@ if (KERN_SUCCESS == err) } }); } -} +}''' + + if options.search_stack: + expr += ''' // Call the callback for the thread stack ranges -for (uint32_t i=0; i 0) { + range_callback(task, &baton, 16, stacks[i].base - STACK_RED_ZONE_SIZE, STACK_RED_ZONE_SIZE); + } +} + ''' + + if options.search_segments: + expr += ''' // Call the callback for all segments for (uint32_t i=0; i 0: result = ''' #define NUM_STACKS %u +#define STACK_RED_ZONE_SIZE %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, process.target.GetStackRedZoneSize()) for stack_dict in stack_dicts: result += ''' stacks[%(index)u].tid = 0x%(tid)x; @@ -870,7 +996,8 @@ def objc_refs(debugger, command, result, dict): # 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. - user_init_code_format = '''#define MAX_MATCHES %u + user_init_code_format = ''' +#define MAX_MATCHES %u struct $malloc_match { void *addr; uintptr_t size; @@ -954,7 +1081,7 @@ int nc = (int)objc_getClassList(baton.classes, sizeof(baton.classes)/sizeof(Clas options.type = 'isa' 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) + expr = get_iterate_memory_expr(options, 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: diff --git a/lldb/include/lldb/API/SBTarget.h b/lldb/include/lldb/API/SBTarget.h index 2d8c4b9..3ea4b3e 100644 --- a/lldb/include/lldb/API/SBTarget.h +++ b/lldb/include/lldb/API/SBTarget.h @@ -765,6 +765,9 @@ public: lldb::SBValue EvaluateExpression (const char *expr, const SBExpressionOptions &options); + lldb::addr_t + GetStackRedZoneSize(); + protected: friend class SBAddress; friend class SBBlock; diff --git a/lldb/scripts/Python/interface/SBTarget.i b/lldb/scripts/Python/interface/SBTarget.i index 8d681e8..c4fe24b 100644 --- a/lldb/scripts/Python/interface/SBTarget.i +++ b/lldb/scripts/Python/interface/SBTarget.i @@ -712,6 +712,9 @@ public: bool GetDescription (lldb::SBStream &description, lldb::DescriptionLevel description_level); + lldb::addr_t + GetStackRedZoneSize(); + lldb::SBValue EvaluateExpression (const char *expr, const lldb::SBExpressionOptions &options); %pythoncode %{ diff --git a/lldb/source/API/SBTarget.cpp b/lldb/source/API/SBTarget.cpp index f4582da..115703e 100644 --- a/lldb/source/API/SBTarget.cpp +++ b/lldb/source/API/SBTarget.cpp @@ -2568,3 +2568,22 @@ SBTarget::EvaluateExpression (const char *expr, const SBExpressionOptions &optio return expr_result; } + +lldb::addr_t +SBTarget::GetStackRedZoneSize() +{ + TargetSP target_sp(GetSP()); + if (target_sp) + { + ABISP abi_sp; + ProcessSP process_sp (target_sp->GetProcessSP()); + if (process_sp) + abi_sp = process_sp->GetABI(); + else + abi_sp = ABI::FindPlugin(target_sp->GetArchitecture()); + if (abi_sp) + return abi_sp->GetRedZoneSize(); + } + return 0; +} +