| 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 stop_description(self, stream): | |
| if self.child_thread_plan.IsPlanComplete(): | |
| return self.child_thread_plan.GetDescription(stream) | |
| return True | |
| 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") | |
| class StepSingleInstruction(StepWithChild): | |
| def __init__(self, thread_plan, dict): | |
| super().__init__(thread_plan) | |
| def queue_child_thread_plan(self): | |
| return self.thread_plan.QueueThreadPlanForStepSingleInstruction( | |
| False, lldb.SBError() | |
| ) | |
| class StepSingleInstructionWithStepOver(StepWithChild): | |
| def __init__(self, thread_plan, dict): | |
| super().__init__(thread_plan) | |
| def queue_child_thread_plan(self): | |
| return self.thread_plan.QueueThreadPlanForStepSingleInstruction( | |
| True, lldb.SBError() | |
| ) | |
| # This plan does a step-over until a variable changes value. | |
| class StepUntil(StepWithChild): | |
| def __init__(self, thread_plan, args_data): | |
| self.thread_plan = thread_plan | |
| self.frame = thread_plan.GetThread().frames[0] | |
| self.target = thread_plan.GetThread().GetProcess().GetTarget() | |
| var_entry = args_data.GetValueForKey("variable_name") | |
| if not var_entry.IsValid(): | |
| print("Did not get a valid entry for variable_name") | |
| self.var_name = var_entry.GetStringValue(100) | |
| self.value = self.frame.FindVariable(self.var_name) | |
| if self.value.GetError().Fail(): | |
| print("Failed to get foo value: %s" % (self.value.GetError().GetCString())) | |
| 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(): | |
| self.thread_plan.SetPlanComplete(True) | |
| return True | |
| if not self.value.IsValid(): | |
| self.thread_plan.SetPlanComplete(True) | |
| return True | |
| if not self.value.GetValueDidChange(): | |
| self.child_thread_plan = self.queue_child_thread_plan() | |
| return False | |
| else: | |
| self.thread_plan.SetPlanComplete(True) | |
| return True | |
| def stop_description(self, stream): | |
| stream.Print(f"Stepped until {self.var_name} changed.") | |
| # This plan does nothing, but sets stop_mode to the | |
| # value of GetStopOthers for this plan. | |
| class StepReportsStopOthers: | |
| stop_mode_dict = {} | |
| def __init__(self, thread_plan, args_data): | |
| self.thread_plan = thread_plan | |
| self.key = str(args_data.GetValueForKey("token").GetUnsignedIntegerValue(1000)) | |
| def should_stop(self, event): | |
| self.thread_plan.SetPlanComplete(True) | |
| StepReportsStopOthers.stop_mode_dict[ | |
| self.key | |
| ] = self.thread_plan.GetStopOthers() | |
| return True | |
| def should_step(self): | |
| return True | |
| def explains_stop(self, event): | |
| return True |