|
1 | 1 | import os
|
2 | 2 | import lldb
|
3 | 3 |
|
4 |
| -from driver import Driver |
| 4 | +from driver import Driver, IDDParallelTerminate |
5 | 5 | from debuggers.lldb.lldb_extensions import *
|
| 6 | +from multiprocessing import Process, Pipe |
6 | 7 |
|
7 |
| -base_response = None |
8 |
| -regressed_response = None |
9 | 8 |
|
10 |
| -class LLDBDebugger(Driver): |
11 |
| - is_initted = False |
| 9 | +processes = [] |
12 | 10 |
|
13 |
| - base_lldb_instance = None |
14 |
| - regression_lldb_instance = None |
15 | 11 |
|
16 |
| - base_command_interpreter = None |
17 |
| - regression_command_interpreter = None |
| 12 | +class LLDBGetState: |
| 13 | + pass |
18 | 14 |
|
19 |
| - lldb_instances = None |
| 15 | +class LLDBDebugger: |
| 16 | + is_initted = False |
20 | 17 |
|
21 |
| - def __init__(self, base_args, regression_args): |
22 |
| - self.base_lldb_instance = lldb.SBDebugger.Create() |
23 |
| - self.base_lldb_instance.SetAsync(False) |
24 |
| - self.base_lldb_instance.SetUseColor(False) |
25 |
| - |
26 |
| - self.regression_lldb_instance = lldb.SBDebugger.Create() |
27 |
| - self.regression_lldb_instance.SetAsync(False) |
28 |
| - self.regression_lldb_instance.SetUseColor(False) |
| 18 | + lldb_instance = None |
29 | 19 |
|
30 |
| - base_error = lldb.SBError() |
31 |
| - base_target = self.base_lldb_instance.CreateTarget(base_args, "x86_64", "host", True, base_error) |
32 |
| - if not base_error.Success(): |
33 |
| - raise Exception(base_error.GetCString()) |
| 20 | + command_interpreter = None |
34 | 21 |
|
35 |
| - regression_error = lldb.SBError() |
36 |
| - regression_target = self.regression_lldb_instance.CreateTarget(regression_args, "x86_64", "host", True, regression_error) |
37 |
| - if not regression_error.Success(): |
38 |
| - raise Exception(regression_error.GetCString()) |
| 22 | + lldb_instances = None |
39 | 23 |
|
40 |
| - self.base_command_interpreter = self.base_lldb_instance.GetCommandInterpreter() |
41 |
| - self.regression_command_interpreter = self.regression_lldb_instance.GetCommandInterpreter() |
| 24 | + def __init__(self, args): |
| 25 | + self.lldb_instance = lldb.SBDebugger.Create() |
| 26 | + self.lldb_instance.SetAsync(False) |
| 27 | + self.lldb_instance.SetUseColor(False) |
| 28 | + |
| 29 | + error = lldb.SBError() |
| 30 | + target = self.lldb_instance.CreateTarget(args, "x86_64", "host", True, error) |
| 31 | + if not error.Success(): |
| 32 | + raise Exception(error.GetCString()) |
42 | 33 |
|
43 |
| - base_launch_info = lldb.SBLaunchInfo(None) |
44 |
| - base_launch_info.SetExecutableFile (base_target.GetExecutable(), True) |
| 34 | + self.command_interpreter = self.lldb_instance.GetCommandInterpreter() |
45 | 35 |
|
46 |
| - regression_launch_info = lldb.SBLaunchInfo(None) |
47 |
| - regression_launch_info.SetExecutableFile (regression_target.GetExecutable(), True) |
| 36 | + launch_info = lldb.SBLaunchInfo(None) |
| 37 | + launch_info.SetExecutableFile (target.GetExecutable(), True) |
48 | 38 |
|
49 | 39 | dirname = os.path.dirname(__file__)
|
50 |
| - self.run_parallel_raw_command("command script import " + os.path.join(dirname, "lldb_commands.py")) |
| 40 | + self.run_single_command("command script import " + os.path.join(dirname, "lldb_commands.py")) |
51 | 41 |
|
52 | 42 | self.is_initted = True
|
53 | 43 |
|
54 |
| - def run_parallel_command(self, command): |
55 |
| - raw_base_response = self.run_single_command(command, "base") |
56 |
| - base_response = raw_base_response[0].split("\n") |
57 |
| - |
58 |
| - raw_regression_response = self.run_single_command(command, "regressed") |
59 |
| - regression_response = raw_regression_response[0].split("\n") |
60 |
| - |
61 |
| - return { "base": base_response, "regressed": regression_response } |
62 |
| - |
63 |
| - def run_parallel_raw_command(self, command): |
64 |
| - base_response = self.run_single_command(command, "base") |
65 |
| - regression_response = self.run_single_command(command, "regressed") |
66 |
| - |
67 |
| - return { "base": base_response, "regressed": regression_response } |
68 |
| - |
69 |
| - |
70 |
| - def run_single_command(self, command, version): |
| 44 | + def run_single_command(self, command): |
71 | 45 | command_result = lldb.SBCommandReturnObject()
|
72 |
| - if version == "base": |
73 |
| - self.base_command_interpreter.HandleCommand(command, command_result) |
74 |
| - elif version == "regressed": |
75 |
| - self.regression_command_interpreter.HandleCommand(command, command_result) |
76 |
| - |
| 46 | + self.command_interpreter.HandleCommand(command, command_result) |
| 47 | + |
77 | 48 | if command_result.Succeeded():
|
78 |
| - return [command_result.GetOutput()] |
| 49 | + return command_result.GetOutput() |
79 | 50 | else:
|
80 |
| - return [command_result.GetError()] |
81 |
| - |
82 |
| - return "" |
83 |
| - |
84 |
| - def get_state(self, version=None): |
85 |
| - result = {} |
86 |
| - base_state = {} |
87 |
| - regression_state = {} |
88 |
| - |
89 |
| - result['stack_frames'] = self.get_current_stack_frames(version) |
90 |
| - result['locals'] = self.get_current_local_vars(None, version) |
91 |
| - result['args'] = self.get_current_args(version) |
92 |
| - result['instructions'] = self.get_current_instructions(version) |
93 |
| - result['registers'] = self.get_current_registers(version) |
| 51 | + return command_result.GetError() |
| 52 | + |
| 53 | + def get_state(self): |
| 54 | + return { |
| 55 | + 'stack_frames': self.get_current_stack_frames(), |
| 56 | + 'locals': self.get_current_local_vars(None), |
| 57 | + 'args': self.get_current_args(), |
| 58 | + 'instructions': self.get_current_instructions(), |
| 59 | + 'registers': self.get_current_registers(), |
| 60 | + } |
| 61 | + |
| 62 | + def get_current_stack_frames(self): |
| 63 | + target = self.lldb_instance.GetTargetAtIndex(0) |
| 64 | + stack_frame = get_current_stack_frame_from_target(target) |
| 65 | + return stack_frame |
| 66 | + |
| 67 | + def get_current_args(self): |
| 68 | + target = self.lldb_instance.GetTargetAtIndex(0) |
| 69 | + args = get_args_as_list(target) |
| 70 | + return args |
| 71 | + |
| 72 | + def get_current_local_vars(self, filters): |
| 73 | + target = self.lldb_instance.GetTargetAtIndex(0) |
| 74 | + target_locals = get_local_vars_as_list(target) |
| 75 | + if filters == 'ignore-order-declaration': |
| 76 | + target_locals.sort() |
| 77 | + return target_locals |
| 78 | + |
| 79 | + def get_current_instructions(self): |
| 80 | + target = self.lldb_instance.GetTargetAtIndex(0) |
| 81 | + args = get_instructions_as_list(target) |
| 82 | + return args |
| 83 | + |
| 84 | + def get_current_registers(self): |
| 85 | + target = self.lldb_instance.GetTargetAtIndex(0) |
| 86 | + args = get_registers_as_list(target) |
| 87 | + return args |
| 88 | + |
| 89 | + def get_current_calls(self): |
| 90 | + target = self.lldb_instance.GetTargetAtIndex(0) |
| 91 | + calls = get_call_instructions(target) |
| 92 | + return calls |
| 93 | + |
| 94 | + def terminate(self): |
| 95 | + pass |
94 | 96 |
|
95 |
| - if version is not None: |
96 |
| - return result |
| 97 | + @staticmethod |
| 98 | + def run(lldb_args, pipe): |
| 99 | + lldb = LLDBDebugger(lldb_args) |
| 100 | + while True: |
| 101 | + args, kwargs = pipe.recv() |
| 102 | + if isinstance(args, IDDParallelTerminate) or isinstance(kwargs, IDDParallelTerminate): |
| 103 | + return |
| 104 | + if isinstance(args, LLDBGetState) or isinstance(kwargs, LLDBGetState): |
| 105 | + res = lldb.get_state() |
| 106 | + pipe.send(res) |
| 107 | + else: |
| 108 | + res = lldb.run_single_command(*args, **kwargs) |
| 109 | + pipe.send(res) |
97 | 110 |
|
98 |
| - base_state['stack_frames'] = result['stack_frames']['base'] |
99 |
| - regression_state['stack_frames'] = result['stack_frames']['regressed'] |
100 | 111 |
|
101 |
| - base_state['locals'] = result['locals']['base'] |
102 |
| - regression_state['locals'] = result['locals']['regressed'] |
103 | 112 |
|
104 |
| - base_state['args'] = result['args']['base'] |
105 |
| - regression_state['args'] = result['args']['regressed'] |
| 113 | +class LLDBParallelDebugger(Driver): |
| 114 | + def __init__(self, base_args, regression_args): |
| 115 | + self.base_pipe = create_LLDBDebugger_for_parallel(base_args) |
| 116 | + self.regressed_pipe = create_LLDBDebugger_for_parallel(regression_args) |
| 117 | + |
| 118 | + def get_state(self, target=None): |
| 119 | + if target == "base": |
| 120 | + self.base_pipe.send((LLDBGetState(), LLDBGetState())) |
| 121 | + return self.base_pipe.recv() |
| 122 | + if target == "regressed": |
| 123 | + self.regressed_pipe.send((LLDBGetState(), LLDBGetState())) |
| 124 | + return self.regressed_pipe.recv() |
| 125 | + |
| 126 | + self.base_pipe.send((LLDBGetState(), LLDBGetState())) |
| 127 | + self.regressed_pipe.send((LLDBGetState(), LLDBGetState())) |
| 128 | + |
| 129 | + return { |
| 130 | + "base": self.base_pipe.recv(), |
| 131 | + "regressed": self.regressed_pipe.recv(), |
| 132 | + } |
| 133 | + |
| 134 | + def run_single_command(self, command, target): |
| 135 | + if target == "base": |
| 136 | + self.base_pipe.send(((command,), {})) |
| 137 | + return self.base_pipe.recv().split("\n") |
| 138 | + if target == "regressed": |
| 139 | + self.regressed_pipe.send(((command,), {})) |
| 140 | + return self.regressed_pipe.recv().split("\n") |
106 | 141 |
|
107 |
| - base_state['instructions'] = result['instructions']['base'] |
108 |
| - regression_state['instructions'] = result['instructions']['regressed'] |
| 142 | + def run_parallel_command(self, command): |
| 143 | + self.base_pipe.send(((command,), {})) |
| 144 | + self.regressed_pipe.send(((command,), {})) |
109 | 145 |
|
110 |
| - base_state['registers'] = result['registers']['base'] |
111 |
| - regression_state['registers'] = result['registers']['regressed'] |
| 146 | + return { |
| 147 | + "base": self.base_pipe.recv().split("\n"), |
| 148 | + "regressed": self.regressed_pipe.recv().split("\n"), |
| 149 | + } |
| 150 | + |
| 151 | + def terminate(self): |
| 152 | + terminate_all_IDDGdbController() |
112 | 153 |
|
113 |
| - return { "base" : base_state, "regressed" : regression_state } |
114 | 154 |
|
115 |
| - def get_current_stack_frames(self, version=None): |
116 |
| - if version == "base": |
117 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
118 |
| - base_stack_frame = get_current_stack_frame_from_target(base_target) |
119 |
| - return base_stack_frame |
120 |
| - |
121 |
| - if version == "regressed": |
122 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
123 |
| - regression_stack_frame = get_current_stack_frame_from_target(regression_target) |
124 |
| - return regression_stack_frame |
125 |
| - |
126 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
127 |
| - base_stack_frame = get_current_stack_frame_from_target(base_target) |
128 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
129 |
| - regression_stack_frame = get_current_stack_frame_from_target(regression_target) |
130 |
| - |
131 |
| - return { "base" : base_stack_frame, "regressed" : regression_stack_frame } |
132 |
| - |
133 |
| - def get_current_args(self, version=None): |
134 |
| - if version == "base": |
135 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
136 |
| - base_args = get_args_as_list(base_target) |
137 |
| - return base_args |
138 |
| - |
139 |
| - if version == "regressed": |
140 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
141 |
| - regression_args = get_args_as_list(regression_target) |
142 |
| - return regression_args |
143 |
| - |
144 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
145 |
| - base_args = get_args_as_list(base_target) |
146 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
147 |
| - regression_args = get_args_as_list(regression_target) |
148 |
| - return { "base" : base_args, "regressed" : regression_args } |
149 |
| - |
150 |
| - def get_current_local_vars(self, filters, version=None): |
151 |
| - if version == "base": |
152 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
153 |
| - base_locals = get_local_vars_as_list(base_target) |
154 |
| - if filters == 'ignore-order-declaration': |
155 |
| - base_locals.sort() |
156 |
| - return base_locals |
157 |
| - |
158 |
| - if version == "regressed": |
159 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
160 |
| - regression_locals = get_local_vars_as_list(regression_target) |
161 |
| - if filters == 'ignore-order-declaration': |
162 |
| - regression_locals.sort() |
163 |
| - return regression_locals |
164 |
| - |
165 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
166 |
| - base_locals = get_local_vars_as_list(base_target) |
167 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
168 |
| - regression_locals = get_local_vars_as_list(regression_target) |
169 |
| - if filters == 'ignore-order-declaration': |
170 |
| - base_locals.sort() |
171 |
| - regression_locals.sort() |
| 155 | +def terminate_all_IDDGdbController(): |
| 156 | + for _, pipe in processes: |
| 157 | + pipe.send((IDDParallelTerminate(), IDDParallelTerminate())) |
| 158 | + for process, _ in processes: |
| 159 | + process.join() |
172 | 160 |
|
173 |
| - return { "base" : base_locals, "regressed" : regression_locals } |
| 161 | +def create_LLDBDebugger_for_parallel(args): |
| 162 | + global processes |
174 | 163 |
|
175 |
| - def get_current_instructions(self, version=None): |
176 |
| - if version == "base": |
177 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
178 |
| - base_args = get_instructions_as_list(base_target) |
179 |
| - return base_args |
180 |
| - |
181 |
| - if version == "regressed": |
182 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
183 |
| - regression_args = get_instructions_as_list(regression_target) |
184 |
| - return regression_args |
185 |
| - |
186 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
187 |
| - base_args = get_instructions_as_list(base_target) |
188 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
189 |
| - regression_args = get_instructions_as_list(regression_target) |
190 |
| - return { "base" : base_args, "regressed" : regression_args } |
191 |
| - |
192 |
| - def get_current_registers(self, version=None): |
193 |
| - if version == "base": |
194 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
195 |
| - base_args = get_registers_as_list(base_target) |
196 |
| - return base_args |
197 |
| - |
198 |
| - if version == "regressed": |
199 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
200 |
| - regression_args = get_registers_as_list(regression_target) |
201 |
| - return regression_args |
202 |
| - |
203 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
204 |
| - base_args = get_registers_as_list(base_target) |
205 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
206 |
| - regression_args = get_registers_as_list(regression_target) |
207 |
| - return { "base" : base_args, "regressed" : regression_args } |
208 |
| - |
209 |
| - def get_current_calls(self, version=None): |
210 |
| - if version == "base": |
211 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
212 |
| - base_calls = get_call_instructions(base_target) |
213 |
| - return base_calls |
214 |
| - |
215 |
| - if version == "regressed": |
216 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
217 |
| - regression_calls = get_call_instructions(regression_target) |
218 |
| - return regression_calls |
219 |
| - |
220 |
| - base_target = self.base_lldb_instance.GetTargetAtIndex(0) |
221 |
| - base_calls = get_call_instructions(base_target) |
222 |
| - regression_target = self.regression_lldb_instance.GetTargetAtIndex(0) |
223 |
| - regression_calls = get_call_instructions(regression_target) |
224 |
| - return { "base" : base_calls, "regressed" : regression_calls } |
225 |
| - |
226 |
| - def terminate(self): |
227 |
| - pass |
| 164 | + parent_conn, child_conn = Pipe() |
| 165 | + process = Process(target=LLDBDebugger.run, args=(args, child_conn)) |
| 166 | + processes.append((process, parent_conn)) |
| 167 | + process.start() |
| 168 | + return parent_conn |
0 commit comments