
It is always doing work on behalf of another thread that presumably has the mutex, so if it is calling SB API's it should have free access to the mutex. This is the same decision as we made earlier with the process RunLock. Differential Revision: https://reviews.llvm.org/D68174 llvm-svn: 373280
73 lines
2.3 KiB
Python
73 lines
2.3 KiB
Python
import lldb
|
|
|
|
class StepWithChild:
|
|
def __init__(self, thread_plan):
|
|
self.thread_plan = thread_plan
|
|
self.child_thread_plan = self.queue_child_thread_plan()
|
|
|
|
def explains_stop(self, event):
|
|
return False
|
|
|
|
def should_stop(self, event):
|
|
if not self.child_thread_plan.IsPlanComplete():
|
|
return False
|
|
|
|
self.thread_plan.SetPlanComplete(True)
|
|
|
|
return True
|
|
|
|
def should_step(self):
|
|
return False
|
|
|
|
def queue_child_thread_plan(self):
|
|
return None
|
|
|
|
class StepOut(StepWithChild):
|
|
def __init__(self, thread_plan, dict):
|
|
StepWithChild.__init__(self, thread_plan)
|
|
|
|
def queue_child_thread_plan(self):
|
|
return self.thread_plan.QueueThreadPlanForStepOut(0)
|
|
|
|
class StepScripted(StepWithChild):
|
|
def __init__(self, thread_plan, dict):
|
|
StepWithChild.__init__(self, thread_plan)
|
|
|
|
def queue_child_thread_plan(self):
|
|
return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut")
|
|
|
|
# This plan does a step-over until a variable changes value.
|
|
class StepUntil(StepWithChild):
|
|
def __init__(self, thread_plan, dict):
|
|
self.frame = thread_plan.GetThread().frames[0]
|
|
self.target = thread_plan.GetThread().GetProcess().GetTarget()
|
|
self.value = self.frame.FindVariable("foo")
|
|
StepWithChild.__init__(self, thread_plan)
|
|
|
|
def queue_child_thread_plan(self):
|
|
le = self.frame.GetLineEntry()
|
|
start_addr = le.GetStartAddress()
|
|
start = start_addr.GetLoadAddress(self.target)
|
|
end = le.GetEndAddress().GetLoadAddress(self.target)
|
|
print("Stepping from 0x%x to 0x%x (0x%x)"%(start, end, end - start))
|
|
return self.thread_plan.QueueThreadPlanForStepOverRange(start_addr,
|
|
end - start)
|
|
|
|
def should_stop(self, event):
|
|
if not self.child_thread_plan.IsPlanComplete():
|
|
return False
|
|
|
|
# If we've stepped out of this frame, stop.
|
|
if not self.frame.IsValid():
|
|
return True
|
|
|
|
if not self.value.IsValid():
|
|
return True
|
|
|
|
print("Got next value: %d"%(self.value.GetValueAsUnsigned()))
|
|
if not self.value.GetValueDidChange():
|
|
self.child_thread_plan = self.queue_child_thread_plan()
|
|
return False
|
|
else:
|
|
return True
|