diff options
Diffstat (limited to 'src/monkey/mi_gdb.h')
-rw-r--r-- | src/monkey/mi_gdb.h | 972 |
1 files changed, 972 insertions, 0 deletions
diff --git a/src/monkey/mi_gdb.h b/src/monkey/mi_gdb.h new file mode 100644 index 000000000..df932b4ec --- /dev/null +++ b/src/monkey/mi_gdb.h | |||
@@ -0,0 +1,972 @@ | |||
1 | /**[txh]******************************************************************** | ||
2 | |||
3 | Copyright (c) 2004-2009 by Salvador E. Tropea. | ||
4 | Covered by the GPL license. | ||
5 | |||
6 | Comments: | ||
7 | Main header for libmigdb. | ||
8 | |||
9 | ***************************************************************************/ | ||
10 | |||
11 | #ifdef __cplusplus | ||
12 | extern "C" { | ||
13 | #endif | ||
14 | |||
15 | #include <stdio.h> | ||
16 | #include <stdlib.h> | ||
17 | #include <unistd.h> /* pid_t */ | ||
18 | |||
19 | #define MI_OK 0 | ||
20 | #define MI_OUT_OF_MEMORY 1 | ||
21 | #define MI_PIPE_CREATE 2 | ||
22 | #define MI_FORK 3 | ||
23 | #define MI_DEBUGGER_RUN 4 | ||
24 | #define MI_PARSER 5 | ||
25 | #define MI_UNKNOWN_ASYNC 6 | ||
26 | #define MI_UNKNOWN_RESULT 7 | ||
27 | #define MI_FROM_GDB 8 | ||
28 | #define MI_GDB_TIME_OUT 9 | ||
29 | #define MI_GDB_DIED 10 | ||
30 | #define MI_MISSING_XTERM 11 | ||
31 | #define MI_CREATE_TEMPORAL 12 | ||
32 | #define MI_MISSING_GDB 13 | ||
33 | #define MI_LAST_ERROR 13 | ||
34 | |||
35 | #define MI_R_NONE 0 /* We are no waiting any response. */ | ||
36 | #define MI_R_SKIP 1 /* We want to discard it. */ | ||
37 | #define MI_R_FE_AND_S 2 /* Wait for done. */ | ||
38 | #define MI_R_E_ARGS 3 | ||
39 | |||
40 | enum mi_val_type { t_const, t_tuple, t_list }; | ||
41 | |||
42 | /* Types and subtypes. */ | ||
43 | /* Type. */ | ||
44 | #define MI_T_OUT_OF_BAND 0 | ||
45 | #define MI_T_RESULT_RECORD 1 | ||
46 | /* Out of band subtypes. */ | ||
47 | #define MI_ST_ASYNC 0 | ||
48 | #define MI_ST_STREAM 1 | ||
49 | /* Async sub-subtypes. */ | ||
50 | #define MI_SST_EXEC 0 | ||
51 | #define MI_SST_STATUS 1 | ||
52 | #define MI_SST_NOTIFY 2 | ||
53 | /* Stream sub-subtypes. */ | ||
54 | #define MI_SST_CONSOLE 3 | ||
55 | #define MI_SST_TARGET 4 | ||
56 | #define MI_SST_LOG 5 | ||
57 | /* Classes. */ | ||
58 | /* Async classes. */ | ||
59 | #define MI_CL_UNKNOWN 0 | ||
60 | #define MI_CL_STOPPED 1 | ||
61 | #define MI_CL_DOWNLOAD 2 | ||
62 | /* Result classes. */ | ||
63 | #define MI_CL_DONE 2 | ||
64 | #define MI_CL_RUNNING 3 | ||
65 | #define MI_CL_CONNECTED 4 | ||
66 | #define MI_CL_ERROR 5 | ||
67 | #define MI_CL_EXIT 6 | ||
68 | |||
69 | #define MI_DEFAULT_TIME_OUT 10 | ||
70 | |||
71 | #define MI_DIS_ASM 0 | ||
72 | #define MI_DIS_SRC_ASM 1 | ||
73 | |||
74 | /* Implemented workaround for gdb bugs that we can dis/enable. */ | ||
75 | /* At least gdb<=6.1.1 fails to find a source file with absolute path if the | ||
76 | name is for a psym instead of a sym. psym==partially loaded symbol table. */ | ||
77 | #define MI_PSYM_SEARCH 0 | ||
78 | |||
79 | #define MI_VERSION_STR "0.8.12" | ||
80 | #define MI_VERSION_MAJOR 0 | ||
81 | #define MI_VERSION_MIDDLE 8 | ||
82 | #define MI_VERSION_MINOR 12 | ||
83 | |||
84 | struct mi_results_struct | ||
85 | { | ||
86 | char *var; /* Result name or NULL if just a value. */ | ||
87 | enum mi_val_type type; | ||
88 | union | ||
89 | { | ||
90 | char *cstr; | ||
91 | struct mi_results_struct *rs; | ||
92 | } v; | ||
93 | struct mi_results_struct *next; | ||
94 | }; | ||
95 | typedef struct mi_results_struct mi_results; | ||
96 | |||
97 | struct mi_output_struct | ||
98 | { | ||
99 | /* Type of output. */ | ||
100 | char type; | ||
101 | char stype; | ||
102 | char sstype; | ||
103 | char tclass; | ||
104 | /* Content. */ | ||
105 | mi_results *c; | ||
106 | /* Always modeled as a list. */ | ||
107 | struct mi_output_struct *next; | ||
108 | }; | ||
109 | typedef struct mi_output_struct mi_output; | ||
110 | |||
111 | typedef void (*stream_cb)(const char *, void *); | ||
112 | typedef void (*async_cb)(mi_output *o, void *); | ||
113 | typedef int (*tm_cb)(void *); | ||
114 | |||
115 | /* Values of this structure shouldn't be manipulated by the user. */ | ||
116 | struct mi_h_struct | ||
117 | { | ||
118 | /* Pipes connected to gdb. */ | ||
119 | int to_gdb[2]; | ||
120 | int from_gdb[2]; | ||
121 | /* Streams for the pipes. */ | ||
122 | FILE *to, *from; | ||
123 | /* PID of child gdb. */ | ||
124 | pid_t pid; | ||
125 | char died; | ||
126 | /* Which rensponse we are waiting for. */ | ||
127 | /*int response;*/ | ||
128 | /* The line we are reading. */ | ||
129 | char *line; | ||
130 | int llen, lread; | ||
131 | /* Parsed output. */ | ||
132 | mi_output *po, *last; | ||
133 | /* Tunneled streams callbacks. */ | ||
134 | stream_cb console; | ||
135 | void *console_data; | ||
136 | stream_cb target; | ||
137 | void *target_data; | ||
138 | stream_cb log; | ||
139 | void *log_data; | ||
140 | /* Async responses callback. */ | ||
141 | async_cb async; | ||
142 | void *async_data; | ||
143 | /* Callbacks to get echo of gdb dialog. */ | ||
144 | stream_cb to_gdb_echo; | ||
145 | void *to_gdb_echo_data; | ||
146 | stream_cb from_gdb_echo; | ||
147 | void *from_gdb_echo_data; | ||
148 | /* Time out */ | ||
149 | tm_cb time_out_cb; | ||
150 | void *time_out_cb_data; | ||
151 | int time_out; | ||
152 | /* Ugly workaround for some of the show responses :-( */ | ||
153 | int catch_console; | ||
154 | char *catched_console; | ||
155 | /* MI version, currently unknown but the user can force v2 */ | ||
156 | unsigned version; | ||
157 | }; | ||
158 | typedef struct mi_h_struct mi_h; | ||
159 | |||
160 | #define MI_TO(a) ((a)->to_gdb[1]) | ||
161 | |||
162 | enum mi_bkp_type { t_unknown=0, t_breakpoint=1, t_hw=2 }; | ||
163 | enum mi_bkp_disp { d_unknown=0, d_keep=1, d_del=2 }; | ||
164 | enum mi_bkp_mode { m_file_line=0, m_function=1, m_file_function=2, m_address=3 }; | ||
165 | |||
166 | struct mi_bkpt_struct | ||
167 | { | ||
168 | int number; | ||
169 | enum mi_bkp_type type; | ||
170 | enum mi_bkp_disp disp; /* keep or del if temporal */ | ||
171 | char enabled; | ||
172 | void *addr; | ||
173 | char *func; | ||
174 | char *file; | ||
175 | int line; | ||
176 | int ignore; | ||
177 | int times; | ||
178 | |||
179 | /* For the user: */ | ||
180 | char *cond; | ||
181 | char *file_abs; | ||
182 | int thread; | ||
183 | enum mi_bkp_mode mode; | ||
184 | struct mi_bkpt_struct *next; | ||
185 | }; | ||
186 | typedef struct mi_bkpt_struct mi_bkpt; | ||
187 | |||
188 | enum mi_wp_mode { wm_unknown=0, wm_write=1, wm_read=2, wm_rw=3 }; | ||
189 | |||
190 | struct mi_wp_struct | ||
191 | { | ||
192 | int number; | ||
193 | char *exp; | ||
194 | enum mi_wp_mode mode; | ||
195 | |||
196 | /* For the user: */ | ||
197 | struct mi_wp_struct *next; | ||
198 | char enabled; | ||
199 | }; | ||
200 | typedef struct mi_wp_struct mi_wp; | ||
201 | |||
202 | struct mi_frames_struct | ||
203 | { | ||
204 | int level; /* The frame number, 0 being the topmost frame, i.e. the innermost | ||
205 | function. */ | ||
206 | void *addr; /* The `$pc' value for that frame. */ | ||
207 | char *func; /* Function name. */ | ||
208 | char *file; /* File name of the source file where the function lives. */ | ||
209 | char *from; | ||
210 | int line; /* Line number corresponding to the `$pc'. */ | ||
211 | /* When arguments are available: */ | ||
212 | mi_results *args; | ||
213 | int thread_id; | ||
214 | /* When more than one is provided: */ | ||
215 | struct mi_frames_struct *next; | ||
216 | }; | ||
217 | typedef struct mi_frames_struct mi_frames; | ||
218 | |||
219 | struct mi_aux_term_struct | ||
220 | { | ||
221 | pid_t pid; | ||
222 | char *tty; | ||
223 | }; | ||
224 | typedef struct mi_aux_term_struct mi_aux_term; | ||
225 | |||
226 | struct mi_pty_struct | ||
227 | { | ||
228 | char *slave; | ||
229 | int master; | ||
230 | }; | ||
231 | typedef struct mi_pty_struct mi_pty; | ||
232 | |||
233 | enum mi_gvar_fmt { fm_natural=0, fm_binary=1, fm_decimal=2, fm_hexadecimal=3, | ||
234 | fm_octal=4, | ||
235 | /* Only for registers format: */ | ||
236 | fm_raw=5 }; | ||
237 | enum mi_gvar_lang { lg_unknown=0, lg_c, lg_cpp, lg_java }; | ||
238 | |||
239 | #define MI_ATTR_DONT_KNOW 0 | ||
240 | #define MI_ATTR_NONEDITABLE 1 | ||
241 | #define MI_ATTR_EDITABLE 2 | ||
242 | |||
243 | struct mi_gvar_struct | ||
244 | { | ||
245 | char *name; | ||
246 | int numchild; | ||
247 | char *type; | ||
248 | enum mi_gvar_fmt format; | ||
249 | enum mi_gvar_lang lang; | ||
250 | char *exp; | ||
251 | int attr; | ||
252 | |||
253 | /* MI v2 fills it, not yet implemented here. */ | ||
254 | /* Use gmi_var_evaluate_expression. */ | ||
255 | char *value; | ||
256 | |||
257 | /* Pointer to the parent. NULL if none. */ | ||
258 | struct mi_gvar_struct *parent; | ||
259 | /* List containing the children. | ||
260 | Filled by gmi_var_list_children. | ||
261 | NULL if numchild==0 or not yet filled. */ | ||
262 | struct mi_gvar_struct *child; | ||
263 | /* Next var in the list. */ | ||
264 | struct mi_gvar_struct *next; | ||
265 | |||
266 | /* For the user: */ | ||
267 | char opened; /* We will show its children. 1 when we fill "child" */ | ||
268 | char changed; /* Needs to be updated. 0 when created. */ | ||
269 | int vischild; /* How many items visible. numchild when we fill "child" */ | ||
270 | int depth; /* How deep is this var. */ | ||
271 | char ispointer; | ||
272 | }; | ||
273 | typedef struct mi_gvar_struct mi_gvar; | ||
274 | |||
275 | struct mi_gvar_chg_struct | ||
276 | { | ||
277 | char *name; | ||
278 | int in_scope; /* if true the other fields apply. */ | ||
279 | char *new_type; /* NULL if type_changed==false */ | ||
280 | int new_num_children; /* only when new_type!=NULL */ | ||
281 | |||
282 | struct mi_gvar_chg_struct *next; | ||
283 | }; | ||
284 | typedef struct mi_gvar_chg_struct mi_gvar_chg; | ||
285 | |||
286 | |||
287 | /* A list of assembler instructions. */ | ||
288 | struct mi_asm_insn_struct | ||
289 | { | ||
290 | void *addr; | ||
291 | char *func; | ||
292 | unsigned offset; | ||
293 | char *inst; | ||
294 | |||
295 | struct mi_asm_insn_struct *next; | ||
296 | }; | ||
297 | typedef struct mi_asm_insn_struct mi_asm_insn; | ||
298 | |||
299 | /* A list of source lines containing assembler instructions. */ | ||
300 | struct mi_asm_insns_struct | ||
301 | { | ||
302 | char *file; | ||
303 | int line; | ||
304 | mi_asm_insn *ins; | ||
305 | |||
306 | struct mi_asm_insns_struct *next; | ||
307 | }; | ||
308 | typedef struct mi_asm_insns_struct mi_asm_insns; | ||
309 | |||
310 | /* Changed register. */ | ||
311 | struct mi_chg_reg_struct | ||
312 | { | ||
313 | int reg; | ||
314 | char *val; | ||
315 | char *name; | ||
316 | char updated; | ||
317 | |||
318 | struct mi_chg_reg_struct *next; | ||
319 | }; | ||
320 | typedef struct mi_chg_reg_struct mi_chg_reg; | ||
321 | |||
322 | /* | ||
323 | Examining gdb sources and looking at docs I can see the following "stop" | ||
324 | reasons: | ||
325 | |||
326 | Breakpoints: | ||
327 | a) breakpoint-hit (bkptno) + frame | ||
328 | Also: without reason for temporal breakpoints. | ||
329 | |||
330 | Watchpoints: | ||
331 | b) watchpoint-trigger (wpt={number,exp};value={old,new}) + frame | ||
332 | c) read-watchpoint-trigger (hw-rwpt{number,exp};value={value}) + frame | ||
333 | d) access-watchpoint-trigger (hw-awpt{number,exp};value={[old,]new}) + frame | ||
334 | e) watchpoint-scope (wpnum) + frame | ||
335 | |||
336 | Movement: | ||
337 | f) function-finished ([gdb-result-var,return-value]) + frame | ||
338 | g) location-reached + frame | ||
339 | h) end-stepping-range + frame | ||
340 | |||
341 | Exit: | ||
342 | i) exited-signalled (signal-name,signal-meaning) | ||
343 | j) exited (exit-code) | ||
344 | k) exited-normally | ||
345 | |||
346 | Signal: | ||
347 | l) signal-received (signal-name,signal-meaning) + frame | ||
348 | |||
349 | Plus: thread-id | ||
350 | */ | ||
351 | enum mi_stop_reason | ||
352 | { | ||
353 | sr_unknown=0, | ||
354 | sr_bkpt_hit, | ||
355 | sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope, | ||
356 | sr_function_finished, sr_location_reached, sr_end_stepping_range, | ||
357 | sr_exited_signalled, sr_exited, sr_exited_normally, | ||
358 | sr_signal_received | ||
359 | }; | ||
360 | |||
361 | struct mi_stop_struct | ||
362 | { | ||
363 | enum mi_stop_reason reason; /* If more than one reason just the last. */ | ||
364 | /* Flags indicating if non-pointer fields are filled. */ | ||
365 | char have_thread_id; | ||
366 | char have_bkptno; | ||
367 | char have_exit_code; | ||
368 | char have_wpno; | ||
369 | /* Where stopped. Doesn't exist for sr_exited*. */ | ||
370 | int thread_id; | ||
371 | mi_frames *frame; | ||
372 | /* sr_bkpt_hit */ | ||
373 | int bkptno; | ||
374 | /* sr_*wp_* no scope */ | ||
375 | mi_wp *wp; | ||
376 | char *wp_old; | ||
377 | char *wp_val; | ||
378 | /* sr_wp_scope */ | ||
379 | int wpno; | ||
380 | /* sr_function_finished. Not for void func. */ | ||
381 | char *gdb_result_var; | ||
382 | char *return_value; | ||
383 | /* sr_exited_signalled, sr_signal_received */ | ||
384 | char *signal_name; | ||
385 | char *signal_meaning; | ||
386 | /* sr_exited */ | ||
387 | int exit_code; | ||
388 | }; | ||
389 | typedef struct mi_stop_struct mi_stop; | ||
390 | |||
391 | /* Variable containing the last error. */ | ||
392 | extern int mi_error; | ||
393 | extern char *mi_error_from_gdb; | ||
394 | const char *mi_get_error_str(); | ||
395 | |||
396 | /* Indicate the name of gdb exe. Default is /usr/bin/gdb */ | ||
397 | void mi_set_gdb_exe(const char *name); | ||
398 | const char *mi_get_gdb_exe(); | ||
399 | /* Indicate the name of a file containing commands to send at start-up */ | ||
400 | void mi_set_gdb_start(const char *name); | ||
401 | const char *mi_get_gdb_start(); | ||
402 | /* Indicate the name of a file containing commands to send after connection */ | ||
403 | void mi_set_gdb_conn(const char *name); | ||
404 | const char *mi_get_gdb_conn(); | ||
405 | void mi_send_target_commands(mi_h *h); | ||
406 | /* Connect to a local copy of gdb. */ | ||
407 | mi_h *mi_connect_local(); | ||
408 | /* Close connection. You should ask gdb to quit first. */ | ||
409 | void mi_disconnect(mi_h *h); | ||
410 | /* Force MI version. */ | ||
411 | #define MI_VERSION2U(maj,mid,min) (maj*0x1000000+mid*0x10000+min) | ||
412 | void mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle, | ||
413 | unsigned vMinor); | ||
414 | void mi_set_workaround(unsigned wa, int enable); | ||
415 | int mi_get_workaround(unsigned wa); | ||
416 | /* Parse gdb output. */ | ||
417 | mi_output *mi_parse_gdb_output(const char *str); | ||
418 | /* Functions to set/get the tunneled streams callbacks. */ | ||
419 | void mi_set_console_cb(mi_h *h, stream_cb cb, void *data); | ||
420 | void mi_set_target_cb(mi_h *h, stream_cb cb, void *data); | ||
421 | void mi_set_log_cb(mi_h *h, stream_cb cb, void *data); | ||
422 | stream_cb mi_get_console_cb(mi_h *h, void **data); | ||
423 | stream_cb mi_get_target_cb(mi_h *h, void **data); | ||
424 | stream_cb mi_get_log_cb(mi_h *h, void **data); | ||
425 | /* The callback to deal with async events. */ | ||
426 | void mi_set_async_cb(mi_h *h, async_cb cb, void *data); | ||
427 | async_cb mi_get_async_cb(mi_h *h, void **data); | ||
428 | /* Time out in gdb responses. */ | ||
429 | void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data); | ||
430 | tm_cb mi_get_time_out_cb(mi_h *h, void **data); | ||
431 | void mi_set_time_out(mi_h *h, int to); | ||
432 | int mi_get_time_out(mi_h *h); | ||
433 | /* Callbacks to "see" the dialog with gdb. */ | ||
434 | void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data); | ||
435 | void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data); | ||
436 | stream_cb mi_get_to_gdb_cb(mi_h *h, void **data); | ||
437 | stream_cb mi_get_from_gdb_cb(mi_h *h, void **data); | ||
438 | /* Sends a message to gdb. */ | ||
439 | int mi_send(mi_h *h, const char *format, ...); | ||
440 | /* Wait until gdb sends a response. */ | ||
441 | mi_output *mi_get_response_blk(mi_h *h); | ||
442 | /* Check if gdb sent a complete response. Use with mi_retire_response. */ | ||
443 | int mi_get_response(mi_h *h); | ||
444 | /* Get the last response. Use with mi_get_response. */ | ||
445 | mi_output *mi_retire_response(mi_h *h); | ||
446 | /* Look for a result record in gdb output. */ | ||
447 | mi_output *mi_get_rrecord(mi_output *r); | ||
448 | /* Look if the output contains an async stop. | ||
449 | If that's the case return the reason for the stop. | ||
450 | If the output contains an error the description is returned in reason. */ | ||
451 | int mi_get_async_stop_reason(mi_output *r, char **reason); | ||
452 | mi_stop *mi_get_stopped(mi_results *r); | ||
453 | mi_frames *mi_get_async_frame(mi_output *r); | ||
454 | /* Wait until gdb sends a response. | ||
455 | Then check if the response is of the desired type. */ | ||
456 | int mi_res_simple_exit(mi_h *h); | ||
457 | int mi_res_simple_done(mi_h *h); | ||
458 | int mi_res_simple_running(mi_h *h); | ||
459 | int mi_res_simple_connected(mi_h *h); | ||
460 | /* It additionally extracts an specified variable. */ | ||
461 | mi_results *mi_res_done_var(mi_h *h, const char *var); | ||
462 | /* Extract a frames list from the response. */ | ||
463 | mi_frames *mi_res_frames_array(mi_h *h, const char *var); | ||
464 | mi_frames *mi_res_frames_list(mi_h *h); | ||
465 | mi_frames *mi_parse_frame(mi_results *c); | ||
466 | mi_frames *mi_res_frame(mi_h *h); | ||
467 | /* Create an auxiliar terminal using xterm. */ | ||
468 | mi_aux_term *gmi_start_xterm(); | ||
469 | /* Indicate the name of xterm exe. Default is /usr/bin/X11/xterm */ | ||
470 | void mi_set_xterm_exe(const char *name); | ||
471 | const char *mi_get_xterm_exe(); | ||
472 | /* Kill the auxiliar terminal and release the structure. */ | ||
473 | void gmi_end_aux_term(mi_aux_term *t); | ||
474 | /* Look for a free Linux VT for the child. */ | ||
475 | mi_aux_term *gmi_look_for_free_vt(); | ||
476 | /* Look for a free and usable Linux VT. */ | ||
477 | int mi_look_for_free_vt(); | ||
478 | /* Close master and release the structure. */ | ||
479 | void gmi_end_pty(mi_pty *p); | ||
480 | /* Look for a free pseudo terminal. */ | ||
481 | mi_pty *gmi_look_for_free_pty(); | ||
482 | /* Extract a list of thread IDs from response. */ | ||
483 | int mi_res_thread_ids(mi_h *h, int **list); | ||
484 | int mi_get_thread_ids(mi_output *res, int **list); | ||
485 | /* A variable response. */ | ||
486 | mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression); | ||
487 | enum mi_gvar_fmt mi_format_str_to_enum(const char *format); | ||
488 | const char *mi_format_enum_to_str(enum mi_gvar_fmt format); | ||
489 | char mi_format_enum_to_char(enum mi_gvar_fmt format); | ||
490 | enum mi_gvar_lang mi_lang_str_to_enum(const char *lang); | ||
491 | const char *mi_lang_enum_to_str(enum mi_gvar_lang lang); | ||
492 | int mi_res_changelist(mi_h *h, mi_gvar_chg **changed); | ||
493 | int mi_res_children(mi_h *h, mi_gvar *v); | ||
494 | mi_bkpt *mi_res_bkpt(mi_h *h); | ||
495 | mi_wp *mi_res_wp(mi_h *h); | ||
496 | char *mi_res_value(mi_h *h); | ||
497 | mi_stop *mi_res_stop(mi_h *h); | ||
498 | enum mi_stop_reason mi_reason_str_to_enum(const char *s); | ||
499 | const char *mi_reason_enum_to_str(enum mi_stop_reason r); | ||
500 | int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na, | ||
501 | unsigned long *addr); | ||
502 | mi_asm_insns *mi_get_asm_insns(mi_h *h); | ||
503 | /* Starting point of the program. */ | ||
504 | void mi_set_main_func(const char *name); | ||
505 | const char *mi_get_main_func(); | ||
506 | mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many); | ||
507 | int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l); | ||
508 | mi_chg_reg *mi_get_list_changed_regs(mi_h *h); | ||
509 | int mi_get_reg_values(mi_h *h, mi_chg_reg *l); | ||
510 | mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many); | ||
511 | int gmi_target_download(mi_h *h); | ||
512 | |||
513 | /* Allocation functions: */ | ||
514 | void *mi_calloc(size_t count, size_t sz); | ||
515 | void *mi_calloc1(size_t sz); | ||
516 | char *mi_malloc(size_t sz); | ||
517 | mi_results *mi_alloc_results(void); | ||
518 | mi_output *mi_alloc_output(void); | ||
519 | mi_frames *mi_alloc_frames(void); | ||
520 | mi_gvar *mi_alloc_gvar(void); | ||
521 | mi_gvar_chg *mi_alloc_gvar_chg(void); | ||
522 | mi_bkpt *mi_alloc_bkpt(void); | ||
523 | mi_wp *mi_alloc_wp(void); | ||
524 | mi_stop *mi_alloc_stop(void); | ||
525 | mi_asm_insns *mi_alloc_asm_insns(void); | ||
526 | mi_asm_insn *mi_alloc_asm_insn(void); | ||
527 | mi_chg_reg *mi_alloc_chg_reg(void); | ||
528 | void mi_free_output(mi_output *r); | ||
529 | void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r); | ||
530 | void mi_free_frames(mi_frames *f); | ||
531 | void mi_free_aux_term(mi_aux_term *t); | ||
532 | void mi_free_results(mi_results *r); | ||
533 | void mi_free_results_but(mi_results *r, mi_results *no); | ||
534 | void mi_free_gvar(mi_gvar *v); | ||
535 | void mi_free_gvar_chg(mi_gvar_chg *p); | ||
536 | void mi_free_wp(mi_wp *wp); | ||
537 | void mi_free_stop(mi_stop *s); | ||
538 | void mi_free_asm_insns(mi_asm_insns *i); | ||
539 | void mi_free_asm_insn(mi_asm_insn *i); | ||
540 | void mi_free_charp_list(char **l); | ||
541 | void mi_free_chg_reg(mi_chg_reg *r); | ||
542 | |||
543 | /* Porgram control: */ | ||
544 | /* Specify the executable and arguments for local debug. */ | ||
545 | int gmi_set_exec(mi_h *h, const char *file, const char *args); | ||
546 | /* Start running the executable. Remote sessions starts running. */ | ||
547 | int gmi_exec_run(mi_h *h); | ||
548 | /* Continue the execution after a "stop". */ | ||
549 | int gmi_exec_continue(mi_h *h); | ||
550 | /* Indicate which terminal will use the target program. For local sessions. */ | ||
551 | int gmi_target_terminal(mi_h *h, const char *tty_name); | ||
552 | /* Specify what's the local copy that have debug info. For remote sessions. */ | ||
553 | int gmi_file_symbol_file(mi_h *h, const char *file); | ||
554 | /* Continue until function return, the return value is included in the async | ||
555 | response. */ | ||
556 | int gmi_exec_finish(mi_h *h); | ||
557 | /* Stop the program using SIGINT. */ | ||
558 | int gmi_exec_interrupt(mi_h *h); | ||
559 | /* Next line of code. */ | ||
560 | int gmi_exec_next(mi_h *h); | ||
561 | /* Next count lines of code. */ | ||
562 | int gmi_exec_next_cnt(mi_h *h, int count); | ||
563 | /* Next line of assembler code. */ | ||
564 | int gmi_exec_next_instruction(mi_h *h); | ||
565 | /* Next line of code. Get inside functions. */ | ||
566 | int gmi_exec_step(mi_h *h); | ||
567 | /* Next count lines of code. Get inside functions. */ | ||
568 | int gmi_exec_step_cnt(mi_h *h, int count); | ||
569 | /* Next line of assembler code. Get inside calls. */ | ||
570 | int gmi_exec_step_instruction(mi_h *h); | ||
571 | /* Execute until location is reached. If file is NULL then is until next line. */ | ||
572 | int gmi_exec_until(mi_h *h, const char *file, int line); | ||
573 | int gmi_exec_until_addr(mi_h *h, void *addr); | ||
574 | /* Return to previous frame inmediatly. */ | ||
575 | mi_frames *gmi_exec_return(mi_h *h); | ||
576 | /* Just kill the program. Please read the notes in prg_control.c. */ | ||
577 | int gmi_exec_kill(mi_h *h); | ||
578 | |||
579 | /* Target manipulation: */ | ||
580 | /* Connect to a remote gdbserver using the specified methode. */ | ||
581 | int gmi_target_select(mi_h *h, const char *type, const char *params); | ||
582 | /* Attach to an already running process. */ | ||
583 | mi_frames *gmi_target_attach(mi_h *h, pid_t pid); | ||
584 | /* Detach from an attached process. */ | ||
585 | int gmi_target_detach(mi_h *h); | ||
586 | |||
587 | /* Miscellaneous commands: */ | ||
588 | /* Exit gdb killing the child is it is running. */ | ||
589 | void gmi_gdb_exit(mi_h *h); | ||
590 | /* Send the version to the console. */ | ||
591 | int gmi_gdb_version(mi_h *h); | ||
592 | /* Set a gdb variable. */ | ||
593 | int gmi_gdb_set(mi_h *h, const char *var, const char *val); | ||
594 | /* Get a gdb variable. */ | ||
595 | char *gmi_gdb_show(mi_h *h, const char *var); | ||
596 | |||
597 | /* Breakpoints manipulation: */ | ||
598 | /* Insert a breakpoint at file:line. */ | ||
599 | mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line); | ||
600 | /* Insert a breakpoint, all available options. */ | ||
601 | mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist, | ||
602 | const char *cond, int count, int thread, | ||
603 | const char *where); | ||
604 | mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line, | ||
605 | int temporary, int hard_assist, | ||
606 | const char *cond, int count, int thread); | ||
607 | /* Remove a breakpoint. */ | ||
608 | int gmi_break_delete(mi_h *h, int number); | ||
609 | /* Free the memory used for a breakpoint description. */ | ||
610 | void mi_free_bkpt(mi_bkpt *b); | ||
611 | /* Modify the "ignore" count for a breakpoint. */ | ||
612 | int gmi_break_set_times(mi_h *h, int number, int count); | ||
613 | /* Associate a condition with the breakpoint. */ | ||
614 | int gmi_break_set_condition(mi_h *h, int number, const char *condition); | ||
615 | /* Enable or disable a breakpoint. */ | ||
616 | int gmi_break_state(mi_h *h, int number, int enable); | ||
617 | /* Set a watchpoint. It doesn't work for remote targets! */ | ||
618 | mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp); | ||
619 | |||
620 | /* Data Manipulation. */ | ||
621 | /* Evaluate an expression. Returns a parsed tree. */ | ||
622 | char *gmi_data_evaluate_expression(mi_h *h, const char *expression); | ||
623 | /* Path for sources. */ | ||
624 | int gmi_dir(mi_h *h, const char *path); | ||
625 | /* A very limited "data read memory" implementation. */ | ||
626 | int gmi_read_memory(mi_h *h, const char *exp, unsigned size, | ||
627 | unsigned char *dest, int *na, int convAddr, | ||
628 | unsigned long *addr); | ||
629 | mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start, | ||
630 | const char *end, int mode); | ||
631 | mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line, | ||
632 | int lines, int mode); | ||
633 | mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many); | ||
634 | int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l); | ||
635 | mi_chg_reg *gmi_data_list_changed_registers(mi_h *h); | ||
636 | int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l); | ||
637 | mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many); | ||
638 | |||
639 | /* Stack manipulation. */ | ||
640 | /* List of frames. Arguments aren't filled. */ | ||
641 | mi_frames *gmi_stack_list_frames(mi_h *h); | ||
642 | /* List of frames. Indicating a range. */ | ||
643 | mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to); | ||
644 | /* List arguments. Only level and args filled. */ | ||
645 | mi_frames *gmi_stack_list_arguments(mi_h *h, int show); | ||
646 | /* List arguments. Indicating a range. Only level and args filled. */ | ||
647 | mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to); | ||
648 | /* Information about the current frame, including args. */ | ||
649 | mi_frames *gmi_stack_info_frame(mi_h *h); | ||
650 | /* Stack info depth. error => -1 */ | ||
651 | int gmi_stack_info_depth_get(mi_h *h); | ||
652 | /* Set stack info depth. error => -1 */ | ||
653 | int gmi_stack_info_depth(mi_h *h, int max_depth); | ||
654 | /* Change current frame. */ | ||
655 | int gmi_stack_select_frame(mi_h *h, int framenum); | ||
656 | /* List of local vars. */ | ||
657 | mi_results *gmi_stack_list_locals(mi_h *h, int show); | ||
658 | |||
659 | /* Thread. */ | ||
660 | /* List available thread ids. */ | ||
661 | int gmi_thread_list_ids(mi_h *h, int **list); | ||
662 | /* Select a thread. */ | ||
663 | mi_frames *gmi_thread_select(mi_h *h, int id); | ||
664 | /* List available threads. */ | ||
665 | mi_frames *gmi_thread_list_all_threads(mi_h *h); | ||
666 | |||
667 | /* Variable objects. */ | ||
668 | /* Create a variable object. */ | ||
669 | mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp); | ||
670 | mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp); | ||
671 | /* Create the variable and also fill the lang and attr fields. */ | ||
672 | mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp); | ||
673 | /* Delete a variable object. Doesn't free the mi_gvar data. */ | ||
674 | int gmi_var_delete(mi_h *h, mi_gvar *var); | ||
675 | /* Set the format used to represent the result. */ | ||
676 | int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format); | ||
677 | /* Fill the format field with info from gdb. */ | ||
678 | int gmi_var_show_format(mi_h *h, mi_gvar *var); | ||
679 | /* Fill the numchild field with info from gdb. */ | ||
680 | int gmi_var_info_num_children(mi_h *h, mi_gvar *var); | ||
681 | /* Fill the type field with info from gdb. */ | ||
682 | int gmi_var_info_type(mi_h *h, mi_gvar *var); | ||
683 | /* Fill the expression and lang fields with info from gdb. | ||
684 | Note that lang isn't filled during creation. */ | ||
685 | int gmi_var_info_expression(mi_h *h, mi_gvar *var); | ||
686 | /* Fill the attr field with info from gdb. | ||
687 | Note that attr isn't filled during creation. */ | ||
688 | int gmi_var_show_attributes(mi_h *h, mi_gvar *var); | ||
689 | /* Update variable. Use NULL for all. | ||
690 | Note that *changed can be NULL if none updated. */ | ||
691 | int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed); | ||
692 | /* Change variable. Fills the value field. */ | ||
693 | int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression); | ||
694 | /* Get current value for a variable. */ | ||
695 | int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var); | ||
696 | /* List children. It ONLY returns the first level information. :-( */ | ||
697 | int gmi_var_list_children(mi_h *h, mi_gvar *var); | ||
698 | |||
699 | #ifdef __cplusplus | ||
700 | }; | ||
701 | |||
702 | /* C++ interface */ | ||
703 | |||
704 | /* | ||
705 | State Can: | ||
706 | disconnected Connect | ||
707 | connected SelectTarget, Disconnect | ||
708 | target_specified TargetUnselect, Run, Set breakpoints/watchpoints, etc. | ||
709 | running Stop | ||
710 | stopped Kill, Restart?, Step, Trace, Continue, etc. | ||
711 | [auto exit] | ||
712 | |||
713 | Modes: | ||
714 | dmX11 Local debug for X11. | ||
715 | dmLinux Local debug for Linux console. | ||
716 | dmRemote Remote debug. | ||
717 | */ | ||
718 | class MIDebugger | ||
719 | { | ||
720 | public: | ||
721 | MIDebugger(); | ||
722 | ~MIDebugger(); | ||
723 | |||
724 | enum eState { disconnected, connected, target_specified, running, stopped }; | ||
725 | enum dMode { dmX11, dmLinux, dmRemote, dmPID }; | ||
726 | enum endianType { enUnknown, enLittle, enBig }; | ||
727 | // Currently tested architectures | ||
728 | enum archType { arUnknown, arIA32, arSPARC, arPIC14, arAVR, arUnsupported }; | ||
729 | |||
730 | int Connect(bool remote=false); /* remote is currently ignored. */ | ||
731 | int Disconnect(); | ||
732 | /* SelectTarget* */ | ||
733 | int SelectTargetX11(const char *exec, const char *args=NULL, | ||
734 | const char *auxtty=NULL); | ||
735 | int SelectTargetLinux(const char *exec, const char *args, | ||
736 | const char *auxtty=NULL); | ||
737 | int SelectTargetRemote(const char *exec, const char *rparams, | ||
738 | const char *rtype=NULL, bool download=false); | ||
739 | // TODO: Linux PIDs can be represented as intergers. What should I use? | ||
740 | // ato_pid_t doesn't exist ;-) | ||
741 | mi_frames *SelectTargetPID(const char *exec, int pid); | ||
742 | int TargetUnselect(); | ||
743 | int Run(); | ||
744 | int Stop(); | ||
745 | int Poll(mi_stop *&rs); | ||
746 | int Continue(); | ||
747 | int RunOrContinue(); | ||
748 | int Kill(); | ||
749 | mi_bkpt *Breakpoint(const char *file, int line); | ||
750 | mi_bkpt *Breakpoint(const char *where, bool temporary=false, const char *cond=NULL, | ||
751 | int count=-1, int thread=-1, bool hard_assist=false); | ||
752 | mi_bkpt *BreakpointFull(const char *file, int line, bool temporary=false, | ||
753 | const char *cond=NULL, int count=-1, int thread=-1, | ||
754 | bool hard_assist=false); | ||
755 | mi_bkpt *Breakpoint(mi_bkpt *b); | ||
756 | int BreakDelete(mi_bkpt *b); | ||
757 | int BreakAfter(mi_bkpt *b) | ||
758 | { | ||
759 | if (state!=target_specified && state!=stopped) | ||
760 | return 0; | ||
761 | return gmi_break_set_times(h,b->number,b->ignore); | ||
762 | } | ||
763 | mi_wp *Watchpoint(enum mi_wp_mode mode, const char *exp); | ||
764 | int WatchDelete(mi_wp *w); | ||
765 | int RunToMain(); | ||
766 | int StepOver(bool inst=false); | ||
767 | int TraceInto(bool inst=false); | ||
768 | int GoTo(const char *file, int line); | ||
769 | int GoTo(void *addr); | ||
770 | int FinishFun(); | ||
771 | mi_frames *ReturnNow(); | ||
772 | mi_frames *CallStack(bool args); | ||
773 | char *EvalExpression(const char *exp); | ||
774 | char *ModifyExpression(char *exp, char *newVal); | ||
775 | mi_gvar *AddgVar(const char *exp, int frame=-1) | ||
776 | { | ||
777 | if (state!=stopped) | ||
778 | return NULL; | ||
779 | return gmi_full_var_create(h,frame,exp); | ||
780 | } | ||
781 | int DelgVar(mi_gvar *var) | ||
782 | { | ||
783 | if (state!=stopped) | ||
784 | return 0; | ||
785 | return gmi_var_delete(h,var); | ||
786 | } | ||
787 | int EvalgVar(mi_gvar *var) | ||
788 | { | ||
789 | if (state!=stopped) | ||
790 | return 0; | ||
791 | return gmi_var_evaluate_expression(h,var); | ||
792 | } | ||
793 | int GetChildgVar(mi_gvar *var) | ||
794 | { | ||
795 | if (state!=stopped) | ||
796 | return 0; | ||
797 | return gmi_var_list_children(h,var); | ||
798 | } | ||
799 | int FillTypeVal(mi_gvar *var); | ||
800 | int FillOneTypeVal(mi_gvar *var); | ||
801 | int FillAttr(mi_gvar *var) | ||
802 | { | ||
803 | if (state!=stopped) | ||
804 | return 0; | ||
805 | return gmi_var_show_attributes(h,var); | ||
806 | } | ||
807 | int FillFormat(mi_gvar *var) | ||
808 | { | ||
809 | if (state!=stopped) | ||
810 | return 0; | ||
811 | return gmi_var_show_format(h,var); | ||
812 | } | ||
813 | int SetFormatgVar(mi_gvar *var, enum mi_gvar_fmt format) | ||
814 | { | ||
815 | if (state!=stopped) | ||
816 | return 0; | ||
817 | return gmi_var_set_format(h,var,format); | ||
818 | } | ||
819 | int ListChangedgVar(mi_gvar_chg *&changed) | ||
820 | { | ||
821 | if (state!=stopped) | ||
822 | return 0; | ||
823 | return gmi_var_update(h,NULL,&changed); | ||
824 | } | ||
825 | int AssigngVar(mi_gvar *var, const char *exp); | ||
826 | int Send(const char *command); | ||
827 | int Version() | ||
828 | { | ||
829 | if (state==running || state==disconnected) | ||
830 | return 0; | ||
831 | return gmi_gdb_version(h); | ||
832 | } | ||
833 | int PathSources(const char *path) | ||
834 | { | ||
835 | if (state==running || state==disconnected) | ||
836 | return 0; | ||
837 | return gmi_dir(h,path); | ||
838 | } | ||
839 | int ReadMemory(const char *exp, unsigned size, unsigned char *dest, | ||
840 | int &na, int convAddr, unsigned long *addr) | ||
841 | { | ||
842 | if (state!=stopped) | ||
843 | return 0; | ||
844 | return gmi_read_memory(h,exp,size,dest,&na,convAddr,addr); | ||
845 | } | ||
846 | char *Show(const char *var); | ||
847 | int ThreadListIDs(int *&list) | ||
848 | { | ||
849 | if (state!=stopped) | ||
850 | return 0; | ||
851 | return gmi_thread_list_ids(h,&list); | ||
852 | } | ||
853 | mi_frames *ThreadList() | ||
854 | { | ||
855 | if (state!=stopped) | ||
856 | return 0; | ||
857 | return gmi_thread_list_all_threads(h); | ||
858 | } | ||
859 | mi_frames *ThreadSelect(int id) | ||
860 | { | ||
861 | if (state!=stopped) | ||
862 | return NULL; | ||
863 | return gmi_thread_select(h,id); | ||
864 | } | ||
865 | mi_asm_insns *Disassemble(const char *start, const char *end, int mode) | ||
866 | { | ||
867 | if (state!=stopped) | ||
868 | return NULL; | ||
869 | return gmi_data_disassemble_se(h,start,end,mode); | ||
870 | } | ||
871 | mi_asm_insns *Disassemble(const char *file, int line, int lines, int mode) | ||
872 | { | ||
873 | if (state!=stopped) | ||
874 | return NULL; | ||
875 | return gmi_data_disassemble_fl(h,file,line,lines,mode); | ||
876 | } | ||
877 | mi_chg_reg *GetRegisterNames(int *how_many) | ||
878 | { | ||
879 | if (state!=target_specified && state!=stopped) | ||
880 | return NULL; | ||
881 | return gmi_data_list_register_names(h,how_many); | ||
882 | } | ||
883 | int GetRegisterNames(mi_chg_reg *chg) | ||
884 | { | ||
885 | if (state!=target_specified && state!=stopped) | ||
886 | return 0; | ||
887 | return gmi_data_list_register_names_l(h,chg); | ||
888 | } | ||
889 | int GetRegisterValues(mi_chg_reg *chg) | ||
890 | { | ||
891 | if (state!=stopped) | ||
892 | return 0; | ||
893 | return gmi_data_list_register_values(h,fm_natural,chg); | ||
894 | } | ||
895 | mi_chg_reg *GetRegisterValues(int *how_many) | ||
896 | { | ||
897 | if (state!=stopped) | ||
898 | return 0; | ||
899 | return gmi_data_list_all_register_values(h,fm_natural,how_many); | ||
900 | } | ||
901 | mi_chg_reg *GetChangedRegisters() | ||
902 | { | ||
903 | if (state!=stopped) | ||
904 | return NULL; | ||
905 | mi_chg_reg *chg=gmi_data_list_changed_registers(h); | ||
906 | if (chg && !gmi_data_list_register_values(h,fm_natural,chg)) | ||
907 | { | ||
908 | mi_free_chg_reg(chg); | ||
909 | chg=NULL; | ||
910 | } | ||
911 | return chg; | ||
912 | } | ||
913 | int UpdateRegisters(mi_chg_reg *regs); | ||
914 | |||
915 | endianType GetTargetEndian(); | ||
916 | archType GetTargetArchitecture(); | ||
917 | eState GetState() { return state; } | ||
918 | |||
919 | /* Some wrappers */ | ||
920 | static void SetGDBExe(const char *name) { mi_set_gdb_exe(name); } | ||
921 | static const char *GetGDBExe() { return mi_get_gdb_exe(); } | ||
922 | static void SetXTermExe(const char *name) { mi_set_xterm_exe(name); } | ||
923 | static const char *GetXTermExe() { return mi_get_xterm_exe(); } | ||
924 | static void SetGDBStartFile(const char *name) { mi_set_gdb_start(name); } | ||
925 | static const char *GetGDBStartFile() { return mi_get_gdb_start(); } | ||
926 | static void SetGDBConnFile(const char *name) { mi_set_gdb_conn(name); } | ||
927 | static const char *GetGDBConnFile() { return mi_get_gdb_conn(); } | ||
928 | static void SetMainFunc(const char *name) { mi_set_main_func(name); } | ||
929 | static const char *GetMainFunc() { return mi_get_main_func(); } | ||
930 | |||
931 | static const char *GetErrorStr() { return mi_get_error_str(); } | ||
932 | static const char *GetGDBError() { return mi_error_from_gdb; } | ||
933 | static int GetErrorNumber() { return mi_error; } | ||
934 | int GetErrorNumberSt(); | ||
935 | void SetConsoleCB(stream_cb cb, void *data=NULL) | ||
936 | { mi_set_console_cb(h,cb,data); } | ||
937 | void SetTargetCB(stream_cb cb, void *data=NULL) | ||
938 | { mi_set_target_cb(h,cb,data); } | ||
939 | void SetLogCB(stream_cb cb, void *data=NULL) | ||
940 | { mi_set_log_cb(h,cb,data); } | ||
941 | void SetAsyncCB(async_cb cb, void *data=NULL) | ||
942 | { mi_set_async_cb(h,cb,data); } | ||
943 | void SetToGDBCB(stream_cb cb, void *data=NULL) | ||
944 | { mi_set_to_gdb_cb(h,cb,data); } | ||
945 | void SetFromGDBCB(stream_cb cb, void *data=NULL) | ||
946 | { mi_set_from_gdb_cb(h,cb,data); } | ||
947 | void SetTimeOutCB(tm_cb cb, void *data) | ||
948 | { mi_set_time_out_cb(h,cb,data); } | ||
949 | void SetTimeOut(int to) | ||
950 | { mi_set_time_out(h,to); } | ||
951 | void ForceMIVersion(unsigned vMajor, unsigned vMiddle, unsigned vMinor) | ||
952 | { mi_force_version(h,vMajor,vMiddle,vMinor); } | ||
953 | |||
954 | const char *GetAuxTTY() | ||
955 | { return aux_tty ? aux_tty->tty : NULL; } | ||
956 | |||
957 | protected: | ||
958 | eState state; | ||
959 | dMode mode; | ||
960 | endianType targetEndian; | ||
961 | archType targetArch; | ||
962 | bool preRun; // Remote targets starts running but outside main. | ||
963 | mi_h *h; | ||
964 | mi_aux_term *aux_tty; | ||
965 | int waitingTempBkpt; | ||
966 | |||
967 | int SelectTargetTTY(const char *exec, const char *args, const char *auxtty, | ||
968 | dMode m); | ||
969 | }; | ||
970 | |||
971 | #endif | ||
972 | |||