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 if not self.value.GetValueDidChange(): 79 self.child_thread_plan = self.queue_child_thread_plan() 80 return False 81 else: 82 return True 83 84# This plan does nothing, but sets stop_mode to the 85# value of GetStopOthers for this plan. 86class StepReportsStopOthers(): 87 stop_mode_dict = {} 88 89 def __init__(self, thread_plan, args_data, dict): 90 self.thread_plan = thread_plan 91 self.key = args_data.GetValueForKey("token").GetStringValue(1000) 92 93 def should_stop(self, event): 94 self.thread_plan.SetPlanComplete(True) 95 print("Called in should_stop") 96 StepReportsStopOthers.stop_mode_dict[self.key] = self.thread_plan.GetStopOthers() 97 return True 98 99 def should_step(self): 100 return True 101 102 def explains_stop(self, event): 103 return True 104