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