15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#!/usr/bin/python
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#----------------------------------------------------------------------
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Be sure to add the python path that points to the LLDB shared library.
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# On MacOSX csh, tcsh:
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# On MacOSX sh, bash:
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#   export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#----------------------------------------------------------------------
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import commands
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import optparse
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import os
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import platform
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import re
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import resource
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import sys
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import time
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)import types
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#----------------------------------------------------------------------
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Code that auto imports LLDB
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#----------------------------------------------------------------------
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)try:
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # Just try for LLDB in case PYTHONPATH is already correctly setup
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    import lldb
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)except ImportError:
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lldb_python_dirs = list()
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # lldb is not in the PYTHONPATH, try some defaults for the current platform
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    platform_system = platform.system()
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if platform_system == 'Darwin':
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # On Darwin, try the currently selected Xcode directory
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        xcode_dir = commands.getoutput("xcode-select --print-path")
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if xcode_dir:
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            lldb_python_dirs.append(os.path.realpath(xcode_dir + '/../SharedFrameworks/LLDB.framework/Resources/Python'))
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            lldb_python_dirs.append(xcode_dir + '/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        lldb_python_dirs.append('/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python')
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    success = False
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    for lldb_python_dir in lldb_python_dirs:
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if os.path.exists(lldb_python_dir):
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not (sys.path.__contains__(lldb_python_dir)):
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                sys.path.append(lldb_python_dir)
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                try:
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    import lldb
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                except ImportError:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    pass
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    print 'imported lldb from: "%s"' % (lldb_python_dir)
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    success = True
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    break
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if not success:
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        sys.exit(1)
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Timer:
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __enter__(self):
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.start = time.clock()
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return self
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __exit__(self, *args):
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.end = time.clock()
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.interval = self.end - self.start
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Action(object):
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Class that encapsulates actions to take when a thread stops for a reason."""
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, callback = None, callback_owner = None):
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.callback = callback
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.callback_owner = callback_owner
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ThreadStopped (self, thread):
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert False, "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass"
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class PlanCompleteAction (Action):
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, callback = None, callback_owner = None):
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Action.__init__(self, callback, callback_owner)
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ThreadStopped (self, thread):
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if thread.GetStopReason() == lldb.eStopReasonPlanComplete:
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if self.callback:
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if self.callback_owner:
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.callback (self.callback_owner, thread)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.callback (thread)
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            return True
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return False
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class BreakpointAction (Action):
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, callback = None, callback_owner = None, name = None, module = None, file = None, line = None, breakpoint = None):
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Action.__init__(self, callback, callback_owner)
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.modules = lldb.SBFileSpecList()
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.files = lldb.SBFileSpecList()
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.breakpoints = list()
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        # "module" can be a list or a string
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if breakpoint:
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.breakpoints.append(breakpoint)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if module:
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if isinstance(module, types.ListType):
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    for module_path in module:
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.modules.Append(lldb.SBFileSpec(module_path, False))
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif isinstance(module, types.StringTypes):
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    self.modules.Append(lldb.SBFileSpec(module, False))
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if name:
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                # "file" can be a list or a string
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if file:
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if isinstance(file, types.ListType):
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.files = lldb.SBFileSpecList()
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        for f in file:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.files.Append(lldb.SBFileSpec(f, False))
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    elif isinstance(file, types.StringTypes):
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.files.Append(lldb.SBFileSpec(file, False))
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.breakpoints.append (self.target.BreakpointCreateByName(name, self.modules, self.files))
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            elif file and line:
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.breakpoints.append (self.target.BreakpointCreateByLocation(file, line))
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def ThreadStopped (self, thread):
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if thread.GetStopReason() == lldb.eStopReasonBreakpoint:
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            for bp in self.breakpoints:
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if bp.GetID() == thread.GetStopReasonDataAtIndex(0):
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if self.callback:
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if self.callback_owner:
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.callback (self.callback_owner, thread)
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        else:
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            self.callback (thread)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    return True
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return False
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TestCase:
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    """Class that aids in running performance tests."""
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self):
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.verbose = False
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.debugger = lldb.SBDebugger.Create()
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.target = None
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.process = None
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.thread = None
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.launch_info = None
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.done = False
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.listener = self.debugger.GetListener()
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.user_actions = list()
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.builtin_actions = list()
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.bp_id_to_dict = dict()
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def Setup(self, args):
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.launch_info = lldb.SBLaunchInfo(args)
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def Run (self, args):
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert False, "performance.TestCase.Run(self, args) must be subclassed"
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def Launch(self):
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.target:
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            error = lldb.SBError()
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.process = self.target.Launch (self.launch_info, error)
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if not error.Success():
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                print "error: %s" % error.GetCString()
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if self.process:
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.process.GetBroadcaster().AddListener(self.listener, lldb.SBProcess.eBroadcastBitStateChanged | lldb.SBProcess.eBroadcastBitInterrupt)
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                return True
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return False
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def WaitForNextProcessEvent (self):
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        event = None
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.process:
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            while event is None:
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                process_event = lldb.SBEvent()
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if self.listener.WaitForEvent (lldb.UINT32_MAX, process_event):
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    state = lldb.SBProcess.GetStateFromEvent (process_event)
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if self.verbose:
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        print "event = %s" % (lldb.SBDebugger.StateAsCString(state))
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if lldb.SBProcess.GetRestartedFromEvent(process_event):
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        continue
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    if state == lldb.eStateInvalid or state == lldb.eStateDetached or state == lldb.eStateCrashed or  state == lldb.eStateUnloaded or state == lldb.eStateExited:
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        event = process_event
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.done = True
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    elif state == lldb.eStateConnected or state == lldb.eStateAttaching or state == lldb.eStateLaunching or state == lldb.eStateRunning or state == lldb.eStateStepping or state == lldb.eStateSuspended:
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        continue
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    elif state == lldb.eStateStopped:
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        event = process_event
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        call_test_step = True
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        fatal = False
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        selected_thread = False
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        for thread in self.process:
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            frame = thread.GetFrameAtIndex(0)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            select_thread = False
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            stop_reason = thread.GetStopReason()
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            if self.verbose:
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                print "tid = %#x pc = %#x " % (thread.GetThreadID(),frame.GetPC()),
1865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            if stop_reason == lldb.eStopReasonNone:
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "none"
1895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonTrace:
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                select_thread = True
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "trace"
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonPlanComplete:
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                select_thread = True
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "plan complete"
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonThreadExiting:
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "thread exiting"
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonExec:
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "exec"
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonInvalid:
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "invalid"
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonException:
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                select_thread = True
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "exception"
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                fatal = True
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonBreakpoint:
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                select_thread = True
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bp_id = thread.GetStopReasonDataAtIndex(0)
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                bp_loc_id = thread.GetStopReasonDataAtIndex(1)
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "breakpoint id = %d.%d" % (bp_id, bp_loc_id)
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonWatchpoint:
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                select_thread = True
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "watchpoint id = %d" % (thread.GetStopReasonDataAtIndex(0))
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            elif stop_reason == lldb.eStopReasonSignal:
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                select_thread = True
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                if self.verbose:
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                    print "signal %d" % (thread.GetStopReasonDataAtIndex(0))
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            if select_thread and not selected_thread:
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                self.thread = thread
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                selected_thread = self.process.SetSelectedThread(thread)
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            for action in self.user_actions:
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                                action.ThreadStopped (thread)
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        if fatal:
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            # if self.verbose:
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            #     Xcode.RunCommand(self.debugger,"bt all",true)
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                            sys.exit(1)
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return event
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class Measurement:
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    '''A class that encapsulates a measurement'''
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self):
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        object.__init__(self)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def Measure(self):
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        assert False, "performance.Measurement.Measure() must be subclassed"
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class MemoryMeasurement(Measurement):
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    '''A class that can measure memory statistics for a process.'''
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self, pid):
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Measurement.__init__(self)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.pid = pid
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.stats = ["rprvt","rshrd","rsize","vsize","vprvt","kprvt","kshrd","faults","cow","pageins"]
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.command = "top -l 1 -pid %u -stats %s" % (self.pid, ",".join(self.stats))
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.value = dict()
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def Measure(self):
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        output = commands.getoutput(self.command).split("\n")[-1]
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        values = re.split('[-+\s]+', output)
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for (idx, stat) in enumerate(values):
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            multiplier = 1
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if stat:
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if stat[-1] == 'K':
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    multiplier = 1024
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    stat = stat[:-1]
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif stat[-1] == 'M':
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    multiplier = 1024*1024
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    stat = stat[:-1]
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif stat[-1] == 'G':
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    multiplier = 1024*1024*1024
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                elif stat[-1] == 'T':
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    multiplier = 1024*1024*1024*1024
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    stat = stat[:-1]
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.value[self.stats[idx]] = int (stat) * multiplier
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __str__(self):
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        '''Dump the MemoryMeasurement current value'''
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s = ''
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        for key in self.value.keys():
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if s:
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                s += "\n"
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            s += "%8s = %s" % (key, self.value[key])
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return s
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class TesterTestCase(TestCase):
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def __init__(self):
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        TestCase.__init__(self)
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.verbose = True
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.num_steps = 5
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def BreakpointHit (self, thread):
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        bp_id = thread.GetStopReasonDataAtIndex(0)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        loc_id = thread.GetStopReasonDataAtIndex(1)
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print "Breakpoint %i.%i hit: %s" % (bp_id, loc_id, thread.process.target.FindBreakpointByID(bp_id))
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        thread.StepOver()
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def PlanComplete (self, thread):
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        if self.num_steps > 0:
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            thread.StepOver()
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.num_steps = self.num_steps - 1
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        else:
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            thread.process.Kill()
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    def Run (self, args):
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        self.Setup(args)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        with Timer() as total_time:
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            self.target = self.debugger.CreateTarget(args[0])
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            if self.target:
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                with Timer() as breakpoint_timer:
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    bp = self.target.BreakpointCreateByName("main")
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                print('Breakpoint time = %.03f sec.' % breakpoint_timer.interval)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.user_actions.append (BreakpointAction(breakpoint=bp, callback=TesterTestCase.BreakpointHit, callback_owner=self))
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                self.user_actions.append (PlanCompleteAction(callback=TesterTestCase.PlanComplete, callback_owner=self))
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                if self.Launch():
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    while not self.done:
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                        self.WaitForNextProcessEvent()
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                else:
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                    print "error: failed to launch process"
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            else:
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                print "error: failed to create target with '%s'" % (args[0])
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        print('Total time = %.03f sec.' % total_time.interval)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)if __name__ == '__main__':
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lldb.SBDebugger.Initialize()
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test = TesterTestCase()
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    test.Run (sys.argv[1:])
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem = MemoryMeasurement(os.getpid())
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    mem.Measure()
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    print str(mem)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    lldb.SBDebugger.Terminate()
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # print "sleeeping for 100 seconds"
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    # time.sleep(100)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)