1#!/usr/bin/env python 2from __future__ import print_function 3import lldb 4import optparse 5import shlex 6 7 8def stack_frames(debugger, command, result, dict): 9 command_args = shlex.split(command) 10 usage = "usage: %prog [options] <PATH> [PATH ...]" 11 description = '''This command will enumerate all stack frames, print the stack size for each, and print an aggregation of which functions have the largest stack frame sizes at the end.''' 12 parser = optparse.OptionParser( 13 description=description, prog='ls', usage=usage) 14 parser.add_option( 15 '-v', 16 '--verbose', 17 action='store_true', 18 dest='verbose', 19 help='display verbose debug info', 20 default=False) 21 try: 22 (options, args) = parser.parse_args(command_args) 23 except: 24 return 25 26 target = debugger.GetSelectedTarget() 27 process = target.GetProcess() 28 29 frame_info = {} 30 for thread in process: 31 last_frame = None 32 print("thread %u" % (thread.id)) 33 for frame in thread.frames: 34 if last_frame: 35 frame_size = 0 36 if frame.idx == 1: 37 if frame.fp == last_frame.fp: 38 # No frame one the first frame (might be right at the 39 # entry point) 40 first_frame_size = 0 41 frame_size = frame.fp - frame.sp 42 else: 43 # First frame that has a valid size 44 first_frame_size = last_frame.fp - last_frame.sp 45 print("<%#7x> %s" % (first_frame_size, last_frame)) 46 if first_frame_size: 47 name = last_frame.name 48 if name not in frame_info: 49 frame_info[name] = first_frame_size 50 else: 51 frame_info[name] += first_frame_size 52 else: 53 # Second or higher frame 54 frame_size = frame.fp - last_frame.fp 55 print("<%#7x> %s" % (frame_size, frame)) 56 if frame_size > 0: 57 name = frame.name 58 if name not in frame_info: 59 frame_info[name] = frame_size 60 else: 61 frame_info[name] += frame_size 62 last_frame = frame 63 print(frame_info) 64 65 66lldb.debugger.HandleCommand( 67 "command script add -f stacks.stack_frames stack_frames") 68print("A new command called 'stack_frames' was added, type 'stack_frames --help' for more information.") 69