diff options
Diffstat (limited to 'src/monkey/prg_control.c')
-rw-r--r-- | src/monkey/prg_control.c | 454 |
1 files changed, 454 insertions, 0 deletions
diff --git a/src/monkey/prg_control.c b/src/monkey/prg_control.c new file mode 100644 index 000000000..671725f94 --- /dev/null +++ b/src/monkey/prg_control.c | |||
@@ -0,0 +1,454 @@ | |||
1 | /**[txh]******************************************************************** | ||
2 | |||
3 | Copyright (c) 2004 by Salvador E. Tropea. | ||
4 | Covered by the GPL license. | ||
5 | |||
6 | Module: Program control. | ||
7 | Comments: | ||
8 | GDB/MI commands for the "Program Control" section.@p | ||
9 | |||
10 | @<pre> | ||
11 | gdb command: Implemented? | ||
12 | |||
13 | -exec-abort N.A. (*) (kill, but with non-interactive options) | ||
14 | -exec-arguments Yes | ||
15 | -exec-continue Yes ASYNC | ||
16 | -exec-finish Yes ASYNC | ||
17 | -exec-interrupt Yes ASYNC | ||
18 | -exec-next Yes ASYNC | ||
19 | -exec-next-instruction Yes ASYNC | ||
20 | -exec-return Yes | ||
21 | -exec-run Yes ASYNC | ||
22 | -exec-show-arguments N.A. (show args) see gmi_stack_info_frame | ||
23 | -exec-step Yes ASYNC | ||
24 | -exec-step-instruction Yes ASYNC | ||
25 | -exec-until Yes ASYNC | ||
26 | -file-exec-and-symbols Yes | ||
27 | -file-exec-file No | ||
28 | -file-list-exec-sections N.A. (info file) | ||
29 | -file-list-exec-source-files N.A. | ||
30 | -file-list-shared-libraries N.A. | ||
31 | -file-list-symbol-files N.A. | ||
32 | -file-symbol-file Yes | ||
33 | @</pre> | ||
34 | |||
35 | (*) gmi_exec_kill implements it, but you should ensure that | ||
36 | gmi_gdb_set("confirm","off") was called.@p | ||
37 | |||
38 | GDB Bug workaround for -file-exec-and-symbols and -file-symbol-file: This | ||
39 | is complex, but a real bug. When you set a breakpoint you never know the | ||
40 | name of the file as it appears in the debug info. So you can be specifying | ||
41 | an absolute file name or a relative file name. The reference point could be | ||
42 | different than the one used in the debug info. To solve all the combinations | ||
43 | gdb does a search trying various combinations. GDB isn't very smart so you | ||
44 | must at least specify the working directory and the directory where the | ||
45 | binary is located to get a good chance (+ user options to solve the rest). | ||
46 | Once you did it gdb can find the file by doing transformations to the | ||
47 | "canonical" filename. This search works OK for already loaded symtabs | ||
48 | (symbol tables), but it have a bug when the search is done for psymtabs | ||
49 | (partial symtabs). The bug is in the use of source_full_path_of (source.c). | ||
50 | This function calls openp indicating try_cwd_first. It makes the search file | ||
51 | if the psymtab file name have at least one dirseparator. It means that | ||
52 | psymtabs for files compiled with relative paths will fail. The search for | ||
53 | symtabs uses symtab_to_filename, it calls open_source_file which finally | ||
54 | calls openp without try_cwd_first.@* | ||
55 | To workaround this bug we must ensure gdb loads *all* the symtabs to memory. | ||
56 | And here comes another problem -file-exec-and-symbols doesn't support it | ||
57 | according to docs. In real life that's a wrapper for "file", but as nobody | ||
58 | can say it won't change we must use the CLI command. | ||
59 | |||
60 | ***************************************************************************/ | ||
61 | |||
62 | #include <signal.h> | ||
63 | #include "mi_gdb.h" | ||
64 | |||
65 | /* Low level versions. */ | ||
66 | |||
67 | void mi_file_exec_and_symbols(mi_h *h, const char *file) | ||
68 | { | ||
69 | if (mi_get_workaround(MI_PSYM_SEARCH)) | ||
70 | mi_send(h,"file %s -readnow\n",file); | ||
71 | else | ||
72 | mi_send(h,"-file-exec-and-symbols %s\n",file); | ||
73 | } | ||
74 | |||
75 | void mi_exec_arguments(mi_h *h, const char *args) | ||
76 | { | ||
77 | mi_send(h,"-exec-arguments %s\n",args); | ||
78 | } | ||
79 | |||
80 | void mi_exec_run(mi_h *h) | ||
81 | { | ||
82 | mi_send(h,"-exec-run\n"); | ||
83 | } | ||
84 | |||
85 | void mi_exec_continue(mi_h *h) | ||
86 | { | ||
87 | mi_send(h,"-exec-continue\n"); | ||
88 | } | ||
89 | |||
90 | void mi_target_terminal(mi_h *h, const char *tty_name) | ||
91 | { | ||
92 | mi_send(h,"tty %s\n",tty_name); | ||
93 | } | ||
94 | |||
95 | void mi_file_symbol_file(mi_h *h, const char *file) | ||
96 | { | ||
97 | if (mi_get_workaround(MI_PSYM_SEARCH)) | ||
98 | mi_send(h,"symbol-file %s -readnow\n",file); | ||
99 | else | ||
100 | mi_send(h,"-file-symbol-file %s\n",file); | ||
101 | } | ||
102 | |||
103 | void mi_exec_finish(mi_h *h) | ||
104 | { | ||
105 | mi_send(h,"-exec-finish\n"); | ||
106 | } | ||
107 | |||
108 | void mi_exec_interrupt(mi_h *h) | ||
109 | { | ||
110 | mi_send(h,"-exec-interrupt\n"); | ||
111 | } | ||
112 | |||
113 | void mi_exec_next(mi_h *h, int count) | ||
114 | { | ||
115 | if (count>1) | ||
116 | mi_send(h,"-exec-next %d\n",count); | ||
117 | else | ||
118 | mi_send(h,"-exec-next\n"); | ||
119 | } | ||
120 | |||
121 | void mi_exec_next_instruction(mi_h *h) | ||
122 | { | ||
123 | mi_send(h,"-exec-next-instruction\n"); | ||
124 | } | ||
125 | |||
126 | void mi_exec_step(mi_h *h, int count) | ||
127 | { | ||
128 | if (count>1) | ||
129 | mi_send(h,"-exec-step %d\n",count); | ||
130 | else | ||
131 | mi_send(h,"-exec-step\n"); | ||
132 | } | ||
133 | |||
134 | void mi_exec_step_instruction(mi_h *h) | ||
135 | { | ||
136 | mi_send(h,"-exec-step-instruction\n"); | ||
137 | } | ||
138 | |||
139 | void mi_exec_until(mi_h *h, const char *file, int line) | ||
140 | { | ||
141 | if (!file) | ||
142 | mi_send(h,"-exec-until\n"); | ||
143 | else | ||
144 | mi_send(h,"-exec-until %s:%d\n",file,line); | ||
145 | } | ||
146 | |||
147 | void mi_exec_until_addr(mi_h *h, void *addr) | ||
148 | { | ||
149 | mi_send(h,"-exec-until *%p\n",addr); | ||
150 | } | ||
151 | |||
152 | void mi_exec_return(mi_h *h) | ||
153 | { | ||
154 | mi_send(h,"-exec-return\n"); | ||
155 | } | ||
156 | |||
157 | void mi_exec_kill(mi_h *h) | ||
158 | { | ||
159 | mi_send(h,"kill\n"); | ||
160 | } | ||
161 | |||
162 | /* High level versions. */ | ||
163 | |||
164 | /**[txh]******************************************************************** | ||
165 | |||
166 | Description: | ||
167 | Specify the executable and arguments for local debug. | ||
168 | |||
169 | Command: -file-exec-and-symbols + -exec-arguments | ||
170 | Return: !=0 OK | ||
171 | |||
172 | ***************************************************************************/ | ||
173 | |||
174 | int gmi_set_exec(mi_h *h, const char *file, const char *args) | ||
175 | { | ||
176 | mi_file_exec_and_symbols(h,file); | ||
177 | if (!mi_res_simple_done(h)) | ||
178 | return 0; | ||
179 | if (!args) | ||
180 | return 1; | ||
181 | mi_exec_arguments(h,args); | ||
182 | return mi_res_simple_done(h); | ||
183 | } | ||
184 | |||
185 | /**[txh]******************************************************************** | ||
186 | |||
187 | Description: | ||
188 | Start running the executable. Remote sessions starts running. | ||
189 | |||
190 | Command: -exec-run | ||
191 | Return: !=0 OK | ||
192 | |||
193 | ***************************************************************************/ | ||
194 | |||
195 | int gmi_exec_run(mi_h *h) | ||
196 | { | ||
197 | mi_exec_run(h); | ||
198 | return mi_res_simple_running(h); | ||
199 | } | ||
200 | |||
201 | /**[txh]******************************************************************** | ||
202 | |||
203 | Description: | ||
204 | Continue the execution after a "stop". | ||
205 | |||
206 | Command: -exec-continue | ||
207 | Return: !=0 OK | ||
208 | |||
209 | ***************************************************************************/ | ||
210 | |||
211 | int gmi_exec_continue(mi_h *h) | ||
212 | { | ||
213 | mi_exec_continue(h); | ||
214 | return mi_res_simple_running(h); | ||
215 | } | ||
216 | |||
217 | /**[txh]******************************************************************** | ||
218 | |||
219 | Description: | ||
220 | Indicate which terminal will use the target program. For local sessions. | ||
221 | |||
222 | Command: tty | ||
223 | Return: !=0 OK | ||
224 | Example: | ||
225 | |||
226 | ***************************************************************************/ | ||
227 | |||
228 | int gmi_target_terminal(mi_h *h, const char *tty_name) | ||
229 | { | ||
230 | mi_target_terminal(h,tty_name); | ||
231 | return mi_res_simple_done(h); | ||
232 | } | ||
233 | |||
234 | /**[txh]******************************************************************** | ||
235 | |||
236 | Description: | ||
237 | Specify what's the local copy that have debug info. For remote sessions. | ||
238 | |||
239 | Command: -file-symbol-file | ||
240 | Return: !=0 OK | ||
241 | |||
242 | ***************************************************************************/ | ||
243 | |||
244 | int gmi_file_symbol_file(mi_h *h, const char *file) | ||
245 | { | ||
246 | mi_file_symbol_file(h,file); | ||
247 | return mi_res_simple_done(h); | ||
248 | } | ||
249 | |||
250 | /**[txh]******************************************************************** | ||
251 | |||
252 | Description: | ||
253 | Continue until function return, the return value is included in the async | ||
254 | response. | ||
255 | |||
256 | Command: -exec-finish | ||
257 | Return: !=0 OK. | ||
258 | |||
259 | ***************************************************************************/ | ||
260 | |||
261 | int gmi_exec_finish(mi_h *h) | ||
262 | { | ||
263 | mi_exec_finish(h); | ||
264 | return mi_res_simple_running(h); | ||
265 | } | ||
266 | |||
267 | /**[txh]******************************************************************** | ||
268 | |||
269 | Description: | ||
270 | Stop the program using SIGINT. The corresponding command should be | ||
271 | -exec-interrupt but not even gdb 6.1.1 can do it because the "async" mode | ||
272 | isn't really working. | ||
273 | |||
274 | Command: -exec-interrupt [replacement] | ||
275 | Return: Always 1 | ||
276 | Example: | ||
277 | |||
278 | ***************************************************************************/ | ||
279 | |||
280 | int gmi_exec_interrupt(mi_h *h) | ||
281 | { | ||
282 | // **** IMPORTANT!!! **** Not even gdb 6.1.1 can do it because the "async" | ||
283 | // mode isn't really working. | ||
284 | //mi_exec_interrupt(h); | ||
285 | //return mi_res_simple_running(h); | ||
286 | |||
287 | kill(h->pid,SIGINT); | ||
288 | return 1; // How can I know? | ||
289 | } | ||
290 | |||
291 | /**[txh]******************************************************************** | ||
292 | |||
293 | Description: | ||
294 | Next line of code. | ||
295 | |||
296 | Command: -exec-next | ||
297 | Return: !=0 OK | ||
298 | |||
299 | ***************************************************************************/ | ||
300 | |||
301 | int gmi_exec_next(mi_h *h) | ||
302 | { | ||
303 | mi_exec_next(h,1); | ||
304 | return mi_res_simple_running(h); | ||
305 | } | ||
306 | |||
307 | /**[txh]******************************************************************** | ||
308 | |||
309 | Description: | ||
310 | Skip count lines of code. | ||
311 | |||
312 | Command: -exec-next count | ||
313 | Return: !=0 OK | ||
314 | |||
315 | ***************************************************************************/ | ||
316 | |||
317 | int gmi_exec_next_cnt(mi_h *h, int count) | ||
318 | { | ||
319 | mi_exec_next(h,count); | ||
320 | return mi_res_simple_running(h); | ||
321 | } | ||
322 | |||
323 | /**[txh]******************************************************************** | ||
324 | |||
325 | Description: | ||
326 | Next line of assembler code. | ||
327 | |||
328 | Command: -exec-next-instruction | ||
329 | Return: !=0 OK | ||
330 | |||
331 | ***************************************************************************/ | ||
332 | |||
333 | int gmi_exec_next_instruction(mi_h *h) | ||
334 | { | ||
335 | mi_exec_next_instruction(h); | ||
336 | return mi_res_simple_running(h); | ||
337 | } | ||
338 | |||
339 | /**[txh]******************************************************************** | ||
340 | |||
341 | Description: | ||
342 | Next line of code. Get inside functions. | ||
343 | |||
344 | Command: -exec-step | ||
345 | Return: !=0 OK | ||
346 | |||
347 | ***************************************************************************/ | ||
348 | |||
349 | int gmi_exec_step(mi_h *h) | ||
350 | { | ||
351 | mi_exec_step(h,1); | ||
352 | return mi_res_simple_running(h); | ||
353 | } | ||
354 | |||
355 | /**[txh]******************************************************************** | ||
356 | |||
357 | Description: | ||
358 | Next count lines of code. Get inside functions. | ||
359 | |||
360 | Command: -exec-step count | ||
361 | Return: !=0 OK | ||
362 | |||
363 | ***************************************************************************/ | ||
364 | |||
365 | int gmi_exec_step_cnt(mi_h *h, int count) | ||
366 | { | ||
367 | mi_exec_step(h,count); | ||
368 | return mi_res_simple_running(h); | ||
369 | } | ||
370 | |||
371 | /**[txh]******************************************************************** | ||
372 | |||
373 | Description: | ||
374 | Next line of assembler code. Get inside calls. | ||
375 | |||
376 | Command: -exec-step-instruction | ||
377 | Return: !=0 OK | ||
378 | |||
379 | ***************************************************************************/ | ||
380 | |||
381 | int gmi_exec_step_instruction(mi_h *h) | ||
382 | { | ||
383 | mi_exec_step_instruction(h); | ||
384 | return mi_res_simple_running(h); | ||
385 | } | ||
386 | |||
387 | /**[txh]******************************************************************** | ||
388 | |||
389 | Description: | ||
390 | Execute until location is reached. If file is NULL then is until next | ||
391 | line. | ||
392 | |||
393 | Command: -exec-until | ||
394 | Return: !=0 OK | ||
395 | |||
396 | ***************************************************************************/ | ||
397 | |||
398 | int gmi_exec_until(mi_h *h, const char *file, int line) | ||
399 | { | ||
400 | mi_exec_until(h,file,line); | ||
401 | return mi_res_simple_running(h); | ||
402 | } | ||
403 | |||
404 | /**[txh]******************************************************************** | ||
405 | |||
406 | Description: | ||
407 | Execute until location is reached. | ||
408 | |||
409 | Command: -exec-until (using *address) | ||
410 | Return: !=0 OK | ||
411 | |||
412 | ***************************************************************************/ | ||
413 | |||
414 | int gmi_exec_until_addr(mi_h *h, void *addr) | ||
415 | { | ||
416 | mi_exec_until_addr(h,addr); | ||
417 | return mi_res_simple_running(h); | ||
418 | } | ||
419 | |||
420 | /**[txh]******************************************************************** | ||
421 | |||
422 | Description: | ||
423 | Return to previous frame inmediatly. | ||
424 | |||
425 | Command: -exec-return | ||
426 | Return: A pointer to a new mi_frames structure indicating the current | ||
427 | location. NULL on error. | ||
428 | |||
429 | ***************************************************************************/ | ||
430 | |||
431 | mi_frames *gmi_exec_return(mi_h *h) | ||
432 | { | ||
433 | mi_exec_return(h); | ||
434 | return mi_res_frame(h); | ||
435 | } | ||
436 | |||
437 | /**[txh]******************************************************************** | ||
438 | |||
439 | Description: | ||
440 | Just kill the program. That's what -exec-abort should do, but it isn't | ||
441 | implemented by gdb. This implementation only works if the interactive mode | ||
442 | is disabled (gmi_gdb_set("confirm","off")). | ||
443 | |||
444 | Command: -exec-abort [using kill] | ||
445 | Return: !=0 OK | ||
446 | |||
447 | ***************************************************************************/ | ||
448 | |||
449 | int gmi_exec_kill(mi_h *h) | ||
450 | { | ||
451 | mi_exec_kill(h); | ||
452 | return mi_res_simple_done(h); | ||
453 | } | ||
454 | |||