renamed firm_break() to firm_debug()
[libfirm] / ir / debug / debugger.c
1 /*
2  * Project:     libFIRM
3  * File name:   ir/debug/debugger.c
4  * Purpose:     Helper function for integerated debug support
5  * Author:      Michael Beck
6  * Modified by:
7  * Created:     2005
8  * CVS-ID:      $Id$
9  * Copyright:   (c) 2001-2005 Universität Karlsruhe
10  * Licence:     This file protected by GPL -  GNU GENERAL PUBLIC LICENSE.
11  */
12 #ifdef HAVE_CONFIG_H
13 #include "config.h"
14 #endif
15
16 #ifndef NDEBUG
17
18 #ifdef _WIN32
19 #define WIN32_LEAN_AND_MEAN
20 #include <windows.h>
21 #endif
22
23 #ifdef HAVE_STDLIB_H
24 #include <stdlib.h>
25 #endif
26
27 #include <stdio.h>
28 #include <signal.h>
29
30 #ifdef HAVE_STRING_H
31 #include <string.h>
32 #endif
33
34 #include <ctype.h>
35
36 #include "set.h"
37 #include "ident.h"
38 #include "irhooks.h"
39 #include "irgraph_t.h"
40 #include "entity_t.h"
41 #include "irprintf.h"
42 #include "debug.h"
43
44 #ifdef _WIN32
45 /** Break into the debugger. The Win32 way. */
46 static void firm_debug_break(void) {
47   DebugBreak();
48 }
49 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
50 /** Break into the debugger. The ia32/x86_64 way under GCC. */
51 static void firm_debug_break(void) {
52   __asm__ __volatile__("int3");
53 }
54 #else
55 /** Break into the debugger. Poor Unix way. */
56 static void firm_debug_break(void) {
57   raise(SIGINT);
58 }
59 #endif /* _WIN32 */
60
61 /** supported breakpoint kinds */
62 typedef enum {
63   BP_NODE  = 'n',   /**< break on node number. */
64   BP_IDENT = 'i'    /**< break on ident. */
65 } bp_kind;
66
67 /**
68  * Reasons for node number breakpoints.
69  */
70 typedef enum _bp_reasons_t {
71   BP_ON_NEW_NODE,    /**< break if node with number is created */
72   BP_ON_REPLACE,     /**< break if node with number is replaced */
73   BP_ON_LOWER,       /**< break if node with number is lowered */
74   BP_ON_REMIRG,      /**< break if an IRG is removed */
75   BP_ON_NEW_ENT,     /**< break if a new entity is created */
76   BP_ON_NEW_TYPE,    /**< break if a new type is created */
77   BP_MAX_REASON
78 } bp_reasons_t;
79
80 /** A breakpoint. */
81 typedef struct _breakpoint {
82   bp_kind      kind;        /**< the kind of this break point */
83   unsigned     bpnr;        /**< break point number */
84   int          active;      /**< non-zero, if this break point is active */
85   bp_reasons_t reason;      /**< reason for the breakpoint */
86   struct _breakpoint *next; /**< link to the next one */
87 } breakpoint;
88
89 /** A node number breakpoint. */
90 typedef struct {
91   breakpoint   bp;       /**< the breakpoint data */
92   long         nr;       /**< the node number */
93 } bp_node_t;
94
95 /** calculate the hash value for a node breakpoint */
96 #define HASH_NODE_BP(key) (((key).nr << 2) ^ (key).bp.reason)
97
98 /** A ident breakpoint. */
99 typedef struct {
100   breakpoint   bp;       /**< the breakpoint data */
101   ident        *id;      /**< the ident */
102 } bp_ident_t;
103
104 /** calculate the hash value for an ident breakpoint */
105 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
106
107 /** The set containing the breakpoints on node numbers. */
108 static set *bp_node_numbers;
109
110 /** The set containing the breakpoints on idents. */
111 static set *bp_idents;
112
113 /**< the list of all breakpoints */
114 static breakpoint *bp_list;
115
116 /** number of the current break point */
117 static unsigned bp_num = 0;
118
119 /** set if break on init command was issued. */
120 static int break_on_init = 0;
121
122 /** the hook entries for the Firm debugger module. */
123 static hook_entry_t debugger_hooks[hook_last];
124
125 /** number of active breakpoints to maintain hooks. */
126 static unsigned num_active_bp[BP_MAX_REASON];
127
128 /** hook the hook h with function fkt. */
129 #define HOOK(h, fkt) \
130   debugger_hooks[h].hook._##h = fkt; register_hook(h, &debugger_hooks[h])
131
132 /** unhook the hook h */
133 #define UNHOOK(h)   unregister_hook(h, &debugger_hooks[h])
134
135 /** returns non-zero if a entry hook h is used */
136 #define IS_HOOKED(h) (debugger_hooks[h].next != NULL)
137
138 /**
139  * A new node is created.
140  *
141  * @param ctx   the hook context
142  * @param irg   the IR graph on which the node is created
143  * @param node  the new IR node that was created
144  */
145 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
146 {
147   bp_node_t key, *elem;
148
149   key.nr        = get_irn_node_nr(node);
150   key.bp.reason = BP_ON_NEW_NODE;
151
152   elem = set_find(bp_node_numbers, &key, sizeof(key), HASH_NODE_BP(key));
153   if (elem && elem->bp.active) {
154     ir_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
155     firm_debug_break();
156   }
157 }
158
159 /**
160  * A node is replaced.
161  *
162  * @param ctx   the hook context
163  * @param old   the IR node the is replaced
164  * @param nw    the new IR node that will replace old
165  */
166 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
167 {
168   bp_node_t key, *elem;
169
170   key.nr        = get_irn_node_nr(old);
171   key.bp.reason = BP_ON_REPLACE;
172
173   elem = set_find(bp_node_numbers, &key, sizeof(key), HASH_NODE_BP(key));
174   if (elem && elem->bp.active) {
175     ir_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
176     firm_debug_break();
177   }
178 }
179
180 /**
181  * A new node is lowered.
182  *
183  * @param ctx   the hook context
184  * @param node  the new IR node that will be lowered
185  */
186 static void dbg_lower(void *ctx, ir_node *node)
187 {
188   bp_node_t key, *elem;
189
190   key.nr        = get_irn_node_nr(node);
191   key.bp.reason = BP_ON_LOWER;
192
193   elem = set_find(bp_node_numbers, &key, sizeof(key), HASH_NODE_BP(key));
194   if (elem && elem->bp.active) {
195     ir_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
196     firm_debug_break();
197   }
198 }
199
200 /**
201  * A graph will be deleted.
202  *
203  * @param ctx   the hook context
204  * @param irg   the IR graph that will be deleted
205  */
206 static void dbg_free_graph(void *ctx, ir_graph *irg)
207 {
208   bp_ident_t key, *elem;
209   entity *ent = get_irg_entity(irg);
210
211   if (! ent)
212     return;
213
214   key.id        = get_entity_ident(ent);
215   key.bp.reason = BP_ON_REMIRG;
216
217   elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
218   if (elem && elem->bp.active) {
219     ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
220     firm_debug_break();
221   }
222 }
223
224 /**
225  * An entity was created.
226  *
227  * @param ctx   the hook context
228  * @param ent   the newly created entity
229  */
230 static void dbg_new_entity(void *ctx, entity *ent)
231 {
232   bp_ident_t key, *elem;
233
234   key.id        = get_entity_ident(ent);
235   key.bp.reason = BP_ON_NEW_ENT;
236
237   elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
238   if (elem && elem->bp.active) {
239     ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
240     firm_debug_break();
241   }
242 }
243
244 /**
245  * A type was created.
246  *
247  * @param ctx   the hook context
248  * @param tp    the newly created type
249  */
250 static void dbg_new_type(void *ctx, type *tp)
251 {
252   bp_ident_t key, *elem;
253
254   key.id        = get_type_ident(tp);
255   key.bp.reason = BP_ON_NEW_TYPE;
256
257   elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
258   if (elem && elem->bp.active) {
259     ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
260     firm_debug_break();
261   }
262 }
263
264 /**
265  * return the reason string.
266  */
267 static const char *reason_str(bp_reasons_t reason)
268 {
269   switch (reason) {
270   case BP_ON_NEW_NODE: return "node creation";
271   case BP_ON_REPLACE:  return "node replace";
272   case BP_ON_LOWER:    return "node lowering";
273   case BP_ON_REMIRG:   return "removing IRG";
274   case BP_ON_NEW_ENT:  return "entity creation";
275   case BP_ON_NEW_TYPE: return "type creation";
276   default:             assert(0);
277   }
278   return "unknown";
279 }
280
281 /**
282  * Compare two node number breakpoints
283  */
284 static int cmp_node_bp(const void *elt, const void *key, size_t size)
285 {
286   const bp_node_t *e1 = elt;
287   const bp_node_t *e2 = key;
288
289   return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
290 }
291
292 /**
293  * Compare two ident breakpoints
294  */
295 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
296 {
297   const bp_ident_t *e1 = elt;
298   const bp_ident_t *e2 = key;
299
300   return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
301 }
302
303 /**
304  * update the hooks
305  */
306 static void update_hooks(breakpoint *bp)
307 {
308 #define CASE_ON(a, b)  case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
309 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
310
311   if (bp->active)
312     ++num_active_bp[bp->reason];
313   else
314     --num_active_bp[bp->reason];
315
316   if (num_active_bp[bp->reason] > 0) {
317     /* register the hooks on demand */
318     switch (bp->reason) {
319     CASE_ON(BP_ON_NEW_NODE, new_node);
320     CASE_ON(BP_ON_REPLACE, replace);
321     CASE_ON(BP_ON_LOWER, lower);
322     CASE_ON(BP_ON_REMIRG, free_graph);
323     CASE_ON(BP_ON_NEW_ENT, new_entity);
324     CASE_ON(BP_ON_NEW_TYPE, new_type);
325     default:
326       ;
327     }
328   }
329   else {
330     /* unregister the hook on demand */
331     switch (bp->reason) {
332     CASE_OFF(BP_ON_NEW_NODE, new_node);
333     CASE_OFF(BP_ON_REPLACE, replace);
334     CASE_OFF(BP_ON_LOWER, lower);
335     CASE_OFF(BP_ON_REMIRG, free_graph);
336     CASE_OFF(BP_ON_NEW_ENT, new_entity);
337     CASE_OFF(BP_ON_NEW_TYPE, new_type);
338     default:
339       ;
340     }
341   }
342 #undef CASE_ON
343 #undef CASE_OFF
344 }
345
346 /**
347  * Break if node nr is reached.
348  */
349 static void break_on_node(long nr, bp_reasons_t reason)
350 {
351   bp_node_t key, *elem;
352
353   key.bp.kind   = BP_NODE;
354   key.bp.bpnr   = 0;
355   key.bp.active = 1;
356   key.bp.reason = reason;
357   key.nr        = nr;
358
359   elem = set_insert(bp_node_numbers, &key, sizeof(key), HASH_NODE_BP(key));
360
361   if (elem->bp.bpnr == 0) {
362     /* new break point */
363     elem->bp.bpnr = ++bp_num;
364     elem->bp.next = bp_list;
365     bp_list = &elem->bp;
366
367     printf("Firm BP %u: %s of Node %ld\n", elem->bp.bpnr, reason_str(reason), nr);
368
369     update_hooks(&elem->bp);
370   }
371 }
372
373 /**
374  * Break if ident name is reached.
375  */
376 static void break_on_ident(const char *name, bp_reasons_t reason) {
377   bp_ident_t key, *elem;
378
379   key.bp.kind   = BP_IDENT;
380   key.bp.bpnr   = 0;
381   key.bp.active = 1;
382   key.bp.reason = reason;
383   key.id        = new_id_from_str(name);
384
385   elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
386
387   if (elem->bp.bpnr == 0) {
388     /* new break point */
389     elem->bp.bpnr = ++bp_num;
390     elem->bp.next = bp_list;
391     bp_list = &elem->bp;
392
393     printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
394
395     update_hooks(&elem->bp);
396   }
397 }
398
399 /**
400  * Sets/resets the active flag of breakpoint bp.
401  */
402 static void bp_activate(unsigned bp, int active)
403 {
404   breakpoint *p;
405
406   for (p = bp_list; p; p = p->next) {
407     if (p->bpnr == bp) {
408       if (p->active != active) {
409         p->active = active;
410         update_hooks(p);
411       }
412
413       printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
414       return;
415     }
416   }
417   printf("Error: Firm BP %u not exists.\n", bp);
418 }
419
420
421 /**
422  * Show a list of supported commands
423  */
424 static void show_commands(void) {
425   printf("Internal Firm debugger extension $Revision$ commands:\n"
426     ".init                  break after initialization\n"
427     ".create nr             break if node nr was created\n"
428     ".replace nr            break if node nr is replaced by another node\n"
429     ".lower nr              break before node nr is lowered\n"
430     ".remirg name           break if the irg of entity name is deleted\n"
431     ".newent name           break if the entity name was created\n"
432     ".newtype name          break if the type name was created\n"
433     ".bp                    show all breakpoints\n"
434     ".enable nr             enable breakpoint nr\n"
435     ".disable nr            disable breakpoint nr\n"
436     ".setmask name lvl      sets the debug module name to level lvl\n"
437     ".setoutfile name file  redirects debug output of module name to file\n"
438     ".help                  list all commands\n"
439   );
440 }
441
442 /**
443  * Shows all Firm breakpoints.
444  */
445 static void show_bp(void) {
446   breakpoint *p;
447   bp_node_t  *node_p;
448   bp_ident_t *ident_p;
449
450   for (p = bp_list; p; p = p->next) {
451     printf("Firm BP %u: ", p->bpnr);
452
453     switch (p->kind) {
454     case BP_NODE:
455       node_p = (bp_node_t *)p;
456       printf("%s of node %ld ", reason_str(p->reason), node_p->nr);
457       break;
458
459     case BP_IDENT:
460       ident_p = (bp_ident_t *)p;
461       printf("%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
462       break;
463     }
464
465     printf(p->active ? "enabled\n" : "disabled\n");
466   }
467 }
468
469 /**
470  * firm_dbg_register() expects that the name is stored persistent.
471  * So we need this little helper function
472  */
473 static firm_dbg_module_t *dbg_register(const char *name) {
474   ident *id = new_id_from_str(name);
475
476   return firm_dbg_register(get_id_str(id));
477 }
478
479 /**
480  * Sets the debug mask of module name to lvl
481  */
482 static void set_dbg_level(const char *name, unsigned lvl)
483 {
484   firm_dbg_module_t *module = dbg_register(name);
485
486   firm_dbg_set_mask(module, lvl);
487
488   printf("Setting debug mask of module %s to %u\n", name, lvl);
489 }
490
491 /**
492  * Redirects the debug output of module name to fname
493  */
494 static void set_dbg_outfile(const char *name, const char *fname)
495 {
496   firm_dbg_module_t *module = dbg_register(name);
497   FILE *f = fopen(fname, "w");
498
499   if (! f) {
500     perror(fname);
501     return;
502   }
503
504   firm_dbg_set_file(module, f);
505   printf("Redirecting debug output of module %s to file %s\n", name, fname);
506 }
507
508 /**
509  * High level function to use from debugger interface
510  *
511  * Supported commands:
512  *  .create nr    break if node nr was created
513  *  .help         list all commands
514  */
515 void firm_debug(const char *cmd) {
516   long nr;
517   unsigned bp;
518   char name[1024], fname[1024];
519   unsigned lvl;
520
521   while (isspace(*cmd)) ++cmd;
522
523   if (sscanf(cmd, ".create %ld\n", &nr) == 1) {
524     break_on_node(nr, BP_ON_NEW_NODE);
525   }
526   else if (sscanf(cmd, ".replace %ld\n", &nr) == 1) {
527     break_on_node(nr, BP_ON_REPLACE);
528   }
529   else if (sscanf(cmd, ".lower %ld\n", &nr) == 1) {
530     break_on_node(nr, BP_ON_LOWER);
531   }
532   else if (sscanf(cmd, ".remirg %s\n", name) == 1) {
533     break_on_ident(name, BP_ON_REMIRG);
534   }
535   else if (sscanf(cmd, ".newent %s\n", name) == 1) {
536     break_on_ident(name, BP_ON_NEW_ENT);
537   }
538   else if (sscanf(cmd, ".newtype %s\n", name) == 1) {
539     break_on_ident(name, BP_ON_NEW_TYPE);
540   }
541   else if (strcmp(cmd, ".init") == 0)
542     break_on_init = 1;
543   else if (strcmp(cmd, ".bp") == 0)
544     show_bp();
545   else if (sscanf(cmd, ".enable %u", &bp) == 1)
546     bp_activate(bp, 1);
547   else if (sscanf(cmd, ".disable %u", &bp) == 1)
548     bp_activate(bp, 0);
549   else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2)
550     set_dbg_level(name, lvl);
551   else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2)
552     set_dbg_outfile(name, fname);
553   else {
554     show_commands();
555   }
556 }
557
558 /* creates the debugger tables */
559 void firm_init_debugger(void)
560 {
561   char *env;
562
563   bp_node_numbers = new_set(cmp_node_bp, 8);
564   bp_idents       = new_set(cmp_ident_bp, 8);
565
566   env = getenv("FIRMDBG");
567
568   if (env)
569     firm_debug(env);
570
571   if (break_on_init)
572     firm_debug_break();
573 }
574
575 #endif /* NDEBUG */
576
577 /**
578  * @page debugger   The Firm debugger extension
579  *
580  * Firm contains a debugger extension. This allows to set debugger breakpoints
581  * an various events.
582  * The extension uses a text interface which can be access in the debugger.
583  *
584  * @section sec_cmd Supported commands
585  *
586  * The following commands are currently supported:
587  *
588  * @b .init
589  *
590  * Break immediately after the debugger extension was initialized.
591  * Typically this command is used in the environment to stop the execution
592  * of a Firm compiler right after the initialization, like this:
593  *
594  * $export FIRMDBG=".init"
595  *
596  *
597  * @b .create nr
598  *
599  * Break if a new IR-node with node number nr was created.
600  * Typically used to find the place where wrong nodes are created.
601  *
602  * @b .replace nr
603  *
604  * Break before IR-node with node number nr is replaced by another node.
605  *
606  * @b .lower nr
607  *
608  * Break before IR-node with node number nr is lowered.
609  *
610  * @b .remirg name
611  *
612  * Break if the irg of entity name is deleted.
613  *
614  * @b .newent name
615  *
616  * Break if the entity name was created.
617  *
618  * @b .newtype name
619  *
620  * Break if the type name was created.
621  *
622  * @b .bp
623  *
624  * Show all Firm internal breakpoints.
625  *
626  * @b .enable nr
627  *
628  * Enables breakpoint nr.
629  *
630  * @b .disable nr
631  *
632  * Disables breakpoint nr.
633  *
634  * @b .setmask name lvl
635  *
636  * Sets the debug module name to level lvl.
637  *
638  * @b .setoutfile name file
639  *
640  * Redirects debug output of module name to file\.
641  *
642  * @b .help
643  *
644  * List all commands.
645  *
646  *
647  * The Firm debugger extension can be accessed using the function firm_debug().
648  * The following example shows how to set a creation breakpoint in GDB when
649  * node 2101 is created.
650  *
651  * -# set FIRMDBG=".init"
652  * -# start gdb with your compiler
653  * -# after gdb breaks, issue
654  *
655  * p firm_debug(".create 2101")
656  *
657  * On the console the following text should be issued:
658  *
659  * Firm BP 1: creation of Node 2101
660  *
661  *
662  * @section gdb_macro GDB macro
663  *
664  * Add the following to your .gdbinit file:
665  * @code
666  #
667  # define firm "cmd"  Firm debugger extension
668  #
669  define firm
670  p firm_debug($arg0)
671  end
672  * @endcode
673  *
674  * Then, all Firm debugger extension commands can be access in the gdb
675  * console using the firm prefix, eg.:
676  *
677  * firm ".create 2101"
678  * firm ".help"
679  */