3 # ----------------------------------------------------------------------
4 # Be sure to add the python path that points to the LLDB shared library.
6 # setenv PYTHONPATH /Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
8 # export PYTHONPATH=/Applications/Xcode.app/Contents/SharedFrameworks/LLDB.framework/Resources/Python
9 # ----------------------------------------------------------------------
21 # ----------------------------------------------------------------------
22 # Code that auto imports LLDB
23 # ----------------------------------------------------------------------
25 # Just try for LLDB in case PYTHONPATH is already correctly setup
28 lldb_python_dirs
= list()
29 # lldb is not in the PYTHONPATH, try some defaults for the current platform
30 platform_system
= platform
.system()
31 if platform_system
== "Darwin":
32 # On Darwin, try the currently selected Xcode directory
33 xcode_dir
= subprocess
.check_output("xcode-select --print-path", shell
=True)
35 lldb_python_dirs
.append(
37 xcode_dir
+ "/../SharedFrameworks/LLDB.framework/Resources/Python"
40 lldb_python_dirs
.append(
41 xcode_dir
+ "/Library/PrivateFrameworks/LLDB.framework/Resources/Python"
43 lldb_python_dirs
.append(
44 "/System/Library/PrivateFrameworks/LLDB.framework/Resources/Python"
47 for lldb_python_dir
in lldb_python_dirs
:
48 if os
.path
.exists(lldb_python_dir
):
49 if not (sys
.path
.__contains
__(lldb_python_dir
)):
50 sys
.path
.append(lldb_python_dir
)
56 print('imported lldb from: "%s"' % (lldb_python_dir
))
61 "error: couldn't locate the 'lldb' module, please set PYTHONPATH correctly"
68 self
.start
= time
.clock()
71 def __exit__(self
, *args
):
72 self
.end
= time
.clock()
73 self
.interval
= self
.end
- self
.start
77 """Class that encapsulates actions to take when a thread stops for a reason."""
79 def __init__(self
, callback
=None, callback_owner
=None):
80 self
.callback
= callback
81 self
.callback_owner
= callback_owner
83 def ThreadStopped(self
, thread
):
86 ), "performance.Action.ThreadStopped(self, thread) must be overridden in a subclass"
89 class PlanCompleteAction(Action
):
90 def __init__(self
, callback
=None, callback_owner
=None):
91 Action
.__init
__(self
, callback
, callback_owner
)
93 def ThreadStopped(self
, thread
):
94 if thread
.GetStopReason() == lldb
.eStopReasonPlanComplete
:
96 if self
.callback_owner
:
97 self
.callback(self
.callback_owner
, thread
)
104 class BreakpointAction(Action
):
115 Action
.__init
__(self
, callback
, callback_owner
)
116 self
.modules
= lldb
.SBFileSpecList()
117 self
.files
= lldb
.SBFileSpecList()
118 self
.breakpoints
= list()
119 # "module" can be a list or a string
121 self
.breakpoints
.append(breakpoint
)
124 if isinstance(module
, types
.ListType
):
125 for module_path
in module
:
126 self
.modules
.Append(lldb
.SBFileSpec(module_path
, False))
127 elif isinstance(module
, types
.StringTypes
):
128 self
.modules
.Append(lldb
.SBFileSpec(module
, False))
130 # "file" can be a list or a string
132 if isinstance(file, types
.ListType
):
133 self
.files
= lldb
.SBFileSpecList()
135 self
.files
.Append(lldb
.SBFileSpec(f
, False))
136 elif isinstance(file, types
.StringTypes
):
137 self
.files
.Append(lldb
.SBFileSpec(file, False))
138 self
.breakpoints
.append(
139 self
.target
.BreakpointCreateByName(name
, self
.modules
, self
.files
)
142 self
.breakpoints
.append(
143 self
.target
.BreakpointCreateByLocation(file, line
)
146 def ThreadStopped(self
, thread
):
147 if thread
.GetStopReason() == lldb
.eStopReasonBreakpoint
:
148 for bp
in self
.breakpoints
:
149 if bp
.GetID() == thread
.GetStopReasonDataAtIndex(0):
151 if self
.callback_owner
:
152 self
.callback(self
.callback_owner
, thread
)
154 self
.callback(thread
)
160 """Class that aids in running performance tests."""
164 self
.debugger
= lldb
.SBDebugger
.Create()
168 self
.launch_info
= None
170 self
.listener
= self
.debugger
.GetListener()
171 self
.user_actions
= list()
172 self
.builtin_actions
= list()
173 self
.bp_id_to_dict
= dict()
175 def Setup(self
, args
):
176 self
.launch_info
= lldb
.SBLaunchInfo(args
)
179 assert False, "performance.TestCase.Run(self, args) must be subclassed"
183 error
= lldb
.SBError()
184 self
.process
= self
.target
.Launch(self
.launch_info
, error
)
185 if not error
.Success():
186 print("error: %s" % error
.GetCString())
188 self
.process
.GetBroadcaster().AddListener(
190 lldb
.SBProcess
.eBroadcastBitStateChanged
191 | lldb
.SBProcess
.eBroadcastBitInterrupt
,
196 def WaitForNextProcessEvent(self
):
200 process_event
= lldb
.SBEvent()
201 if self
.listener
.WaitForEvent(lldb
.UINT32_MAX
, process_event
):
202 state
= lldb
.SBProcess
.GetStateFromEvent(process_event
)
204 print("event = %s" % (lldb
.SBDebugger
.StateAsCString(state
)))
205 if lldb
.SBProcess
.GetRestartedFromEvent(process_event
):
208 state
== lldb
.eStateInvalid
209 or state
== lldb
.eStateDetached
210 or state
== lldb
.eStateCrashed
211 or state
== lldb
.eStateUnloaded
212 or state
== lldb
.eStateExited
214 event
= process_event
217 state
== lldb
.eStateConnected
218 or state
== lldb
.eStateAttaching
219 or state
== lldb
.eStateLaunching
220 or state
== lldb
.eStateRunning
221 or state
== lldb
.eStateStepping
222 or state
== lldb
.eStateSuspended
225 elif state
== lldb
.eStateStopped
:
226 event
= process_event
227 call_test_step
= True
229 selected_thread
= False
230 for thread
in self
.process
:
231 frame
= thread
.GetFrameAtIndex(0)
232 select_thread
= False
234 stop_reason
= thread
.GetStopReason()
237 "tid = %#x pc = %#x "
238 % (thread
.GetThreadID(), frame
.GetPC()),
241 if stop_reason
== lldb
.eStopReasonNone
:
244 elif stop_reason
== lldb
.eStopReasonTrace
:
248 elif stop_reason
== lldb
.eStopReasonPlanComplete
:
251 print("plan complete")
252 elif stop_reason
== lldb
.eStopReasonThreadExiting
:
254 print("thread exiting")
255 elif stop_reason
== lldb
.eStopReasonExec
:
258 elif stop_reason
== lldb
.eStopReasonInvalid
:
261 elif stop_reason
== lldb
.eStopReasonException
:
266 elif stop_reason
== lldb
.eStopReasonBreakpoint
:
268 bp_id
= thread
.GetStopReasonDataAtIndex(0)
269 bp_loc_id
= thread
.GetStopReasonDataAtIndex(1)
271 print("breakpoint id = %d.%d" % (bp_id
, bp_loc_id
))
272 elif stop_reason
== lldb
.eStopReasonWatchpoint
:
277 % (thread
.GetStopReasonDataAtIndex(0))
279 elif stop_reason
== lldb
.eStopReasonSignal
:
284 % (thread
.GetStopReasonDataAtIndex(0))
286 elif stop_reason
== lldb
.eStopReasonFork
:
290 % (thread
.GetStopReasonDataAtIndex(0))
292 elif stop_reason
== lldb
.eStopReasonVFork
:
296 % (thread
.GetStopReasonDataAtIndex(0))
298 elif stop_reason
== lldb
.eStopReasonVForkDone
:
302 if select_thread
and not selected_thread
:
304 selected_thread
= self
.process
.SetSelectedThread(thread
)
306 for action
in self
.user_actions
:
307 action
.ThreadStopped(thread
)
311 # Xcode.RunCommand(self.debugger,"bt all",true)
317 """A class that encapsulates a measurement"""
320 object.__init
__(self
)
323 assert False, "performance.Measurement.Measure() must be subclassed"
326 class MemoryMeasurement(Measurement
):
327 """A class that can measure memory statistics for a process."""
329 def __init__(self
, pid
):
330 Measurement
.__init
__(self
)
344 self
.command
= "top -l 1 -pid %u -stats %s" % (self
.pid
, ",".join(self
.stats
))
348 output
= subprocess
.getoutput(self
.command
).split("\n")[-1]
349 values
= re
.split("[-+\s]+", output
)
350 for idx
, stat
in enumerate(values
):
356 elif stat
[-1] == "M":
357 multiplier
= 1024 * 1024
359 elif stat
[-1] == "G":
360 multiplier
= 1024 * 1024 * 1024
361 elif stat
[-1] == "T":
362 multiplier
= 1024 * 1024 * 1024 * 1024
364 self
.value
[self
.stats
[idx
]] = int(stat
) * multiplier
367 """Dump the MemoryMeasurement current value"""
369 for key
in self
.value
.keys():
372 s
+= "%8s = %s" % (key
, self
.value
[key
])
376 class TesterTestCase(TestCase
):
378 TestCase
.__init
__(self
)
382 def BreakpointHit(self
, thread
):
383 bp_id
= thread
.GetStopReasonDataAtIndex(0)
384 loc_id
= thread
.GetStopReasonDataAtIndex(1)
386 "Breakpoint %i.%i hit: %s"
387 % (bp_id
, loc_id
, thread
.process
.target
.FindBreakpointByID(bp_id
))
391 def PlanComplete(self
, thread
):
392 if self
.num_steps
> 0:
394 self
.num_steps
= self
.num_steps
- 1
396 thread
.process
.Kill()
400 with
Timer() as total_time
:
401 self
.target
= self
.debugger
.CreateTarget(args
[0])
403 with
Timer() as breakpoint_timer
:
404 bp
= self
.target
.BreakpointCreateByName("main")
405 print("Breakpoint time = %.03f sec." % breakpoint_timer
.interval
)
407 self
.user_actions
.append(
410 callback
=TesterTestCase
.BreakpointHit
,
414 self
.user_actions
.append(
416 callback
=TesterTestCase
.PlanComplete
, callback_owner
=self
422 self
.WaitForNextProcessEvent()
424 print("error: failed to launch process")
426 print("error: failed to create target with '%s'" % (args
[0]))
427 print("Total time = %.03f sec." % total_time
.interval
)
430 if __name__
== "__main__":
431 lldb
.SBDebugger
.Initialize()
432 test
= TesterTestCase()
433 test
.Run(sys
.argv
[1:])
434 mem
= MemoryMeasurement(os
.getpid())
437 lldb
.SBDebugger
.Terminate()
438 # print "sleeeping for 100 seconds"