brintos

brintos / llvm-project-archived public Read only

0
0
Text · 16.5 KiB · c3181b6 Raw
439 lines · python
1#!/usr/bin/env python2 3# ----------------------------------------------------------------------4# Be sure to add the python path that points to the LLDB shared library.5# On MacOSX csh, tcsh:6#   setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python7# On MacOSX sh, bash:8#   export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python9# ----------------------------------------------------------------------10 11import optparse12import os13import platform14import re15import resource16import sys17import subprocess18import time19 20# ----------------------------------------------------------------------21# Code that auto imports LLDB22# ----------------------------------------------------------------------23try:24    # Just try for LLDB in case PYTHONPATH is already correctly setup25    import lldb26except ImportError:27    lldb_python_dirs = list()28    # lldb is not in the PYTHONPATH, try some defaults for the current platform29    platform_system = platform.system()30    if platform_system == "Darwin":31        # On Darwin, try the currently selected Xcode directory32        xcode_dir = subprocess.check_output("xcode-select --print-path", shell=True)33        if xcode_dir:34            lldb_python_dirs.append(35                os.path.realpath(36                    xcode_dir + "/../SharedFrameworks/LLDB.framework/Resources/Python"37                )38            )39            lldb_python_dirs.append(40                xcode_dir + "/Library/PrivateFrameworks/LLDB.framework/Resources/Python"41            )42        lldb_python_dirs.append(43            "/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python"44        )45    success = False46    for lldb_python_dir in lldb_python_dirs:47        if os.path.exists(lldb_python_dir):48            if not (sys.path.__contains__(lldb_python_dir)):49                sys.path.append(lldb_python_dir)50                try:51                    import lldb52                except ImportError:53                    pass54                else:55                    print('imported lldb from: "%s"' % (lldb_python_dir))56                    success = True57                    break58    if not success:59        print(60            "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"61        )62        sys.exit(1)63 64 65class Timer:66    def __enter__(self):67        self.start = time.clock()68        return self69 70    def __exit__(self, *args):71        self.end = time.clock()72        self.interval = self.end - self.start73 74 75class Action(object):76    """Class that encapsulates actions to take when a thread stops for a reason."""77 78    def __init__(self, callback=None, callback_owner=None):79        self.callback = callback80        self.callback_owner = callback_owner81 82    def ThreadStopped(self, thread):83        assert (84            False85        ), "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass"86 87 88class PlanCompleteAction(Action):89    def __init__(self, callback=None, callback_owner=None):90        Action.__init__(self, callback, callback_owner)91 92    def ThreadStopped(self, thread):93        if thread.GetStopReason() == lldb.eStopReasonPlanComplete:94            if self.callback:95                if self.callback_owner:96                    self.callback(self.callback_owner, thread)97                else:98                    self.callback(thread)99            return True100        return False101 102 103class BreakpointAction(Action):104    def __init__(105        self,106        callback=None,107        callback_owner=None,108        name=None,109        module=None,110        file=None,111        line=None,112        breakpoint=None,113    ):114        Action.__init__(self, callback, callback_owner)115        self.modules = lldb.SBFileSpecList()116        self.files = lldb.SBFileSpecList()117        self.breakpoints = list()118        # "module" can be a list or a string119        if breakpoint:120            self.breakpoints.append(breakpoint)121        else:122            if module:123                if isinstance(module, list):124                    for module_path in module:125                        self.modules.Append(lldb.SBFileSpec(module_path, False))126                elif isinstance(module, str):127                    self.modules.Append(lldb.SBFileSpec(module, False))128            if name:129                # "file" can be a list or a string130                if file:131                    if isinstance(file, list):132                        self.files = lldb.SBFileSpecList()133                        for f in file:134                            self.files.Append(lldb.SBFileSpec(f, False))135                    elif isinstance(file, str):136                        self.files.Append(lldb.SBFileSpec(file, False))137                self.breakpoints.append(138                    self.target.BreakpointCreateByName(name, self.modules, self.files)139                )140            elif file and line:141                self.breakpoints.append(142                    self.target.BreakpointCreateByLocation(file, line)143                )144 145    def ThreadStopped(self, thread):146        if thread.GetStopReason() == lldb.eStopReasonBreakpoint:147            for bp in self.breakpoints:148                if bp.GetID() == thread.GetStopReasonDataAtIndex(0):149                    if self.callback:150                        if self.callback_owner:151                            self.callback(self.callback_owner, thread)152                        else:153                            self.callback(thread)154                    return True155        return False156 157 158class TestCase:159    """Class that aids in running performance tests."""160 161    def __init__(self):162        self.verbose = False163        self.debugger = lldb.SBDebugger.Create()164        self.target = None165        self.process = None166        self.thread = None167        self.launch_info = None168        self.done = False169        self.listener = self.debugger.GetListener()170        self.user_actions = list()171        self.builtin_actions = list()172        self.bp_id_to_dict = dict()173 174    def Setup(self, args):175        self.launch_info = lldb.SBLaunchInfo(args)176 177    def Run(self, args):178        assert False, "performance.TestCase.Run(self, args) must be subclassed"179 180    def Launch(self):181        if self.target:182            error = lldb.SBError()183            self.process = self.target.Launch(self.launch_info, error)184            if not error.Success():185                print("error: %s" % error.GetCString())186            if self.process:187                self.process.GetBroadcaster().AddListener(188                    self.listener,189                    lldb.SBProcess.eBroadcastBitStateChanged190                    | lldb.SBProcess.eBroadcastBitInterrupt,191                )192                return True193        return False194 195    def WaitForNextProcessEvent(self):196        event = None197        if self.process:198            while event is None:199                process_event = lldb.SBEvent()200                if self.listener.WaitForEvent(lldb.UINT32_MAX, process_event):201                    state = lldb.SBProcess.GetStateFromEvent(process_event)202                    if self.verbose:203                        print("event = %s" % (lldb.SBDebugger.StateAsCString(state)))204                    if lldb.SBProcess.GetRestartedFromEvent(process_event):205                        continue206                    if (207                        state == lldb.eStateInvalid208                        or state == lldb.eStateDetached209                        or state == lldb.eStateCrashed210                        or state == lldb.eStateUnloaded211                        or state == lldb.eStateExited212                    ):213                        event = process_event214                        self.done = True215                    elif (216                        state == lldb.eStateConnected217                        or state == lldb.eStateAttaching218                        or state == lldb.eStateLaunching219                        or state == lldb.eStateRunning220                        or state == lldb.eStateStepping221                        or state == lldb.eStateSuspended222                    ):223                        continue224                    elif state == lldb.eStateStopped:225                        event = process_event226                        call_test_step = True227                        fatal = False228                        selected_thread = False229                        for thread in self.process:230                            frame = thread.GetFrameAtIndex(0)231                            select_thread = False232 233                            stop_reason = thread.GetStopReason()234                            if self.verbose:235                                print(236                                    "tid = %#x pc = %#x "237                                    % (thread.GetThreadID(), frame.GetPC()),238                                    end=" ",239                                )240                            if stop_reason == lldb.eStopReasonNone:241                                if self.verbose:242                                    print("none")243                            elif stop_reason == lldb.eStopReasonTrace:244                                select_thread = True245                                if self.verbose:246                                    print("trace")247                            elif stop_reason == lldb.eStopReasonPlanComplete:248                                select_thread = True249                                if self.verbose:250                                    print("plan complete")251                            elif stop_reason == lldb.eStopReasonThreadExiting:252                                if self.verbose:253                                    print("thread exiting")254                            elif stop_reason == lldb.eStopReasonExec:255                                if self.verbose:256                                    print("exec")257                            elif stop_reason == lldb.eStopReasonInvalid:258                                if self.verbose:259                                    print("invalid")260                            elif stop_reason == lldb.eStopReasonException:261                                select_thread = True262                                if self.verbose:263                                    print("exception")264                                fatal = True265                            elif stop_reason == lldb.eStopReasonBreakpoint:266                                select_thread = True267                                bp_id = thread.GetStopReasonDataAtIndex(0)268                                bp_loc_id = thread.GetStopReasonDataAtIndex(1)269                                if self.verbose:270                                    print("breakpoint id = %d.%d" % (bp_id, bp_loc_id))271                            elif stop_reason == lldb.eStopReasonWatchpoint:272                                select_thread = True273                                if self.verbose:274                                    print(275                                        "watchpoint id = %d"276                                        % (thread.GetStopReasonDataAtIndex(0))277                                    )278                            elif stop_reason == lldb.eStopReasonSignal:279                                select_thread = True280                                if self.verbose:281                                    print(282                                        "signal %d"283                                        % (thread.GetStopReasonDataAtIndex(0))284                                    )285                            elif stop_reason == lldb.eStopReasonFork:286                                if self.verbose:287                                    print(288                                        "fork pid = %d"289                                        % (thread.GetStopReasonDataAtIndex(0))290                                    )291                            elif stop_reason == lldb.eStopReasonVFork:292                                if self.verbose:293                                    print(294                                        "vfork pid = %d"295                                        % (thread.GetStopReasonDataAtIndex(0))296                                    )297                            elif stop_reason == lldb.eStopReasonVForkDone:298                                if self.verbose:299                                    print("vfork done")300 301                            if select_thread and not selected_thread:302                                self.thread = thread303                                selected_thread = self.process.SetSelectedThread(thread)304 305                            for action in self.user_actions:306                                action.ThreadStopped(thread)307 308                        if fatal:309                            # if self.verbose:310                            #     Xcode.RunCommand(self.debugger,"bt all",true)311                            sys.exit(1)312        return event313 314 315class Measurement:316    """A class that encapsulates a measurement"""317 318    def __init__(self):319        object.__init__(self)320 321    def Measure(self):322        assert False, "performance.Measurement.Measure() must be subclassed"323 324 325class MemoryMeasurement(Measurement):326    """A class that can measure memory statistics for a process."""327 328    def __init__(self, pid):329        Measurement.__init__(self)330        self.pid = pid331        self.stats = [332            "rprvt",333            "rshrd",334            "rsize",335            "vsize",336            "vprvt",337            "kprvt",338            "kshrd",339            "faults",340            "cow",341            "pageins",342        ]343        self.command = "top -l 1 -pid %u -stats %s" % (self.pid, ",".join(self.stats))344        self.value = dict()345 346    def Measure(self):347        output = subprocess.getoutput(self.command).split("\n")[-1]348        values = re.split(r"[-+\s]+", output)349        for idx, stat in enumerate(values):350            multiplier = 1351            if stat:352                if stat[-1] == "K":353                    multiplier = 1024354                    stat = stat[:-1]355                elif stat[-1] == "M":356                    multiplier = 1024 * 1024357                    stat = stat[:-1]358                elif stat[-1] == "G":359                    multiplier = 1024 * 1024 * 1024360                elif stat[-1] == "T":361                    multiplier = 1024 * 1024 * 1024 * 1024362                    stat = stat[:-1]363                self.value[self.stats[idx]] = int(stat) * multiplier364 365    def __str__(self):366        """Dump the MemoryMeasurement current value"""367        s = ""368        for key in self.value.keys():369            if s:370                s += "\n"371            s += "%8s = %s" % (key, self.value[key])372        return s373 374 375class TesterTestCase(TestCase):376    def __init__(self):377        TestCase.__init__(self)378        self.verbose = True379        self.num_steps = 5380 381    def BreakpointHit(self, thread):382        bp_id = thread.GetStopReasonDataAtIndex(0)383        loc_id = thread.GetStopReasonDataAtIndex(1)384        print(385            "Breakpoint %i.%i hit: %s"386            % (bp_id, loc_id, thread.process.target.FindBreakpointByID(bp_id))387        )388        thread.StepOver()389 390    def PlanComplete(self, thread):391        if self.num_steps > 0:392            thread.StepOver()393            self.num_steps = self.num_steps - 1394        else:395            thread.process.Kill()396 397    def Run(self, args):398        self.Setup(args)399        with Timer() as total_time:400            self.target = self.debugger.CreateTarget(args[0])401            if self.target:402                with Timer() as breakpoint_timer:403                    bp = self.target.BreakpointCreateByName("main")404                print("Breakpoint time = %.03f sec." % breakpoint_timer.interval)405 406                self.user_actions.append(407                    BreakpointAction(408                        breakpoint=bp,409                        callback=TesterTestCase.BreakpointHit,410                        callback_owner=self,411                    )412                )413                self.user_actions.append(414                    PlanCompleteAction(415                        callback=TesterTestCase.PlanComplete, callback_owner=self416                    )417                )418 419                if self.Launch():420                    while not self.done:421                        self.WaitForNextProcessEvent()422                else:423                    print("error: failed to launch process")424            else:425                print("error: failed to create target with '%s'" % (args[0]))426        print("Total time = %.03f sec." % total_time.interval)427 428 429if __name__ == "__main__":430    lldb.SBDebugger.Initialize()431    test = TesterTestCase()432    test.Run(sys.argv[1:])433    mem = MemoryMeasurement(os.getpid())434    mem.Measure()435    print(str(mem))436    lldb.SBDebugger.Terminate()437    # print "sleeeping for 100 seconds"438    # time.sleep(100)439