| 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, args_data, dict): | |
| self.frame = thread_plan.GetThread().frames[0] | |
| self.target = thread_plan.GetThread().GetProcess().GetTarget() | |
| func_entry = args_data.GetValueForKey("variable_name") | |
| if not func_entry.IsValid(): | |
| print("Did not get a valid entry for variable_name") | |
| func_name = func_entry.GetStringValue(100) | |
| self.value = self.frame.FindVariable(func_name) | |
| if self.value.GetError().Fail(): | |
| print("Failed to get foo value: %s"%(self.value.GetError().GetCString())) | |
| else: | |
| print("'foo' value: %d"%(self.value.GetValueAsUnsigned())) | |
| 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) | |
| 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 |