xref: /llvm-project/lldb/test/API/functionalities/step_scripted/Steps.py (revision d3dfd8cec44072302818c34193d898903dbaef8f)
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