1import lldb 2 3class StepWithChild: 4 def __init__(self, thread_plan): 5 self.thread_plan = thread_plan 6 self.child_thread_plan = self.queue_child_thread_plan() 7 8 def explains_stop(self, event): 9 return False 10 11 def should_stop(self, event): 12 if not self.child_thread_plan.IsPlanComplete(): 13 return False 14 15 self.thread_plan.SetPlanComplete(True) 16 17 return True 18 19 def should_step(self): 20 return False 21 22 def queue_child_thread_plan(self): 23 return None 24 25class StepOut(StepWithChild): 26 def __init__(self, thread_plan, dict): 27 StepWithChild.__init__(self, thread_plan) 28 29 def queue_child_thread_plan(self): 30 return self.thread_plan.QueueThreadPlanForStepOut(0) 31 32class StepScripted(StepWithChild): 33 def __init__(self, thread_plan, dict): 34 StepWithChild.__init__(self, thread_plan) 35 36 def queue_child_thread_plan(self): 37 return self.thread_plan.QueueThreadPlanForStepScripted("Steps.StepOut") 38 39# This plan does a step-over until a variable changes value. 40class StepUntil(StepWithChild): 41 def __init__(self, thread_plan, args_data, dict): 42 self.frame = thread_plan.GetThread().frames[0] 43 self.target = thread_plan.GetThread().GetProcess().GetTarget() 44 func_entry = args_data.GetValueForKey("variable_name") 45 46 if not func_entry.IsValid(): 47 print("Did not get a valid entry for variable_name") 48 func_name = func_entry.GetStringValue(100) 49 50 self.value = self.frame.FindVariable(func_name) 51 if self.value.GetError().Fail(): 52 print("Failed to get foo value: %s"%(self.value.GetError().GetCString())) 53 else: 54 print("'foo' value: %d"%(self.value.GetValueAsUnsigned())) 55 56 StepWithChild.__init__(self, thread_plan) 57 58 59 def queue_child_thread_plan(self): 60 le = self.frame.GetLineEntry() 61 start_addr = le.GetStartAddress() 62 start = start_addr.GetLoadAddress(self.target) 63 end = le.GetEndAddress().GetLoadAddress(self.target) 64 return self.thread_plan.QueueThreadPlanForStepOverRange(start_addr, 65 end - start) 66 67 def should_stop(self, event): 68 if not self.child_thread_plan.IsPlanComplete(): 69 return False 70 71 # If we've stepped out of this frame, stop. 72 if not self.frame.IsValid(): 73 return True 74 75 if not self.value.IsValid(): 76 return True 77 78 print("Got next value: %d"%(self.value.GetValueAsUnsigned())) 79 if not self.value.GetValueDidChange(): 80 self.child_thread_plan = self.queue_child_thread_plan() 81 return False 82 else: 83 return True 84