1 /*
2  * Copyright (C) 2002-2009, Parrot Foundation.
3  */
4 
5 /*
6  * debugger.h
7  *
8  * Overview:
9  *    Parrot debugger header files
10  * History:
11  *      Initial version by Daniel Grunblatt on 2002.5.19
12  * Notes:
13  * References:
14  */
15 
16 #ifndef PARROT_PDB_H_GUARD
17 #define PARROT_PDB_H_GUARD
18 
19 enum {
20     PDB_NO_RUN      = 1 << 0,
21     PDB_SRC_LOADED  = 1 << 1,
22     PDB_RUNNING     = 1 << 2,
23     PDB_STOPPED     = 1 << 3,
24     PDB_BREAK       = 1 << 4, /* Set only from debug_break */
25     PDB_EXIT        = 1 << 5,
26     PDB_ENTER       = 1 << 6,
27     PDB_GCDEBUG     = 1 << 7,
28     PDB_TRACING     = 1 << 8,
29     PDB_ECHO        = 1 << 9
30 };
31 
32 enum {
33     PDB_cond_int     = 1 << 0,
34     PDB_cond_num     = 1 << 1,
35     PDB_cond_str     = 1 << 2,
36     PDB_cond_pmc     = 1 << 3,
37     PDB_cond_gt      = 1 << 4,
38     PDB_cond_ge      = 1 << 5,
39     PDB_cond_eq      = 1 << 6,
40     PDB_cond_ne      = 1 << 7,
41     PDB_cond_le      = 1 << 8,
42     PDB_cond_lt      = 1 << 9,
43     PDB_cond_const   = 1 << 10,
44     PDB_cond_notnull = 1 << 11
45 };
46 
47 /*  PDB_condition_t
48  *      Conditions for breakpoint or watchpoints.
49  *
50  *  type:           The type of condition and the way to use arguments.
51  *  reg:            The register involved, there must be at least one.
52  *  value:          A pointer to the second argument.
53  *  next:           A pointer to the next condition - used to construct a
54  *                  list of watchpoints; not used for conditional breakpoints
55  */
56 
57 typedef struct PDB_condition *PDB_condition_ptr;
58 
59 typedef struct PDB_condition {
60     unsigned short          type;
61     unsigned char           reg;
62     unsigned char           dummy;      /* For alignment XXX ??  */
63     void                    *value;     /* What neeeds to be aligned with what? */
64     PDB_condition_ptr       next;
65 } PDB_condition_t;
66 
67 /*  PDB_label_t
68  *      A label in the source file.
69  *
70  *  opcode:         The pointer to the bytecode where the label is.
71  *  number:         Number label.
72  *  next:           The next label.
73  */
74 
75 typedef struct PDB_label *PDB_label_ptr;
76 
77 typedef struct PDB_label {
78     const opcode_t         *opcode;
79     long                    number;
80     PDB_label_ptr           next;
81 } PDB_label_t;
82 
83 /*  PDB_line_t
84  *      A line in the source file.
85  *
86  *  opcode:         A pointer to the opcode in the bytecode corresponding to
87  *                  this line.
88  *  source_offset:  Offset from the source file start.
89  *  number:         Line number.
90  *  label:          The label if any.
91  *  next:           The next line (if any).
92  */
93 typedef struct PDB_line *PDB_line_ptr;
94 
95 typedef struct PDB_line {
96     opcode_t                *opcode;
97     ptrdiff_t               source_offset;
98     unsigned long           number;
99     PDB_label_t             *label;
100     PDB_line_ptr            next;
101 } PDB_line_t;
102 
103 /*  PDB_file_t
104  *      A source code file.
105  *
106  *  sourcefilename: The source code file name.
107  *  source:         The file itself.
108  *  size:           The size of the file in bytes.
109  *  list_line:      The next line to list.
110  *  line:           The first line of the source code.
111  *  label:          The first label.
112  *  next:           The next file (if any); multiple files are not currently
113  *                  supported
114  */
115 typedef struct PDB_file *PDB_file_ptr;
116 
117 typedef struct PDB_file {
118     char                    *sourcefilename;
119     char                    *source;
120     size_t                  size;
121     unsigned long           list_line;
122     PDB_line_t              *line;
123     PDB_label_t             *label;
124     PDB_file_ptr            next;
125 } PDB_file_t;
126 
127 /*  PDB_breakpoint_t
128  *      List of breakpoints.
129  *
130  *  id:             The identification number of this breakpoint
131  *  pc:             Where the breakpoint is
132  *  line:           The source file line number
133  *  skip:           The number of times to skip this breakpoint
134  *  condition:      The condition attached to the breakpoint; may be NULL
135  *  prev, next:     The previous & next breakpoints in the list; may be NULL.
136  */
137 
138 typedef struct PDB_breakpoint *PDB_breakpoint_ptr;
139 
140 typedef struct PDB_breakpoint {
141     unsigned long           id;
142     opcode_t                *pc;
143     unsigned long           line;
144     long                    skip;
145     PDB_condition_t         *condition;
146     PDB_breakpoint_ptr      prev;
147     PDB_breakpoint_ptr      next;
148 } PDB_breakpoint_t;
149 
150 /*  PDB_t
151  *      The debugger.
152  *
153  *  file:               Source code file.
154  *  breakpoint:         The first breakpoint.
155  *  watchpoint:         The first watchpoint
156  *  breakpoint_skip:    Number of breakpoints to skip.
157  *  cur_command:        The command being executed.
158  *  last_command:       Last command executed.
159  *  cur_opcode:         Current opcode.
160  *  state:              The status of the program being debugged.
161  *  debugee:            The interpreter we are debugging
162  *  debugger:           The debugger interpreter
163  */
164 
165 typedef struct PDB {
166     PDB_file_t              *file;
167     PDB_breakpoint_t        *breakpoint;
168     PDB_condition_t         *watchpoint;
169     unsigned long            breakpoint_skip;
170     char                    *cur_command;
171     char                    *last_command;
172     opcode_t                *cur_opcode;
173     int                     state;
174     Interp                  *debugee;
175     Interp                  *debugger;
176     unsigned long           tracing;
177     FILE                    *script_file;
178     unsigned long           script_line;
179 } PDB_t;
180 
181 
182 /* HEADERIZER BEGIN: src/debug.c */
183 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
184 
185 PARROT_EXPORT
186 void Parrot_debugger_break(PARROT_INTERP, ARGIN(opcode_t * cur_opcode))
187         __attribute__nonnull__(1)
188         __attribute__nonnull__(2);
189 
190 PARROT_EXPORT
191 void Parrot_debugger_destroy(PARROT_INTERP)
192         __attribute__nonnull__(1);
193 
194 PARROT_EXPORT
195 void Parrot_debugger_init(PARROT_INTERP)
196         __attribute__nonnull__(1);
197 
198 PARROT_EXPORT
199 void Parrot_debugger_load(PARROT_INTERP,
200     ARGIN_NULLOK(const STRING *filename))
201         __attribute__nonnull__(1);
202 
203 PARROT_EXPORT
204 void Parrot_debugger_start(PARROT_INTERP,
205     ARGIN_NULLOK(opcode_t * cur_opcode))
206         __attribute__nonnull__(1);
207 
208 PARROT_EXPORT
209 void PDB_backtrace(PARROT_INTERP)
210         __attribute__nonnull__(1);
211 
212 PARROT_EXPORT
213 void PDB_load_source(PARROT_INTERP, ARGIN(const char *command))
214         __attribute__nonnull__(1)
215         __attribute__nonnull__(2);
216 
217 PARROT_EXPORT
218 void PDB_print(PARROT_INTERP, ARGIN(const char *command))
219         __attribute__nonnull__(1)
220         __attribute__nonnull__(2);
221 
222 PARROT_EXPORT
223 void PDB_script_file(PARROT_INTERP, ARGIN(const char *command))
224         __attribute__nonnull__(1)
225         __attribute__nonnull__(2);
226 
227 PARROT_WARN_UNUSED_RESULT
228 PARROT_CANNOT_RETURN_NULL
229 STRING * Parrot_dbg_get_exception_backtrace(PARROT_INTERP,
230     ARGMOD(PMC * exception))
231         __attribute__nonnull__(1)
232         __attribute__nonnull__(2)
233         FUNC_MODIFIES(* exception);
234 
235 long PDB_add_label(PARROT_INTERP,
236     ARGMOD(PDB_file_t *file),
237     ARGIN(const opcode_t *cur_opcode),
238     opcode_t offset)
239         __attribute__nonnull__(1)
240         __attribute__nonnull__(2)
241         __attribute__nonnull__(3)
242         FUNC_MODIFIES(*file);
243 
244 void PDB_assign(PARROT_INTERP, ARGIN(const char *command))
245         __attribute__nonnull__(1)
246         __attribute__nonnull__(2);
247 
248 PARROT_WARN_UNUSED_RESULT
249 char PDB_break(PARROT_INTERP)
250         __attribute__nonnull__(1);
251 
252 PARROT_WARN_UNUSED_RESULT
253 char PDB_check_condition(PARROT_INTERP,
254     ARGIN(const PDB_condition_t *condition))
255         __attribute__nonnull__(1)
256         __attribute__nonnull__(2);
257 
258 PARROT_CAN_RETURN_NULL
259 PDB_condition_t * PDB_cond(PARROT_INTERP, ARGIN(const char *command))
260         __attribute__nonnull__(1)
261         __attribute__nonnull__(2);
262 
263 void PDB_continue(PARROT_INTERP, ARGIN_NULLOK(const char *command))
264         __attribute__nonnull__(1);
265 
266 void PDB_delete_breakpoint(PARROT_INTERP, ARGIN(const char *command))
267         __attribute__nonnull__(1)
268         __attribute__nonnull__(2);
269 
270 void PDB_delete_condition(PARROT_INTERP,
271     ARGMOD(PDB_breakpoint_t *breakpoint))
272         __attribute__nonnull__(1)
273         __attribute__nonnull__(2)
274         FUNC_MODIFIES(*breakpoint);
275 
276 void PDB_disable_breakpoint(PARROT_INTERP, ARGIN(const char *command))
277         __attribute__nonnull__(1)
278         __attribute__nonnull__(2);
279 
280 void PDB_disassemble(PARROT_INTERP, ARGIN_NULLOK(const char *command))
281         __attribute__nonnull__(1);
282 
283 size_t PDB_disassemble_op(PARROT_INTERP,
284     ARGOUT(char *dest),
285     size_t space,
286     ARGIN(const op_info_t *info),
287     ARGIN(const opcode_t *op),
288     ARGMOD_NULLOK(PDB_file_t *file),
289     ARGIN_NULLOK(const opcode_t *code_start),
290     int full_name)
291         __attribute__nonnull__(1)
292         __attribute__nonnull__(2)
293         __attribute__nonnull__(4)
294         __attribute__nonnull__(5)
295         FUNC_MODIFIES(*dest)
296         FUNC_MODIFIES(*file);
297 
298 void PDB_enable_breakpoint(PARROT_INTERP, ARGIN(const char *command))
299         __attribute__nonnull__(1)
300         __attribute__nonnull__(2);
301 
302 PARROT_WARN_UNUSED_RESULT
303 PARROT_CAN_RETURN_NULL
304 PARROT_MALLOC
305 char * PDB_escape(PARROT_INTERP, ARGIN(const char *string), UINTVAL length)
306         __attribute__nonnull__(1)
307         __attribute__nonnull__(2);
308 
309 void PDB_eval(PARROT_INTERP, const char *command)
310         __attribute__nonnull__(1);
311 
312 PARROT_CAN_RETURN_NULL
313 PARROT_WARN_UNUSED_RESULT
314 PDB_breakpoint_t * PDB_find_breakpoint(PARROT_INTERP,
315     ARGIN(const char *command))
316         __attribute__nonnull__(1)
317         __attribute__nonnull__(2);
318 
319 void PDB_free_file(PARROT_INTERP, ARGIN_NULLOK(PDB_file_t *file))
320         __attribute__nonnull__(1);
321 
322 void PDB_get_command(PARROT_INTERP)
323         __attribute__nonnull__(1);
324 
325 PARROT_WARN_UNUSED_RESULT
326 PARROT_PURE_FUNCTION
327 char PDB_hasinstruction(ARGIN(const char *c))
328         __attribute__nonnull__(1);
329 
330 void PDB_help(PARROT_INTERP, ARGIN(const char *command))
331         __attribute__nonnull__(1)
332         __attribute__nonnull__(2);
333 
334 void PDB_info(PARROT_INTERP)
335         __attribute__nonnull__(1);
336 
337 void PDB_init(PARROT_INTERP, ARGIN_NULLOK(const char *command))
338         __attribute__nonnull__(1);
339 
340 void PDB_list(PARROT_INTERP, ARGIN(const char *command))
341         __attribute__nonnull__(1)
342         __attribute__nonnull__(2);
343 
344 void PDB_next(PARROT_INTERP, ARGIN_NULLOK(const char *command))
345         __attribute__nonnull__(1);
346 
347 char PDB_program_end(PARROT_INTERP)
348         __attribute__nonnull__(1);
349 
350 PARROT_IGNORABLE_RESULT
351 int /*@alt void@*/
352 PDB_run_command(PARROT_INTERP,
353     ARGIN(const char *command))
354         __attribute__nonnull__(1)
355         __attribute__nonnull__(2);
356 
357 void PDB_set_break(PARROT_INTERP, ARGIN_NULLOK(const char *command))
358         __attribute__nonnull__(1);
359 
360 void PDB_skip_breakpoint(PARROT_INTERP, unsigned long i)
361         __attribute__nonnull__(1);
362 
363 void PDB_trace(PARROT_INTERP, ARGIN_NULLOK(const char *command))
364         __attribute__nonnull__(1);
365 
366 int PDB_unescape(ARGMOD(char *string))
367         __attribute__nonnull__(1)
368         FUNC_MODIFIES(*string);
369 
370 void PDB_watchpoint(PARROT_INTERP, ARGIN(const char *command))
371         __attribute__nonnull__(1)
372         __attribute__nonnull__(2);
373 
374 #define ASSERT_ARGS_Parrot_debugger_break __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
375        PARROT_ASSERT_ARG(interp) \
376     , PARROT_ASSERT_ARG(cur_opcode))
377 #define ASSERT_ARGS_Parrot_debugger_destroy __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
378        PARROT_ASSERT_ARG(interp))
379 #define ASSERT_ARGS_Parrot_debugger_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
380        PARROT_ASSERT_ARG(interp))
381 #define ASSERT_ARGS_Parrot_debugger_load __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
382        PARROT_ASSERT_ARG(interp))
383 #define ASSERT_ARGS_Parrot_debugger_start __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
384        PARROT_ASSERT_ARG(interp))
385 #define ASSERT_ARGS_PDB_backtrace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
386        PARROT_ASSERT_ARG(interp))
387 #define ASSERT_ARGS_PDB_load_source __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
388        PARROT_ASSERT_ARG(interp) \
389     , PARROT_ASSERT_ARG(command))
390 #define ASSERT_ARGS_PDB_print __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
391        PARROT_ASSERT_ARG(interp) \
392     , PARROT_ASSERT_ARG(command))
393 #define ASSERT_ARGS_PDB_script_file __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
394        PARROT_ASSERT_ARG(interp) \
395     , PARROT_ASSERT_ARG(command))
396 #define ASSERT_ARGS_Parrot_dbg_get_exception_backtrace \
397      __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
398        PARROT_ASSERT_ARG(interp) \
399     , PARROT_ASSERT_ARG(exception))
400 #define ASSERT_ARGS_PDB_add_label __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
401        PARROT_ASSERT_ARG(interp) \
402     , PARROT_ASSERT_ARG(file) \
403     , PARROT_ASSERT_ARG(cur_opcode))
404 #define ASSERT_ARGS_PDB_assign __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
405        PARROT_ASSERT_ARG(interp) \
406     , PARROT_ASSERT_ARG(command))
407 #define ASSERT_ARGS_PDB_break __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
408        PARROT_ASSERT_ARG(interp))
409 #define ASSERT_ARGS_PDB_check_condition __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
410        PARROT_ASSERT_ARG(interp) \
411     , PARROT_ASSERT_ARG(condition))
412 #define ASSERT_ARGS_PDB_cond __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
413        PARROT_ASSERT_ARG(interp) \
414     , PARROT_ASSERT_ARG(command))
415 #define ASSERT_ARGS_PDB_continue __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
416        PARROT_ASSERT_ARG(interp))
417 #define ASSERT_ARGS_PDB_delete_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
418        PARROT_ASSERT_ARG(interp) \
419     , PARROT_ASSERT_ARG(command))
420 #define ASSERT_ARGS_PDB_delete_condition __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
421        PARROT_ASSERT_ARG(interp) \
422     , PARROT_ASSERT_ARG(breakpoint))
423 #define ASSERT_ARGS_PDB_disable_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
424        PARROT_ASSERT_ARG(interp) \
425     , PARROT_ASSERT_ARG(command))
426 #define ASSERT_ARGS_PDB_disassemble __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
427        PARROT_ASSERT_ARG(interp))
428 #define ASSERT_ARGS_PDB_disassemble_op __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
429        PARROT_ASSERT_ARG(interp) \
430     , PARROT_ASSERT_ARG(dest) \
431     , PARROT_ASSERT_ARG(info) \
432     , PARROT_ASSERT_ARG(op))
433 #define ASSERT_ARGS_PDB_enable_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
434        PARROT_ASSERT_ARG(interp) \
435     , PARROT_ASSERT_ARG(command))
436 #define ASSERT_ARGS_PDB_escape __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
437        PARROT_ASSERT_ARG(interp) \
438     , PARROT_ASSERT_ARG(string))
439 #define ASSERT_ARGS_PDB_eval __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
440        PARROT_ASSERT_ARG(interp))
441 #define ASSERT_ARGS_PDB_find_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
442        PARROT_ASSERT_ARG(interp) \
443     , PARROT_ASSERT_ARG(command))
444 #define ASSERT_ARGS_PDB_free_file __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
445        PARROT_ASSERT_ARG(interp))
446 #define ASSERT_ARGS_PDB_get_command __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
447        PARROT_ASSERT_ARG(interp))
448 #define ASSERT_ARGS_PDB_hasinstruction __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
449        PARROT_ASSERT_ARG(c))
450 #define ASSERT_ARGS_PDB_help __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
451        PARROT_ASSERT_ARG(interp) \
452     , PARROT_ASSERT_ARG(command))
453 #define ASSERT_ARGS_PDB_info __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
454        PARROT_ASSERT_ARG(interp))
455 #define ASSERT_ARGS_PDB_init __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
456        PARROT_ASSERT_ARG(interp))
457 #define ASSERT_ARGS_PDB_list __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
458        PARROT_ASSERT_ARG(interp) \
459     , PARROT_ASSERT_ARG(command))
460 #define ASSERT_ARGS_PDB_next __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
461        PARROT_ASSERT_ARG(interp))
462 #define ASSERT_ARGS_PDB_program_end __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
463        PARROT_ASSERT_ARG(interp))
464 #define ASSERT_ARGS_PDB_run_command __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
465        PARROT_ASSERT_ARG(interp) \
466     , PARROT_ASSERT_ARG(command))
467 #define ASSERT_ARGS_PDB_set_break __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
468        PARROT_ASSERT_ARG(interp))
469 #define ASSERT_ARGS_PDB_skip_breakpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
470        PARROT_ASSERT_ARG(interp))
471 #define ASSERT_ARGS_PDB_trace __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
472        PARROT_ASSERT_ARG(interp))
473 #define ASSERT_ARGS_PDB_unescape __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
474        PARROT_ASSERT_ARG(string))
475 #define ASSERT_ARGS_PDB_watchpoint __attribute__unused__ int _ASSERT_ARGS_CHECK = (\
476        PARROT_ASSERT_ARG(interp) \
477     , PARROT_ASSERT_ARG(command))
478 /* Don't modify between HEADERIZER BEGIN / HEADERIZER END.  Your changes will be lost. */
479 /* HEADERIZER END: src/debug.c */
480 
481 #endif /* PARROT_PDB_H_GUARD */
482 
483 /*
484  * Local variables:
485  *   c-file-style: "parrot"
486  * End:
487  * vim: expandtab shiftwidth=4 cinoptions='\:2=2' :
488  */
489