2b2c14bdb0427403fba8217d0f1c880fc8777069
[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_NR  = '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 number breakpoint. */
90 typedef struct {
91   breakpoint   bp;       /**< the breakpoint data */
92   long         nr;       /**< the node number */
93 } bp_nr_t;
94
95 /** calculate the hash value for a node breakpoint */
96 #define HASH_NR_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_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_nr_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_numbers, &key, sizeof(key), HASH_NR_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_nr_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_numbers, &key, sizeof(key), HASH_NR_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_nr_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_numbers, &key, sizeof(key), HASH_NR_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   {
209     bp_nr_t key, *elem;
210     key.nr        = get_irg_graph_nr(irg);
211     key.bp.reason = BP_ON_REMIRG;
212
213     elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
214     if (elem && elem->bp.active) {
215       ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
216       firm_debug_break();
217     }
218   }
219   {
220     bp_ident_t key, *elem;
221     entity *ent = get_irg_entity(irg);
222
223     if (! ent)
224       return;
225
226     key.id        = get_entity_ident(ent);
227     key.bp.reason = BP_ON_REMIRG;
228
229     elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
230     if (elem && elem->bp.active) {
231       ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
232       firm_debug_break();
233     }
234   }
235 }
236
237 /**
238  * An entity was created.
239  *
240  * @param ctx   the hook context
241  * @param ent   the newly created entity
242  */
243 static void dbg_new_entity(void *ctx, entity *ent)
244 {
245   {
246     bp_ident_t key, *elem;
247
248     key.id        = get_entity_ident(ent);
249     key.bp.reason = BP_ON_NEW_ENT;
250
251     elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
252     if (elem && elem->bp.active) {
253       ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
254       firm_debug_break();
255     }
256   }
257   {
258     bp_nr_t key, *elem;
259
260     key.nr        = get_entity_nr(ent);
261     key.bp.reason = BP_ON_NEW_ENT;
262
263     elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
264     if (elem && elem->bp.active) {
265       ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
266       firm_debug_break();
267     }
268   }
269 }
270
271 /**
272  * A type was created.
273  *
274  * @param ctx   the hook context
275  * @param tp    the newly created type
276  */
277 static void dbg_new_type(void *ctx, type *tp)
278 {
279   {
280     bp_nr_t key, *elem;
281
282     key.nr        = get_type_nr(tp);
283     key.bp.reason = BP_ON_NEW_TYPE;
284
285     elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
286     if (elem && elem->bp.active) {
287       ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
288       firm_debug_break();
289     }
290   }
291   {
292     bp_ident_t key, *elem;
293
294     key.id        = get_type_ident(tp);
295     key.bp.reason = BP_ON_NEW_TYPE;
296
297     elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
298     if (elem && elem->bp.active) {
299       ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
300       firm_debug_break();
301     }
302   }
303 }
304
305 /**
306  * return the reason string.
307  */
308 static const char *reason_str(bp_reasons_t reason)
309 {
310   switch (reason) {
311   case BP_ON_NEW_NODE: return "node creation";
312   case BP_ON_REPLACE:  return "node replace";
313   case BP_ON_LOWER:    return "node lowering";
314   case BP_ON_REMIRG:   return "removing IRG";
315   case BP_ON_NEW_ENT:  return "entity creation";
316   case BP_ON_NEW_TYPE: return "type creation";
317   default:             assert(0);
318   }
319   return "unknown";
320 }
321
322 /**
323  * Compare two number breakpoints
324  */
325 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
326 {
327   const bp_nr_t *e1 = elt;
328   const bp_nr_t *e2 = key;
329
330   return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
331 }
332
333 /**
334  * Compare two ident breakpoints
335  */
336 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
337 {
338   const bp_ident_t *e1 = elt;
339   const bp_ident_t *e2 = key;
340
341   return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
342 }
343
344 /**
345  * update the hooks
346  */
347 static void update_hooks(breakpoint *bp)
348 {
349 #define CASE_ON(a, b)  case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
350 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
351
352   if (bp->active)
353     ++num_active_bp[bp->reason];
354   else
355     --num_active_bp[bp->reason];
356
357   if (num_active_bp[bp->reason] > 0) {
358     /* register the hooks on demand */
359     switch (bp->reason) {
360     CASE_ON(BP_ON_NEW_NODE, new_node);
361     CASE_ON(BP_ON_REPLACE, replace);
362     CASE_ON(BP_ON_LOWER, lower);
363     CASE_ON(BP_ON_REMIRG, free_graph);
364     CASE_ON(BP_ON_NEW_ENT, new_entity);
365     CASE_ON(BP_ON_NEW_TYPE, new_type);
366     default:
367       ;
368     }
369   }
370   else {
371     /* unregister the hook on demand */
372     switch (bp->reason) {
373     CASE_OFF(BP_ON_NEW_NODE, new_node);
374     CASE_OFF(BP_ON_REPLACE, replace);
375     CASE_OFF(BP_ON_LOWER, lower);
376     CASE_OFF(BP_ON_REMIRG, free_graph);
377     CASE_OFF(BP_ON_NEW_ENT, new_entity);
378     CASE_OFF(BP_ON_NEW_TYPE, new_type);
379     default:
380       ;
381     }
382   }
383 #undef CASE_ON
384 #undef CASE_OFF
385 }
386
387 /**
388  * Break if nr is reached.
389  */
390 static void break_on_nr(long nr, bp_reasons_t reason)
391 {
392   bp_nr_t key, *elem;
393
394   key.bp.kind   = BP_NR;
395   key.bp.bpnr   = 0;
396   key.bp.active = 1;
397   key.bp.reason = reason;
398   key.nr        = nr;
399
400   elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
401
402   if (elem->bp.bpnr == 0) {
403     /* new break point */
404     elem->bp.bpnr = ++bp_num;
405     elem->bp.next = bp_list;
406     bp_list = &elem->bp;
407
408     printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
409
410     update_hooks(&elem->bp);
411   }
412 }
413
414 /**
415  * Break if ident name is reached.
416  */
417 static void break_on_ident(const char *name, bp_reasons_t reason) {
418   bp_ident_t key, *elem;
419
420   key.bp.kind   = BP_IDENT;
421   key.bp.bpnr   = 0;
422   key.bp.active = 1;
423   key.bp.reason = reason;
424   key.id        = new_id_from_str(name);
425
426   elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
427
428   if (elem->bp.bpnr == 0) {
429     /* new break point */
430     elem->bp.bpnr = ++bp_num;
431     elem->bp.next = bp_list;
432     bp_list = &elem->bp;
433
434     printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
435
436     update_hooks(&elem->bp);
437   }
438 }
439
440 /**
441  * Sets/resets the active flag of breakpoint bp.
442  */
443 static void bp_activate(unsigned bp, int active)
444 {
445   breakpoint *p;
446
447   for (p = bp_list; p; p = p->next) {
448     if (p->bpnr == bp) {
449       if (p->active != active) {
450         p->active = active;
451         update_hooks(p);
452       }
453
454       printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
455       return;
456     }
457   }
458   printf("Error: Firm BP %u not exists.\n", bp);
459 }
460
461
462 /**
463  * Show a list of supported commands
464  */
465 static void show_commands(void) {
466   printf("Internal Firm debugger extension $Revision$ commands:\n"
467     ".init                  break after initialization\n"
468     ".create nr             break if node nr was created\n"
469     ".replace nr            break if node nr is replaced by another node\n"
470     ".lower nr              break before node nr is lowered\n"
471     ".remirg nr|name        break if the irg of nr or entity name is deleted\n"
472     ".newent nr|name        break if the entity nr or name was created\n"
473     ".newtype nr|name       break if the type nr or name was created\n"
474     ".bp                    show all breakpoints\n"
475     ".enable nr             enable breakpoint nr\n"
476     ".disable nr            disable breakpoint nr\n"
477     ".setmask name lvl      sets the debug module name to level lvl\n"
478     ".setoutfile name file  redirects debug output of module name to file\n"
479     ".help                  list all commands\n"
480   );
481 }
482
483 /**
484  * Shows all Firm breakpoints.
485  */
486 static void show_bp(void) {
487   breakpoint *p;
488   bp_nr_t  *node_p;
489   bp_ident_t *ident_p;
490
491   for (p = bp_list; p; p = p->next) {
492     printf("Firm BP %u: ", p->bpnr);
493
494     switch (p->kind) {
495     case BP_NR:
496       node_p = (bp_nr_t *)p;
497       printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
498       break;
499
500     case BP_IDENT:
501       ident_p = (bp_ident_t *)p;
502       printf("%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
503       break;
504     }
505
506     printf(p->active ? "enabled\n" : "disabled\n");
507   }
508 }
509
510 /**
511  * firm_dbg_register() expects that the name is stored persistent.
512  * So we need this little helper function
513  */
514 static firm_dbg_module_t *dbg_register(const char *name) {
515   ident *id = new_id_from_str(name);
516
517   return firm_dbg_register(get_id_str(id));
518 }
519
520 /**
521  * Sets the debug mask of module name to lvl
522  */
523 static void set_dbg_level(const char *name, unsigned lvl)
524 {
525   firm_dbg_module_t *module = dbg_register(name);
526
527   firm_dbg_set_mask(module, lvl);
528
529   printf("Setting debug mask of module %s to %u\n", name, lvl);
530 }
531
532 /**
533  * Redirects the debug output of module name to fname
534  */
535 static void set_dbg_outfile(const char *name, const char *fname)
536 {
537   firm_dbg_module_t *module = dbg_register(name);
538   FILE *f = fopen(fname, "w");
539
540   if (! f) {
541     perror(fname);
542     return;
543   }
544
545   firm_dbg_set_file(module, f);
546   printf("Redirecting debug output of module %s to file %s\n", name, fname);
547 }
548
549 /**
550  * High level function to use from debugger interface
551  *
552  * Supported commands:
553  *  .create nr    break if node nr was created
554  *  .help         list all commands
555  */
556 void firm_debug(const char *cmd) {
557   long nr;
558   unsigned bp;
559   char name[1024], fname[1024];
560   unsigned lvl;
561
562   while (isspace(*cmd)) ++cmd;
563
564   if (sscanf(cmd, ".create %ld\n", &nr) == 1) {
565     break_on_nr(nr, BP_ON_NEW_NODE);
566   }
567   else if (sscanf(cmd, ".replace %ld\n", &nr) == 1) {
568     break_on_nr(nr, BP_ON_REPLACE);
569   }
570   else if (sscanf(cmd, ".lower %ld\n", &nr) == 1) {
571     break_on_nr(nr, BP_ON_LOWER);
572   }
573   else if (sscanf(cmd, ".remirg %ld\n", &nr) == 1) {
574     break_on_nr(nr, BP_ON_REMIRG);
575   }
576   else if (sscanf(cmd, ".remirg %s\n", name) == 1) {
577     break_on_ident(name, BP_ON_REMIRG);
578   }
579   else if (sscanf(cmd, ".newent %ld\n", &nr) == 1) {
580     break_on_nr(nr, BP_ON_NEW_ENT);
581   }
582   else if (sscanf(cmd, ".newent %s\n", name) == 1) {
583     break_on_ident(name, BP_ON_NEW_ENT);
584   }
585   else if (sscanf(cmd, ".newtype %ld\n", &nr) == 1) {
586     break_on_nr(nr, BP_ON_NEW_TYPE);
587   }
588   else if (sscanf(cmd, ".newtype %s\n", name) == 1) {
589     break_on_ident(name, BP_ON_NEW_TYPE);
590   }
591   else if (strcmp(cmd, ".init") == 0)
592     break_on_init = 1;
593   else if (strcmp(cmd, ".bp") == 0)
594     show_bp();
595   else if (sscanf(cmd, ".enable %u", &bp) == 1)
596     bp_activate(bp, 1);
597   else if (sscanf(cmd, ".disable %u", &bp) == 1)
598     bp_activate(bp, 0);
599   else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2)
600     set_dbg_level(name, lvl);
601   else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2)
602     set_dbg_outfile(name, fname);
603   else {
604     show_commands();
605   }
606 }
607
608 /* creates the debugger tables */
609 void firm_init_debugger(void)
610 {
611   char *env;
612
613   bp_numbers = new_set(cmp_nr_bp, 8);
614   bp_idents       = new_set(cmp_ident_bp, 8);
615
616   env = getenv("FIRMDBG");
617
618   if (env)
619     firm_debug(env);
620
621   if (break_on_init)
622     firm_debug_break();
623 }
624
625 #endif /* NDEBUG */
626
627 /**
628  * @page debugger   The Firm debugger extension
629  *
630  * Firm contains a debugger extension. This allows to set debugger breakpoints
631  * an various events.
632  * The extension uses a text interface which can be accessed from most debuggers.
633  *
634  * @section sec_cmd Supported commands
635  *
636  * The following commands are currently supported:
637  *
638  * @b .init
639  *
640  * Break immediately after the debugger extension was initialized.
641  * Typically this command is used in the environment to stop the execution
642  * of a Firm compiler right after the initialization, like this:
643  *
644  * $export FIRMDBG=".init"
645  *
646  *
647  * @b .create nr
648  *
649  * Break if a new IR-node with node number nr was created.
650  * Typically used to find the place where wrong nodes are created.
651  *
652  * @b .replace nr
653  *
654  * Break before IR-node with node number nr is replaced by another node.
655  *
656  * @b .lower nr
657  *
658  * Break before IR-node with node number nr is lowered.
659  *
660  * @b .remirg nr
661  *
662  * Break if the irg with graph number nr is deleted.
663  *
664  * @b .remirg name
665  *
666  * Break if the irg of entity name is deleted.
667  *
668  * @b .newent nr
669  *
670  * Break if the entity with number nr was created.
671  *
672  * @b .newent name
673  *
674  * Break if the entity name was created.
675  *
676  * @b .newtype nr
677  *
678  * Break if the type with number nr was created.
679  *
680  * @b .newtype name
681  *
682  * Break if the type name was created.
683  *
684  * @b .bp
685  *
686  * Show all Firm internal breakpoints.
687  *
688  * @b .enable nr
689  *
690  * Enables breakpoint nr.
691  *
692  * @b .disable nr
693  *
694  * Disables breakpoint nr.
695  *
696  * @b .setmask name lvl
697  *
698  * Sets the debug module name to level lvl.
699  *
700  * @b .setoutfile name file
701  *
702  * Redirects debug output of module name to file\.
703  *
704  * @b .help
705  *
706  * List all commands.
707  *
708  *
709  * The Firm debugger extension can be accessed using the function firm_debug().
710  * The following example shows how to set a creation breakpoint in GDB when
711  * node 2101 is created.
712  *
713  * -# set FIRMDBG=".init"
714  * -# start gdb with your compiler
715  * -# after gdb breaks, issue
716  *
717  * p firm_debug(".create 2101")
718  *
719  * On the console the following text should be issued:
720  *
721  * Firm BP 1: creation of Node 2101
722  *
723  *
724  * @section gdb_macro GDB macro
725  *
726  * Add the following to your .gdbinit file:
727  * @code
728  #
729  # define firm "cmd"  Firm debugger extension
730  #
731  define firm
732  p firm_debug($arg0)
733  end
734  * @endcode
735  *
736  * Then, all Firm debugger extension commands can be access in the gdb
737  * console using the firm prefix, eg.:
738  *
739  * firm ".create 2101"
740  * firm ".help"
741  */
742
743 static void _firm_only_that_you_can_compile_with_NDEBUG_defined(void) {
744 }