aboutsummaryrefslogtreecommitdiff
path: root/src/monkey/gdbmi.h
blob: c03d09b614619c781ab4df1ddfbfe904bfe9c7bb (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
/**[txh]********************************************************************

  Copyright (c) 2004-2009 by Salvador E. Tropea.
  Covered by the GPL license.

  Comments:
  Main header for libmigdb.
  
***************************************************************************/

#ifndef GDBMI_H
#define GDBMI_H

#ifdef __cplusplus
extern "C"
{
#if 0                           /* keep Emacsens' auto-indent happy */
}
#endif
#endif

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h> /* pid_t */

#define MI_OK                      0
#define MI_OUT_OF_MEMORY           1
#define MI_PIPE_CREATE             2
#define MI_FORK                    3
#define MI_DEBUGGER_RUN            4
#define MI_PARSER                  5
#define MI_UNKNOWN_ASYNC           6
#define MI_UNKNOWN_RESULT          7
#define MI_FROM_GDB                8
#define MI_GDB_TIME_OUT            9
#define MI_GDB_DIED               10
#define MI_MISSING_XTERM          11
#define MI_CREATE_TEMPORAL        12
#define MI_MISSING_GDB            13
#define MI_LAST_ERROR             13

#define MI_R_NONE                  0 /* We are no waiting any response. */
#define MI_R_SKIP                  1 /* We want to discard it. */
#define MI_R_FE_AND_S              2 /* Wait for done. */
#define MI_R_E_ARGS                3

enum mi_val_type { t_const, t_tuple, t_list };

/* Types and subtypes. */
/* Type. */
#define MI_T_OUT_OF_BAND   0
#define MI_T_RESULT_RECORD 1
/* Out of band subtypes. */
#define MI_ST_ASYNC        0
#define MI_ST_STREAM       1
/* Async sub-subtypes. */
#define MI_SST_EXEC        0
#define MI_SST_STATUS      1
#define MI_SST_NOTIFY      2
/* Stream sub-subtypes. */
#define MI_SST_CONSOLE     3
#define MI_SST_TARGET      4
#define MI_SST_LOG         5
/* Classes. */
/* Async classes. */
#define MI_CL_UNKNOWN      0
#define MI_CL_STOPPED      1
#define MI_CL_DOWNLOAD     2
/* Result classes. */
#define MI_CL_DONE         2
#define MI_CL_RUNNING      3
#define MI_CL_CONNECTED    4
#define MI_CL_ERROR        5
#define MI_CL_EXIT         6

#define MI_DEFAULT_TIME_OUT 10

#define MI_DIS_ASM        0
#define MI_DIS_SRC_ASM    1

/* Implemented workaround for gdb bugs that we can dis/enable. */
/* At least gdb<=6.1.1 fails to find a source file with absolute path if the
   name is for a psym instead of a sym. psym==partially loaded symbol table. */
#define MI_PSYM_SEARCH    0

#define MI_VERSION_STR "0.8.12"
#define MI_VERSION_MAJOR  0
#define MI_VERSION_MIDDLE 8
#define MI_VERSION_MINOR  12

struct mi_results_struct
{
 char *var; /* Result name or NULL if just a value. */
 enum mi_val_type type;
 union
 {
  char *cstr;
  struct mi_results_struct *rs;
 } v;
 struct mi_results_struct *next;
};
typedef struct mi_results_struct mi_results;

struct mi_output_struct
{
 /* Type of output. */
 char type;
 char stype;
 char sstype;
 char tclass;
 /* Content. */
 mi_results *c;
 /* Always modeled as a list. */
 struct mi_output_struct *next;
};
typedef struct mi_output_struct mi_output;

typedef void (*stream_cb)(const char *, void *);
typedef void (*async_cb)(mi_output *o, void *);
typedef int  (*tm_cb)(void *);

/* Values of this structure shouldn't be manipulated by the user. */
struct mi_h_struct
{
 /* Pipes connected to gdb. */
 int to_gdb[2];
 int from_gdb[2];
 /* Streams for the pipes. */
 FILE *to, *from;
 /* PID of child gdb. */
 pid_t pid;
 char died;
 /* Which rensponse we are waiting for. */
 /*int response;*/
 /* The line we are reading. */
 char *line;
 int   llen, lread;
 /* Parsed output. */
 mi_output *po, *last;
 /* Tunneled streams callbacks. */
 stream_cb console;
 void *console_data;
 stream_cb target;
 void *target_data;
 stream_cb log;
 void *log_data;
 /* Async responses callback. */
 async_cb async;
 void *async_data;
 /* Callbacks to get echo of gdb dialog. */
 stream_cb to_gdb_echo;
 void *to_gdb_echo_data;
 stream_cb from_gdb_echo;
 void *from_gdb_echo_data;
 /* Time out */
 tm_cb time_out_cb;
 void *time_out_cb_data;
 int time_out;
 /* Ugly workaround for some of the show responses :-( */
 int catch_console;
 char *catched_console;
 /* MI version, currently unknown but the user can force v2 */
 unsigned version;
};
typedef struct mi_h_struct mi_h;

#define MI_TO(a) ((a)->to_gdb[1])

enum mi_bkp_type { t_unknown=0, t_breakpoint=1, t_hw=2 };
enum mi_bkp_disp { d_unknown=0, d_keep=1, d_del=2 };
enum mi_bkp_mode { m_file_line=0, m_function=1, m_file_function=2, m_address=3 };

struct mi_bkpt_struct
{
 int number;
 enum mi_bkp_type type;
 enum mi_bkp_disp disp; /* keep or del if temporal */
 char enabled;
 void *addr;
 char *func;
 char *file;
 int line;
 int ignore;
 int times;

 /* For the user: */
 char *cond;
 char *file_abs;
 int thread;
 enum mi_bkp_mode mode;
 struct mi_bkpt_struct *next;
};
typedef struct mi_bkpt_struct mi_bkpt;

enum mi_wp_mode { wm_unknown=0, wm_write=1, wm_read=2, wm_rw=3 };

struct mi_wp_struct
{
 int number;
 char *exp;
 enum mi_wp_mode mode;

 /* For the user: */
 struct mi_wp_struct *next;
 char enabled;
};
typedef struct mi_wp_struct mi_wp;

struct mi_frames_struct
{
 int level;  /* The frame number, 0 being the topmost frame, i.e. the innermost
                function. */
 void *addr; /* The `$pc' value for that frame. */
 char *func; /* Function name. */
 char *file; /* File name of the source file where the function lives. */
 char *from;
 int line;   /* Line number corresponding to the `$pc'. */
 /* When arguments are available: */
 mi_results *args;
 int thread_id;
 /* When more than one is provided: */
 struct mi_frames_struct *next;
};
typedef struct mi_frames_struct mi_frames;

struct mi_aux_term_struct
{
 pid_t pid;
 char *tty;
};
typedef struct mi_aux_term_struct mi_aux_term;

struct mi_pty_struct
{
 char *slave;
 int master;
};
typedef struct mi_pty_struct mi_pty;

enum mi_gvar_fmt { fm_natural=0, fm_binary=1, fm_decimal=2, fm_hexadecimal=3,
                   fm_octal=4,
                   /* Only for registers format: */
                   fm_raw=5 };
enum mi_gvar_lang { lg_unknown=0, lg_c, lg_cpp, lg_java };

#define MI_ATTR_DONT_KNOW   0
#define MI_ATTR_NONEDITABLE 1
#define MI_ATTR_EDITABLE    2

struct mi_gvar_struct
{
 char *name;
 int   numchild;
 char *type;
 enum mi_gvar_fmt format;
 enum mi_gvar_lang lang;
 char *exp;
 int   attr;

 /* MI v2 fills it, not yet implemented here. */
 /* Use gmi_var_evaluate_expression. */
 char *value;

 /* Pointer to the parent. NULL if none. */
 struct mi_gvar_struct *parent;
 /* List containing the children.
    Filled by gmi_var_list_children.
    NULL if numchild==0 or not yet filled. */
 struct mi_gvar_struct *child;
 /* Next var in the list. */
 struct mi_gvar_struct *next;

 /* For the user: */
 char opened;  /* We will show its children. 1 when we fill "child" */
 char changed; /* Needs to be updated. 0 when created. */
 int vischild; /* How many items visible. numchild when we fill "child" */
 int depth;    /* How deep is this var. */
 char ispointer;
};
typedef struct mi_gvar_struct mi_gvar;

struct mi_gvar_chg_struct
{
 char *name;
 int   in_scope;  /* if true the other fields apply. */
 char *new_type;  /* NULL if type_changed==false */
 int   new_num_children; /* only when new_type!=NULL */

 struct mi_gvar_chg_struct *next;
};
typedef struct mi_gvar_chg_struct mi_gvar_chg;


/* A list of assembler instructions. */
struct mi_asm_insn_struct
{
 void *addr;
 char *func;
 unsigned offset;
 char *inst;

 struct mi_asm_insn_struct *next;
};
typedef struct mi_asm_insn_struct mi_asm_insn;

/* A list of source lines containing assembler instructions. */
struct mi_asm_insns_struct
{
 char *file;
 int line;
 mi_asm_insn *ins;

 struct mi_asm_insns_struct *next;
};
typedef struct mi_asm_insns_struct mi_asm_insns;

/* Changed register. */
struct mi_chg_reg_struct
{
 int reg;
 char *val;
 char *name;
 char updated;

 struct mi_chg_reg_struct *next;
};
typedef struct mi_chg_reg_struct mi_chg_reg;

/*
 Examining gdb sources and looking at docs I can see the following "stop"
reasons:

Breakpoints:
a) breakpoint-hit (bkptno) + frame
Also: without reason for temporal breakpoints.

Watchpoints:
b) watchpoint-trigger (wpt={number,exp};value={old,new}) + frame
c) read-watchpoint-trigger (hw-rwpt{number,exp};value={value}) + frame
d) access-watchpoint-trigger (hw-awpt{number,exp};value={[old,]new}) + frame
e) watchpoint-scope (wpnum) + frame

Movement:
f) function-finished ([gdb-result-var,return-value]) + frame
g) location-reached + frame
h) end-stepping-range + frame

Exit:
i) exited-signalled (signal-name,signal-meaning)
j) exited (exit-code)
k) exited-normally

Signal:
l) signal-received (signal-name,signal-meaning) + frame

Plus: thread-id
*/
enum mi_stop_reason
{
 sr_unknown=0,
 sr_bkpt_hit,
 sr_wp_trigger, sr_read_wp_trigger, sr_access_wp_trigger, sr_wp_scope,
 sr_function_finished, sr_location_reached, sr_end_stepping_range,
 sr_exited_signalled, sr_exited, sr_exited_normally,
 sr_signal_received
};

struct mi_stop_struct
{
 enum mi_stop_reason reason; /* If more than one reason just the last. */
 /* Flags indicating if non-pointer fields are filled. */
 char have_thread_id;
 char have_bkptno;
 char have_exit_code;
 char have_wpno;
 /* Where stopped. Doesn't exist for sr_exited*. */
 int thread_id;
 mi_frames *frame;
 /* sr_bkpt_hit */
 int bkptno;
 /* sr_*wp_* no scope */
 mi_wp *wp;
 char *wp_old;
 char *wp_val;
 /* sr_wp_scope */
 int wpno;
 /* sr_function_finished. Not for void func. */
 char *gdb_result_var;
 char *return_value;
 /* sr_exited_signalled, sr_signal_received */
 char *signal_name;
 char *signal_meaning;
 /* sr_exited */
 int exit_code;
};
typedef struct mi_stop_struct mi_stop;

/* Variable containing the last error. */
extern int mi_error;
extern char *mi_error_from_gdb;
const char *mi_get_error_str();

/* Indicate the name of gdb exe. Default is /usr/bin/gdb */
void mi_set_gdb_exe(const char *name);
const char *mi_get_gdb_exe();
/* Indicate the name of a file containing commands to send at start-up */
void mi_set_gdb_start(const char *name);
const char *mi_get_gdb_start();
/* Indicate the name of a file containing commands to send after connection */
void mi_set_gdb_conn(const char *name);
const char *mi_get_gdb_conn();
void mi_send_target_commands(mi_h *h);
/* Connect to a local copy of gdb. */
mi_h *mi_connect_local();
/* Close connection. You should ask gdb to quit first. */
void  mi_disconnect(mi_h *h);
/* Force MI version. */
#define MI_VERSION2U(maj,mid,min) (maj*0x1000000+mid*0x10000+min)
void  mi_force_version(mi_h *h, unsigned vMajor, unsigned vMiddle,
                       unsigned vMinor);
void  mi_set_workaround(unsigned wa, int enable);
int   mi_get_workaround(unsigned wa);
/* Parse gdb output. */
mi_output *mi_parse_gdb_output(const char *str);
/* Functions to set/get the tunneled streams callbacks. */
void mi_set_console_cb(mi_h *h, stream_cb cb, void *data);
void mi_set_target_cb(mi_h *h, stream_cb cb, void *data);
void mi_set_log_cb(mi_h *h, stream_cb cb, void *data);
stream_cb mi_get_console_cb(mi_h *h, void **data);
stream_cb mi_get_target_cb(mi_h *h, void **data);
stream_cb mi_get_log_cb(mi_h *h, void **data);
/* The callback to deal with async events. */
void mi_set_async_cb(mi_h *h, async_cb cb, void *data);
async_cb mi_get_async_cb(mi_h *h, void **data);
/* Time out in gdb responses. */
void mi_set_time_out_cb(mi_h *h, tm_cb cb, void *data);
tm_cb mi_get_time_out_cb(mi_h *h, void **data);
void mi_set_time_out(mi_h *h, int to);
int mi_get_time_out(mi_h *h);
/* Callbacks to "see" the dialog with gdb. */
void mi_set_to_gdb_cb(mi_h *h, stream_cb cb, void *data);
void mi_set_from_gdb_cb(mi_h *h, stream_cb cb, void *data);
stream_cb mi_get_to_gdb_cb(mi_h *h, void **data);
stream_cb mi_get_from_gdb_cb(mi_h *h, void **data);
/* Sends a message to gdb. */
int mi_send(mi_h *h, const char *format, ...);
/* Wait until gdb sends a response. */
mi_output *mi_get_response_blk(mi_h *h);
/* Check if gdb sent a complete response. Use with mi_retire_response. */
int mi_get_response(mi_h *h);
/* Get the last response. Use with mi_get_response. */
mi_output *mi_retire_response(mi_h *h);
/* Look for a result record in gdb output. */
mi_output *mi_get_rrecord(mi_output *r);
/* Look if the output contains an async stop.
   If that's the case return the reason for the stop.
   If the output contains an error the description is returned in reason. */
int mi_get_async_stop_reason(mi_output *r, char **reason);
mi_stop *mi_get_stopped(mi_results *r);
mi_frames *mi_get_async_frame(mi_output *r);
/* Wait until gdb sends a response.
   Then check if the response is of the desired type. */
int mi_res_simple_exit(mi_h *h);
int mi_res_simple_done(mi_h *h);
int mi_res_simple_running(mi_h *h);
int mi_res_simple_connected(mi_h *h);
/* It additionally extracts an specified variable. */
mi_results *mi_res_done_var(mi_h *h, const char *var);
/* Extract a frames list from the response. */
mi_frames *mi_res_frames_array(mi_h *h, const char *var);
mi_frames *mi_res_frames_list(mi_h *h);
mi_frames *mi_parse_frame(mi_results *c);
mi_frames *mi_res_frame(mi_h *h);
/* Create an auxiliar terminal using xterm. */
mi_aux_term *gmi_start_xterm();
/* Indicate the name of xterm exe. Default is /usr/bin/X11/xterm */
void mi_set_xterm_exe(const char *name);
const char *mi_get_xterm_exe();
/* Kill the auxiliar terminal and release the structure. */
void gmi_end_aux_term(mi_aux_term *t);
/* Look for a free Linux VT for the child. */
mi_aux_term *gmi_look_for_free_vt();
/* Look for a free and usable Linux VT. */
int mi_look_for_free_vt();
/* Close master and release the structure. */
void gmi_end_pty(mi_pty *p);
/* Look for a free pseudo terminal. */
mi_pty *gmi_look_for_free_pty();
/* Extract a list of thread IDs from response. */
int mi_res_thread_ids(mi_h *h, int **list);
int mi_get_thread_ids(mi_output *res, int **list);
/* A variable response. */
mi_gvar *mi_res_gvar(mi_h *h, mi_gvar *cur, const char *expression);
enum mi_gvar_fmt mi_format_str_to_enum(const char *format);
const char *mi_format_enum_to_str(enum mi_gvar_fmt format);
char mi_format_enum_to_char(enum mi_gvar_fmt format);
enum mi_gvar_lang mi_lang_str_to_enum(const char *lang);
const char *mi_lang_enum_to_str(enum mi_gvar_lang lang);
int mi_res_changelist(mi_h *h, mi_gvar_chg **changed);
int mi_res_children(mi_h *h, mi_gvar *v);
mi_bkpt *mi_res_bkpt(mi_h *h);
mi_wp *mi_res_wp(mi_h *h);
char *mi_res_value(mi_h *h);
mi_stop *mi_res_stop(mi_h *h);
enum mi_stop_reason mi_reason_str_to_enum(const char *s);
const char *mi_reason_enum_to_str(enum mi_stop_reason r);
int mi_get_read_memory(mi_h *h, unsigned char *dest, unsigned ws, int *na,
                       unsigned long *addr);
mi_asm_insns *mi_get_asm_insns(mi_h *h);
/* Starting point of the program. */
void mi_set_main_func(const char *name);
const char *mi_get_main_func();
mi_chg_reg *mi_get_list_registers(mi_h *h, int *how_many);
int mi_get_list_registers_l(mi_h *h, mi_chg_reg *l);
mi_chg_reg *mi_get_list_changed_regs(mi_h *h);
int mi_get_reg_values(mi_h *h, mi_chg_reg *l);
mi_chg_reg *mi_get_reg_values_l(mi_h *h, int *how_many);
int gmi_target_download(mi_h *h);

/* Allocation functions: */
void *mi_calloc(size_t count, size_t sz);
void *mi_calloc1(size_t sz);
char *mi_malloc(size_t sz);
mi_results       *mi_alloc_results(void);
mi_output        *mi_alloc_output(void);
mi_frames        *mi_alloc_frames(void);
mi_gvar          *mi_alloc_gvar(void);
mi_gvar_chg      *mi_alloc_gvar_chg(void);
mi_bkpt          *mi_alloc_bkpt(void);
mi_wp            *mi_alloc_wp(void);
mi_stop          *mi_alloc_stop(void);
mi_asm_insns     *mi_alloc_asm_insns(void);
mi_asm_insn      *mi_alloc_asm_insn(void);
mi_chg_reg       *mi_alloc_chg_reg(void);
void mi_free_output(mi_output *r);
void mi_free_output_but(mi_output *r, mi_output *no, mi_results *no_r);
void mi_free_frames(mi_frames *f);
void mi_free_aux_term(mi_aux_term *t);
void mi_free_results(mi_results *r);
void mi_free_results_but(mi_results *r, mi_results *no);
void mi_free_gvar(mi_gvar *v);
void mi_free_gvar_chg(mi_gvar_chg *p);
void mi_free_wp(mi_wp *wp);
void mi_free_stop(mi_stop *s);
void mi_free_asm_insns(mi_asm_insns *i);
void mi_free_asm_insn(mi_asm_insn *i);
void mi_free_charp_list(char **l);
void mi_free_chg_reg(mi_chg_reg *r);

/* Porgram control: */
/* Specify the executable and arguments for local debug. */
int gmi_set_exec(mi_h *h, const char *file, const char *args);
/* Start running the executable. Remote sessions starts running. */
int gmi_exec_run(mi_h *h);
/* Continue the execution after a "stop". */
int gmi_exec_continue(mi_h *h);
/* Indicate which terminal will use the target program. For local sessions. */
int gmi_target_terminal(mi_h *h, const char *tty_name);
/* Specify what's the local copy that have debug info. For remote sessions. */
int gmi_file_symbol_file(mi_h *h, const char *file);
/* Continue until function return, the return value is included in the async
   response. */
int gmi_exec_finish(mi_h *h);
/* Stop the program using SIGINT. */
int gmi_exec_interrupt(mi_h *h);
/* Next line of code. */
int gmi_exec_next(mi_h *h);
/* Next count lines of code. */
int gmi_exec_next_cnt(mi_h *h, int count);
/* Next line of assembler code. */
int gmi_exec_next_instruction(mi_h *h);
/* Next line of code. Get inside functions. */
int gmi_exec_step(mi_h *h);
/* Next count lines of code. Get inside functions. */
int gmi_exec_step_cnt(mi_h *h, int count);
/* Next line of assembler code. Get inside calls. */
int gmi_exec_step_instruction(mi_h *h);
/* Execute until location is reached. If file is NULL then is until next line. */
int gmi_exec_until(mi_h *h, const char *file, int line);
int gmi_exec_until_addr(mi_h *h, void *addr);
/* Return to previous frame inmediatly. */
mi_frames *gmi_exec_return(mi_h *h);
/* Just kill the program. Please read the notes in prg_control.c. */
int gmi_exec_kill(mi_h *h);

/* Target manipulation: */
/* Connect to a remote gdbserver using the specified methode. */
int gmi_target_select(mi_h *h, const char *type, const char *params);
/* Attach to an already running process. */
mi_frames *gmi_target_attach(mi_h *h, pid_t pid);
/* Detach from an attached process. */
int gmi_target_detach(mi_h *h);

/* Miscellaneous commands: */
/* Exit gdb killing the child is it is running. */
void gmi_gdb_exit(mi_h *h);
/* Send the version to the console. */
int gmi_gdb_version(mi_h *h);
/* Set a gdb variable. */
int gmi_gdb_set(mi_h *h, const char *var, const char *val);
/* Get a gdb variable. */
char *gmi_gdb_show(mi_h *h, const char *var);

/* Breakpoints manipulation: */
/* Insert a breakpoint at file:line. */
mi_bkpt *gmi_break_insert(mi_h *h, const char *file, int line);
/* Insert a breakpoint, all available options. */
mi_bkpt *gmi_break_insert_full(mi_h *h, int temporary, int hard_assist,
                               const char *cond, int count, int thread,
                               const char *where);
mi_bkpt *gmi_break_insert_full_fl(mi_h *h, const char *file, int line,
                                  int temporary, int hard_assist,
                                  const char *cond, int count, int thread);
/* Remove a breakpoint. */
int gmi_break_delete(mi_h *h, int number);
/* Free the memory used for a breakpoint description. */
void mi_free_bkpt(mi_bkpt *b);
/* Modify the "ignore" count for a breakpoint. */
int gmi_break_set_times(mi_h *h, int number, int count);
/* Associate a condition with the breakpoint. */
int gmi_break_set_condition(mi_h *h, int number, const char *condition);
/* Enable or disable a breakpoint. */
int gmi_break_state(mi_h *h, int number, int enable);
/* Set a watchpoint. It doesn't work for remote targets! */
mi_wp *gmi_break_watch(mi_h *h, enum mi_wp_mode mode, const char *exp);

/* Data Manipulation. */
/* Evaluate an expression. Returns a parsed tree. */
char *gmi_data_evaluate_expression(mi_h *h, const char *expression);
/* Path for sources. */
int gmi_dir(mi_h *h, const char *path);
/* A very limited "data read memory" implementation. */
int gmi_read_memory(mi_h *h, const char *exp, unsigned size,
                    unsigned char *dest, int *na, int convAddr,
                    unsigned long *addr);
mi_asm_insns *gmi_data_disassemble_se(mi_h *h, const char *start,
                                      const char *end, int mode);
mi_asm_insns *gmi_data_disassemble_fl(mi_h *h, const char *file, int line,
                                      int lines, int mode);
mi_chg_reg *gmi_data_list_register_names(mi_h *h, int *how_many);
int gmi_data_list_register_names_l(mi_h *h, mi_chg_reg *l);
mi_chg_reg *gmi_data_list_changed_registers(mi_h *h);
int gmi_data_list_register_values(mi_h *h, enum mi_gvar_fmt fmt, mi_chg_reg *l);
mi_chg_reg *gmi_data_list_all_register_values(mi_h *h, enum mi_gvar_fmt fmt, int *how_many);

/* Stack manipulation. */
/* List of frames. Arguments aren't filled. */
mi_frames *gmi_stack_list_frames(mi_h *h);
/* List of frames. Indicating a range. */
mi_frames *gmi_stack_list_frames_r(mi_h *h, int from, int to);
/* List arguments. Only level and args filled. */
mi_frames *gmi_stack_list_arguments(mi_h *h, int show);
/* List arguments. Indicating a range. Only level and args filled. */
mi_frames *gmi_stack_list_arguments_r(mi_h *h, int show, int from, int to);
/* Information about the current frame, including args. */
mi_frames *gmi_stack_info_frame(mi_h *h);
/* Stack info depth. error => -1 */
int gmi_stack_info_depth_get(mi_h *h);
/* Set stack info depth. error => -1 */
int gmi_stack_info_depth(mi_h *h, int max_depth);
/* Change current frame. */
int gmi_stack_select_frame(mi_h *h, int framenum);
/* List of local vars. */
mi_results *gmi_stack_list_locals(mi_h *h, int show);

/* Thread. */
/* List available thread ids. */
int gmi_thread_list_ids(mi_h *h, int **list);
/* Select a thread. */
mi_frames *gmi_thread_select(mi_h *h, int id);
/* List available threads. */
mi_frames *gmi_thread_list_all_threads(mi_h *h);

/* Variable objects. */
/* Create a variable object. */
mi_gvar *gmi_var_create_nm(mi_h *h, const char *name, int frame, const char *exp);
mi_gvar *gmi_var_create(mi_h *h, int frame, const char *exp);
/* Create the variable and also fill the lang and attr fields. */
mi_gvar *gmi_full_var_create(mi_h *h, int frame, const char *exp);
/* Delete a variable object. Doesn't free the mi_gvar data. */
int gmi_var_delete(mi_h *h, mi_gvar *var);
/* Set the format used to represent the result. */
int gmi_var_set_format(mi_h *h, mi_gvar *var, enum mi_gvar_fmt format);
/* Fill the format field with info from gdb. */
int gmi_var_show_format(mi_h *h, mi_gvar *var);
/* Fill the numchild field with info from gdb. */
int gmi_var_info_num_children(mi_h *h, mi_gvar *var);
/* Fill the type field with info from gdb. */
int gmi_var_info_type(mi_h *h, mi_gvar *var);
/* Fill the expression and lang fields with info from gdb.
   Note that lang isn't filled during creation. */
int gmi_var_info_expression(mi_h *h, mi_gvar *var);
/* Fill the attr field with info from gdb.
   Note that attr isn't filled during creation. */
int gmi_var_show_attributes(mi_h *h, mi_gvar *var);
/* Update variable. Use NULL for all.
   Note that *changed can be NULL if none updated. */
int gmi_var_update(mi_h *h, mi_gvar *var, mi_gvar_chg **changed);
/* Change variable. Fills the value field. */
int gmi_var_assign(mi_h *h, mi_gvar *var, const char *expression);
/* Get current value for a variable. */
int gmi_var_evaluate_expression(mi_h *h, mi_gvar *var);
/* List children. It ONLY returns the first level information. :-( */
int gmi_var_list_children(mi_h *h, mi_gvar *var);




#if 0                           /* keep Emacsens' auto-indent happy */
{
#endif
#ifdef __cplusplus
}
#endif

#endif