Add an additional PhiM check:
[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 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 void firm_debug_break(void) {
52   __asm__ __volatile__("int3");
53 }
54 #else
55 /* Break into the debugger. Poor Unix way. */
56 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 /**
129  * The debug message buffer
130  */
131 static char firm_dbg_msg_buf[2048];
132
133 /**
134  * If set, the debug extension writes all output to the
135  * firm_dbg_msg_buf buffer
136  */
137 static int redir_output = 0;
138
139 /**
140  * Is set to one, if the debug extension is active
141  */
142 static int is_active = 0;
143
144 /** hook the hook h with function fkt. */
145 #define HOOK(h, fkt) \
146 do {                                    \
147   debugger_hooks[h].hook._##h = fkt;    \
148   register_hook(h, &debugger_hooks[h]); \
149 } while(0)
150
151 /** unhook the hook h */
152 #define UNHOOK(h) \
153 do {                                      \
154   unregister_hook(h, &debugger_hooks[h]); \
155   debugger_hooks[h].hook._##h = NULL;     \
156 } while(0)
157
158 /** returns non-zero if a entry hook h is used */
159 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
160
161 /* some macros needed to create the info string */
162 #define _DBG_VERSION(major, minor)  #major "." #minor
163 #define DBG_VERSION(major, minor)   _DBG_VERSION(major, minor)
164 #define API_VERSION(major, minor)   "API:" DBG_VERSION(major, minor)
165
166 /* the API version: change if needed */
167 #define FIRM_DBG_MAJOR  1
168 #define FIRM_DBG_MINOR  0
169
170 /** for automatic detection of the debug extension */
171 static const char *firm_debug_info_string =
172   API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR)
173   ;
174
175 /**
176  * Returns non-zero, if the debug extension is active
177  */
178 int firm_debug_active(void) {
179   return is_active;
180 }
181
182 /**
183  * reset the debug text buffer
184  */
185 static void reset_dbg_buf(void) {
186   firm_dbg_msg_buf[0] = '\0';
187 }
188
189 /**
190  * Add text to the debug text buffer
191  */
192 static void add_to_dbg_buf(const char *buf) {
193   strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
194 }
195
196 /**
197  * Return the content of the debug text buffer.
198  *
199  * To be called from the debugger.
200  */
201 const char *firm_debug_text(void) {
202   return firm_dbg_msg_buf;
203 }
204
205 /**
206  * debug output
207  */
208 static void dbg_printf(const char *fmt, ...)
209 {
210   char buf[1024];
211
212   va_list args;
213   va_start(args, fmt);
214
215   if (fmt[0] != '+')
216     reset_dbg_buf();
217   else
218     ++fmt;
219
220   ir_vsnprintf(buf, sizeof(buf), fmt, args);
221   va_end(args);
222
223   if (redir_output)
224     add_to_dbg_buf(buf);
225   else
226     puts(buf);
227 }
228
229 /**
230  * A new node is created.
231  *
232  * @param ctx   the hook context
233  * @param irg   the IR graph on which the node is created
234  * @param node  the new IR node that was created
235  */
236 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
237 {
238   bp_nr_t key, *elem;
239
240   key.nr        = get_irn_node_nr(node);
241   key.bp.reason = BP_ON_NEW_NODE;
242
243   elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
244   if (elem && elem->bp.active) {
245     dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
246     firm_debug_break();
247   }
248 }
249
250 /**
251  * A node is replaced.
252  *
253  * @param ctx   the hook context
254  * @param old   the IR node the is replaced
255  * @param nw    the new IR node that will replace old
256  */
257 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
258 {
259   bp_nr_t key, *elem;
260
261   key.nr        = get_irn_node_nr(old);
262   key.bp.reason = BP_ON_REPLACE;
263
264   elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
265   if (elem && elem->bp.active) {
266     dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
267     firm_debug_break();
268   }
269 }
270
271 /**
272  * A new node is lowered.
273  *
274  * @param ctx   the hook context
275  * @param node  the new IR node that will be lowered
276  */
277 static void dbg_lower(void *ctx, ir_node *node)
278 {
279   bp_nr_t key, *elem;
280
281   key.nr        = get_irn_node_nr(node);
282   key.bp.reason = BP_ON_LOWER;
283
284   elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
285   if (elem && elem->bp.active) {
286     dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
287     firm_debug_break();
288   }
289 }
290
291 /**
292  * A graph will be deleted.
293  *
294  * @param ctx   the hook context
295  * @param irg   the IR graph that will be deleted
296  */
297 static void dbg_free_graph(void *ctx, ir_graph *irg)
298 {
299   {
300     bp_nr_t key, *elem;
301     key.nr        = get_irg_graph_nr(irg);
302     key.bp.reason = BP_ON_REMIRG;
303
304     elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
305     if (elem && elem->bp.active) {
306       ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
307       firm_debug_break();
308     }
309   }
310   {
311     bp_ident_t key, *elem;
312     entity *ent = get_irg_entity(irg);
313
314     if (! ent)
315       return;
316
317     key.id        = get_entity_ident(ent);
318     key.bp.reason = BP_ON_REMIRG;
319
320     elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
321     if (elem && elem->bp.active) {
322       dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
323       firm_debug_break();
324     }
325   }
326 }
327
328 /**
329  * An entity was created.
330  *
331  * @param ctx   the hook context
332  * @param ent   the newly created entity
333  */
334 static void dbg_new_entity(void *ctx, entity *ent)
335 {
336   {
337     bp_ident_t key, *elem;
338
339     key.id        = get_entity_ident(ent);
340     key.bp.reason = BP_ON_NEW_ENT;
341
342     elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
343     if (elem && elem->bp.active) {
344       ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
345       firm_debug_break();
346     }
347   }
348   {
349     bp_nr_t key, *elem;
350
351     key.nr        = get_entity_nr(ent);
352     key.bp.reason = BP_ON_NEW_ENT;
353
354     elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
355     if (elem && elem->bp.active) {
356       dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
357       firm_debug_break();
358     }
359   }
360 }
361
362 /**
363  * A type was created.
364  *
365  * @param ctx   the hook context
366  * @param tp    the newly created type
367  */
368 static void dbg_new_type(void *ctx, ir_type *tp)
369 {
370   {
371     bp_nr_t key, *elem;
372
373     key.nr        = get_type_nr(tp);
374     key.bp.reason = BP_ON_NEW_TYPE;
375
376     elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
377     if (elem && elem->bp.active) {
378       ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
379       firm_debug_break();
380     }
381   }
382   {
383     bp_ident_t key, *elem;
384
385     key.id        = get_type_ident(tp);
386     key.bp.reason = BP_ON_NEW_TYPE;
387
388     elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
389     if (elem && elem->bp.active) {
390       dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
391       firm_debug_break();
392     }
393   }
394 }
395
396 /**
397  * return the reason string.
398  */
399 static const char *reason_str(bp_reasons_t reason)
400 {
401   switch (reason) {
402   case BP_ON_NEW_NODE: return "node creation";
403   case BP_ON_REPLACE:  return "node replace";
404   case BP_ON_LOWER:    return "node lowering";
405   case BP_ON_REMIRG:   return "removing IRG";
406   case BP_ON_NEW_ENT:  return "entity creation";
407   case BP_ON_NEW_TYPE: return "type creation";
408   default:             assert(0);
409   }
410   return "unknown";
411 }
412
413 /**
414  * Compare two number breakpoints
415  */
416 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
417 {
418   const bp_nr_t *e1 = elt;
419   const bp_nr_t *e2 = key;
420
421   return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
422 }
423
424 /**
425  * Compare two ident breakpoints
426  */
427 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
428 {
429   const bp_ident_t *e1 = elt;
430   const bp_ident_t *e2 = key;
431
432   return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
433 }
434
435 /**
436  * update the hooks
437  */
438 static void update_hooks(breakpoint *bp)
439 {
440 #define CASE_ON(a, b)  case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
441 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
442
443   if (bp->active)
444     ++num_active_bp[bp->reason];
445   else
446     --num_active_bp[bp->reason];
447
448   if (num_active_bp[bp->reason] > 0) {
449     /* register the hooks on demand */
450     switch (bp->reason) {
451     CASE_ON(BP_ON_NEW_NODE, new_node);
452     CASE_ON(BP_ON_REPLACE, replace);
453     CASE_ON(BP_ON_LOWER, lower);
454     CASE_ON(BP_ON_REMIRG, free_graph);
455     CASE_ON(BP_ON_NEW_ENT, new_entity);
456     CASE_ON(BP_ON_NEW_TYPE, new_type);
457     default:
458       ;
459     }
460   }
461   else {
462     /* unregister the hook on demand */
463     switch (bp->reason) {
464     CASE_OFF(BP_ON_NEW_NODE, new_node);
465     CASE_OFF(BP_ON_REPLACE, replace);
466     CASE_OFF(BP_ON_LOWER, lower);
467     CASE_OFF(BP_ON_REMIRG, free_graph);
468     CASE_OFF(BP_ON_NEW_ENT, new_entity);
469     CASE_OFF(BP_ON_NEW_TYPE, new_type);
470     default:
471       ;
472     }
473   }
474 #undef CASE_ON
475 #undef CASE_OFF
476 }
477
478 /**
479  * Break if nr is reached.
480  */
481 static void break_on_nr(long nr, bp_reasons_t reason)
482 {
483   bp_nr_t key, *elem;
484
485   key.bp.kind   = BP_NR;
486   key.bp.bpnr   = 0;
487   key.bp.active = 1;
488   key.bp.reason = reason;
489   key.nr        = nr;
490
491   elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
492
493   if (elem->bp.bpnr == 0) {
494     /* new break point */
495     elem->bp.bpnr = ++bp_num;
496     elem->bp.next = bp_list;
497     bp_list = &elem->bp;
498
499     dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
500
501     update_hooks(&elem->bp);
502   }
503 }
504
505 /**
506  * Break if ident name is reached.
507  */
508 static void break_on_ident(const char *name, bp_reasons_t reason) {
509   bp_ident_t key, *elem;
510
511   key.bp.kind   = BP_IDENT;
512   key.bp.bpnr   = 0;
513   key.bp.active = 1;
514   key.bp.reason = reason;
515   key.id        = new_id_from_str(name);
516
517   elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
518
519   if (elem->bp.bpnr == 0) {
520     /* new break point */
521     elem->bp.bpnr = ++bp_num;
522     elem->bp.next = bp_list;
523     bp_list = &elem->bp;
524
525     dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
526
527     update_hooks(&elem->bp);
528   }
529 }
530
531 /**
532  * Sets/resets the active flag of breakpoint bp.
533  */
534 static void bp_activate(unsigned bp, int active)
535 {
536   breakpoint *p;
537
538   for (p = bp_list; p; p = p->next) {
539     if (p->bpnr == bp) {
540       if (p->active != active) {
541         p->active = active;
542         update_hooks(p);
543       }
544
545       dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
546       return;
547     }
548   }
549   dbg_printf("Error: Firm BP %u not exists.\n", bp);
550 }
551
552
553 /**
554  * Show a list of supported commands
555  */
556 static void show_commands(void) {
557   dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
558     ".init                  break after initialization\n"
559     ".create nr             break if node nr was created\n"
560     ".replace nr            break if node nr is replaced by another node\n"
561     ".lower nr              break before node nr is lowered\n"
562     ".remirg nr|name        break if the irg of nr or entity name is deleted\n"
563     ".newent nr|name        break if the entity nr or name was created\n"
564     ".newtype nr|name       break if the type nr or name was created\n"
565     ".bp                    show all breakpoints\n"
566     ".enable nr             enable breakpoint nr\n"
567     ".disable nr            disable breakpoint nr\n"
568     ".setmask name msk      sets the debug module name to mask msk\n"
569     ".setlvl  name lvl      sets the debug module name to level lvl\n"
570     ".setoutfile name file  redirects debug output of module name to file\n"
571     ".help                  list all commands\n"
572   );
573 }
574
575 /**
576  * Shows all Firm breakpoints.
577  */
578 static void show_bp(void) {
579   breakpoint *p;
580   bp_nr_t  *node_p;
581   bp_ident_t *ident_p;
582   int have_one = 0;
583
584   dbg_printf("Firm Breakpoints:");
585   for (p = bp_list; p; p = p->next) {
586     have_one = 1;
587     dbg_printf("+\n  BP %u: ", p->bpnr);
588
589     switch (p->kind) {
590     case BP_NR:
591       node_p = (bp_nr_t *)p;
592       dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
593       break;
594
595     case BP_IDENT:
596       ident_p = (bp_ident_t *)p;
597       dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
598       break;
599     }
600
601     dbg_printf(p->active ? "+enabled" : "+disabled");
602   }
603   dbg_printf(have_one ? "+\n" : "+ NONE\n");
604 }
605
606 /**
607  * firm_dbg_register() expects that the name is stored persistent.
608  * So we need this little helper function
609  */
610 static firm_dbg_module_t *dbg_register(const char *name) {
611   ident *id = new_id_from_str(name);
612
613   return firm_dbg_register(get_id_str(id));
614 }
615
616 /**
617  * Sets the debug mask of module name to lvl
618  */
619 static void set_dbg_level(const char *name, unsigned lvl)
620 {
621   firm_dbg_module_t *module = dbg_register(name);
622
623   if (firm_dbg_get_mask(module) != lvl) {
624     firm_dbg_set_mask(module, lvl);
625
626     dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
627   }
628 }
629
630 /**
631  * Redirects the debug output of module name to fname
632  */
633 static void set_dbg_outfile(const char *name, const char *fname)
634 {
635   firm_dbg_module_t *module = dbg_register(name);
636   FILE *f = fopen(fname, "w");
637
638   if (! f) {
639     perror(fname);
640     return;
641   }
642
643   firm_dbg_set_file(module, f);
644   dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
645 }
646
647 /**
648  * High level function to use from debugger interface
649  *
650  * Supported commands:
651  *  .create nr    break if node nr was created
652  *  .help         list all commands
653  */
654 void firm_debug(const char *cmd) {
655   long nr;
656   unsigned bp;
657   char name[1024], fname[1024];
658   unsigned lvl;
659
660   while (isspace(*cmd)) ++cmd;
661
662   if (sscanf(cmd, ".create %ld\n", &nr) == 1) {
663     break_on_nr(nr, BP_ON_NEW_NODE);
664   }
665   else if (sscanf(cmd, ".replace %ld\n", &nr) == 1) {
666     break_on_nr(nr, BP_ON_REPLACE);
667   }
668   else if (sscanf(cmd, ".lower %ld\n", &nr) == 1) {
669     break_on_nr(nr, BP_ON_LOWER);
670   }
671   else if (sscanf(cmd, ".remirg %ld\n", &nr) == 1) {
672     break_on_nr(nr, BP_ON_REMIRG);
673   }
674   else if (sscanf(cmd, ".remirg %s\n", name) == 1) {
675     break_on_ident(name, BP_ON_REMIRG);
676   }
677   else if (sscanf(cmd, ".newent %ld\n", &nr) == 1) {
678     break_on_nr(nr, BP_ON_NEW_ENT);
679   }
680   else if (sscanf(cmd, ".newent %s\n", name) == 1) {
681     break_on_ident(name, BP_ON_NEW_ENT);
682   }
683   else if (sscanf(cmd, ".newtype %ld\n", &nr) == 1) {
684     break_on_nr(nr, BP_ON_NEW_TYPE);
685   }
686   else if (sscanf(cmd, ".newtype %s\n", name) == 1) {
687     break_on_ident(name, BP_ON_NEW_TYPE);
688   }
689   else if (strcmp(cmd, ".init") == 0)
690     break_on_init = 1;
691   else if (strcmp(cmd, ".bp") == 0)
692     show_bp();
693   else if (sscanf(cmd, ".enable %u", &bp) == 1)
694     bp_activate(bp, 1);
695   else if (sscanf(cmd, ".disable %u", &bp) == 1)
696     bp_activate(bp, 0);
697   else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2)
698     set_dbg_level(name, lvl);
699   else if (sscanf(cmd, ".setlvl %s %u\n", name, &lvl) == 2)
700     set_dbg_level(name, (1 << lvl) - 1);
701   else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2)
702     set_dbg_outfile(name, fname);
703   else {
704     show_commands();
705   }
706 }
707
708 /* creates the debugger tables */
709 void firm_init_debugger(void)
710 {
711   char *env;
712
713   bp_numbers = new_set(cmp_nr_bp, 8);
714   bp_idents  = new_set(cmp_ident_bp, 8);
715
716   env = getenv("FIRMDBG");
717
718   is_active = 1;
719
720   if (env)
721     firm_debug(env);
722
723   if (break_on_init)
724     firm_debug_break();
725 }
726
727 #else
728
729 /* some picky compiler do not allow empty files */
730 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
731
732 #endif /* NDEBUG */
733
734 /**
735  * @page debugger   The Firm debugger extension
736  *
737  * Firm contains a debugger extension. This allows to set debugger breakpoints
738  * an various events.
739  * The extension uses a text interface which can be accessed from most debuggers.
740  *
741  * @section sec_cmd Supported commands
742  *
743  * The following commands are currently supported:
744  *
745  * @b .init
746  *
747  * Break immediately after the debugger extension was initialized.
748  * Typically this command is used in the environment to stop the execution
749  * of a Firm compiler right after the initialization, like this:
750  *
751  * $export FIRMDBG=".init"
752  *
753  * @b .create nr
754  *
755  * Break if a new IR-node with node number nr was created.
756  * Typically used to find the place where wrong nodes are created.
757  *
758  * @b .replace nr
759  *
760  * Break before IR-node with node number nr is replaced by another node.
761  *
762  * @b .lower nr
763  *
764  * Break before IR-node with node number nr is lowered.
765  *
766  * @b .remirg nr
767  *
768  * Break if the irg with graph number nr is deleted.
769  *
770  * @b .remirg name
771  *
772  * Break if the irg of entity name is deleted.
773  *
774  * @b .newent nr
775  *
776  * Break if the entity with number nr was created.
777  *
778  * @b .newent name
779  *
780  * Break if the entity name was created.
781  *
782  * @b .newtype nr
783  *
784  * Break if the type with number nr was created.
785  *
786  * @b .newtype name
787  *
788  * Break if the type name was created.
789  *
790  * @b .bp
791  *
792  * Show all Firm internal breakpoints.
793  *
794  * @b .enable nr
795  *
796  * Enables breakpoint nr.
797  *
798  * @b .disable nr
799  *
800  * Disables breakpoint nr.
801  *
802  * @b .setmask name msk
803  *
804  * Sets the debug module name to mask msk.
805  *
806  * @b .setlvl name lvl
807  *
808  * Sets the debug module name to level lvl.
809  *
810  * @b .setoutfile name file
811  *
812  * Redirects debug output of module name to file.
813  *
814  * @b .help
815  *
816  * List all commands.
817  *
818  *
819  * The Firm debugger extension can be accessed using the function firm_debug().
820  * The following example shows how to set a creation breakpoint in GDB when
821  * node 2101 is created.
822  *
823  * -# set FIRMDBG=".init"
824  * -# start gdb with your compiler
825  * -# after gdb breaks, issue
826  *
827  * call firm_debug(".create 2101")
828  *
829  * On the console the following text should be issued:
830  *
831  * Firm BP 1: creation of Node 2101
832  *
833  *
834  * @section gdb_macro GDB macro
835  *
836  * Add the following to your .gdbinit file:
837  * @code
838  #
839  # define firm "cmd"  Firm debugger extension
840  #
841  define firm
842  call firm_debug($arg0)
843  end
844  * @endcode
845  *
846  * Then, all Firm debugger extension commands can be access in the gdb
847  * console using the firm prefix, eg.:
848  *
849  * firm ".create 2101"
850  *
851  * firm ".help"
852  */