3 * File name: ir/debug/debugger.c
4 * Purpose: Helper function for integerated debug support
9 * Copyright: (c) 2001-2005 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
19 #define WIN32_LEAN_AND_MEAN
39 #include "irgraph_t.h"
45 /* Break into the debugger. The Win32 way. */
46 void firm_debug_break(void) {
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");
55 /* Break into the debugger. Poor Unix way. */
56 void firm_debug_break(void) {
61 /** supported breakpoint kinds */
63 BP_NR = 'n', /**< break on node number. */
64 BP_IDENT = 'i' /**< break on ident. */
68 * Reasons for node number breakpoints.
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 */
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 */
89 /** A number breakpoint. */
91 breakpoint bp; /**< the breakpoint data */
92 long nr; /**< the node number */
95 /** calculate the hash value for a node breakpoint */
96 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
98 /** A ident breakpoint. */
100 breakpoint bp; /**< the breakpoint data */
101 ident *id; /**< the ident */
104 /** calculate the hash value for an ident breakpoint */
105 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
107 /** The set containing the breakpoints on node numbers. */
108 static set *bp_numbers;
110 /** The set containing the breakpoints on idents. */
111 static set *bp_idents;
113 /**< the list of all breakpoints */
114 static breakpoint *bp_list;
116 /** number of the current break point */
117 static unsigned bp_num = 0;
119 /** set if break on init command was issued. */
120 static int break_on_init = 0;
122 /** the hook entries for the Firm debugger module. */
123 static hook_entry_t debugger_hooks[hook_last];
125 /** number of active breakpoints to maintain hooks. */
126 static unsigned num_active_bp[BP_MAX_REASON];
129 * The debug message buffer
131 static char firm_dbg_msg_buf[2048];
134 * If set, the debug extension writes all output to the
135 * firm_dbg_msg_buf buffer
137 static int redir_output = 0;
140 * Is set to one, if the debug extension is active
142 static int is_active = 0;
144 /** hook the hook h with function fkt. */
145 #define HOOK(h, fkt) \
147 debugger_hooks[h].hook._##h = fkt; \
148 register_hook(h, &debugger_hooks[h]); \
151 /** unhook the hook h */
154 unregister_hook(h, &debugger_hooks[h]); \
155 debugger_hooks[h].hook._##h = NULL; \
158 /** returns non-zero if a entry hook h is used */
159 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
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)
166 /* the API version: change if needed */
167 #define FIRM_DBG_MAJOR 1
168 #define FIRM_DBG_MINOR 0
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)
176 * Returns non-zero, if the debug extension is active
178 int firm_debug_active(void) {
183 * reset the debug text buffer
185 static void reset_dbg_buf(void) {
186 firm_dbg_msg_buf[0] = '\0';
190 * Add text to the debug text buffer
192 static void add_to_dbg_buf(const char *buf) {
193 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
197 * Return the content of the debug text buffer.
199 * To be called from the debugger.
201 const char *firm_debug_text(void) {
202 return firm_dbg_msg_buf;
208 static void dbg_printf(const char *fmt, ...)
220 ir_vsnprintf(buf, sizeof(buf), fmt, args);
230 * A new node is created.
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
236 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
240 key.nr = get_irn_node_nr(node);
241 key.bp.reason = BP_ON_NEW_NODE;
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);
251 * A node is replaced.
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
257 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
261 key.nr = get_irn_node_nr(old);
262 key.bp.reason = BP_ON_REPLACE;
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);
272 * A new node is lowered.
274 * @param ctx the hook context
275 * @param node the new IR node that will be lowered
277 static void dbg_lower(void *ctx, ir_node *node)
281 key.nr = get_irn_node_nr(node);
282 key.bp.reason = BP_ON_LOWER;
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);
292 * A graph will be deleted.
294 * @param ctx the hook context
295 * @param irg the IR graph that will be deleted
297 static void dbg_free_graph(void *ctx, ir_graph *irg)
301 key.nr = get_irg_graph_nr(irg);
302 key.bp.reason = BP_ON_REMIRG;
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);
311 bp_ident_t key, *elem;
312 entity *ent = get_irg_entity(irg);
317 key.id = get_entity_ident(ent);
318 key.bp.reason = BP_ON_REMIRG;
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);
329 * An entity was created.
331 * @param ctx the hook context
332 * @param ent the newly created entity
334 static void dbg_new_entity(void *ctx, entity *ent)
337 bp_ident_t key, *elem;
339 key.id = get_entity_ident(ent);
340 key.bp.reason = BP_ON_NEW_ENT;
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);
351 key.nr = get_entity_nr(ent);
352 key.bp.reason = BP_ON_NEW_ENT;
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);
363 * A type was created.
365 * @param ctx the hook context
366 * @param tp the newly created type
368 static void dbg_new_type(void *ctx, ir_type *tp)
373 key.nr = get_type_nr(tp);
374 key.bp.reason = BP_ON_NEW_TYPE;
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);
383 bp_ident_t key, *elem;
385 key.id = get_type_ident(tp);
386 key.bp.reason = BP_ON_NEW_TYPE;
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);
397 * return the reason string.
399 static const char *reason_str(bp_reasons_t 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";
414 * Compare two number breakpoints
416 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
418 const bp_nr_t *e1 = elt;
419 const bp_nr_t *e2 = key;
421 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
425 * Compare two ident breakpoints
427 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
429 const bp_ident_t *e1 = elt;
430 const bp_ident_t *e2 = key;
432 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
438 static void update_hooks(breakpoint *bp)
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
444 ++num_active_bp[bp->reason];
446 --num_active_bp[bp->reason];
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);
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);
479 * Break if nr is reached.
481 static void break_on_nr(long nr, bp_reasons_t reason)
488 key.bp.reason = reason;
491 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
493 if (elem->bp.bpnr == 0) {
494 /* new break point */
495 elem->bp.bpnr = ++bp_num;
496 elem->bp.next = bp_list;
499 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
501 update_hooks(&elem->bp);
506 * Break if ident name is reached.
508 static void break_on_ident(const char *name, bp_reasons_t reason) {
509 bp_ident_t key, *elem;
511 key.bp.kind = BP_IDENT;
514 key.bp.reason = reason;
515 key.id = new_id_from_str(name);
517 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
519 if (elem->bp.bpnr == 0) {
520 /* new break point */
521 elem->bp.bpnr = ++bp_num;
522 elem->bp.next = bp_list;
525 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
527 update_hooks(&elem->bp);
532 * Sets/resets the active flag of breakpoint bp.
534 static void bp_activate(unsigned bp, int active)
538 for (p = bp_list; p; p = p->next) {
540 if (p->active != active) {
545 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
549 dbg_printf("Error: Firm BP %u not exists.\n", bp);
554 * Show a list of supported commands
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 lvl sets the debug module name to level lvl\n"
569 ".setoutfile name file redirects debug output of module name to file\n"
570 ".help list all commands\n"
575 * Shows all Firm breakpoints.
577 static void show_bp(void) {
583 dbg_printf("Firm Breakpoints:");
584 for (p = bp_list; p; p = p->next) {
586 dbg_printf("+\n BP %u: ", p->bpnr);
590 node_p = (bp_nr_t *)p;
591 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
595 ident_p = (bp_ident_t *)p;
596 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
600 dbg_printf(p->active ? "+enabled" : "+disabled");
602 dbg_printf(have_one ? "+\n" : "+ NONE\n");
606 * firm_dbg_register() expects that the name is stored persistent.
607 * So we need this little helper function
609 static firm_dbg_module_t *dbg_register(const char *name) {
610 ident *id = new_id_from_str(name);
612 return firm_dbg_register(get_id_str(id));
616 * Sets the debug mask of module name to lvl
618 static void set_dbg_level(const char *name, unsigned lvl)
620 firm_dbg_module_t *module = dbg_register(name);
622 firm_dbg_set_mask(module, lvl);
624 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
628 * Redirects the debug output of module name to fname
630 static void set_dbg_outfile(const char *name, const char *fname)
632 firm_dbg_module_t *module = dbg_register(name);
633 FILE *f = fopen(fname, "w");
640 firm_dbg_set_file(module, f);
641 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
645 * High level function to use from debugger interface
647 * Supported commands:
648 * .create nr break if node nr was created
649 * .help list all commands
651 void firm_debug(const char *cmd) {
654 char name[1024], fname[1024];
657 while (isspace(*cmd)) ++cmd;
659 if (sscanf(cmd, ".create %ld\n", &nr) == 1) {
660 break_on_nr(nr, BP_ON_NEW_NODE);
662 else if (sscanf(cmd, ".replace %ld\n", &nr) == 1) {
663 break_on_nr(nr, BP_ON_REPLACE);
665 else if (sscanf(cmd, ".lower %ld\n", &nr) == 1) {
666 break_on_nr(nr, BP_ON_LOWER);
668 else if (sscanf(cmd, ".remirg %ld\n", &nr) == 1) {
669 break_on_nr(nr, BP_ON_REMIRG);
671 else if (sscanf(cmd, ".remirg %s\n", name) == 1) {
672 break_on_ident(name, BP_ON_REMIRG);
674 else if (sscanf(cmd, ".newent %ld\n", &nr) == 1) {
675 break_on_nr(nr, BP_ON_NEW_ENT);
677 else if (sscanf(cmd, ".newent %s\n", name) == 1) {
678 break_on_ident(name, BP_ON_NEW_ENT);
680 else if (sscanf(cmd, ".newtype %ld\n", &nr) == 1) {
681 break_on_nr(nr, BP_ON_NEW_TYPE);
683 else if (sscanf(cmd, ".newtype %s\n", name) == 1) {
684 break_on_ident(name, BP_ON_NEW_TYPE);
686 else if (strcmp(cmd, ".init") == 0)
688 else if (strcmp(cmd, ".bp") == 0)
690 else if (sscanf(cmd, ".enable %u", &bp) == 1)
692 else if (sscanf(cmd, ".disable %u", &bp) == 1)
694 else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2)
695 set_dbg_level(name, lvl);
696 else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2)
697 set_dbg_outfile(name, fname);
703 /* creates the debugger tables */
704 void firm_init_debugger(void)
708 bp_numbers = new_set(cmp_nr_bp, 8);
709 bp_idents = new_set(cmp_ident_bp, 8);
711 env = getenv("FIRMDBG");
724 /* some picky compiler do not allow empty files */
725 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
730 * @page debugger The Firm debugger extension
732 * Firm contains a debugger extension. This allows to set debugger breakpoints
734 * The extension uses a text interface which can be accessed from most debuggers.
736 * @section sec_cmd Supported commands
738 * The following commands are currently supported:
741 * Break immediately after the debugger extension was initialized.
742 * Typically this command is used in the environment to stop the execution
743 * of a Firm compiler right after the initialization, like this:
745 * $export FIRMDBG=".init"
750 * Break if a new IR-node with node number nr was created.
751 * Typically used to find the place where wrong nodes are created.
755 * Break before IR-node with node number nr is replaced by another node.
759 * Break before IR-node with node number nr is lowered.
763 * Break if the irg with graph number nr is deleted.
767 * Break if the irg of entity name is deleted.
771 * Break if the entity with number nr was created.
775 * Break if the entity name was created.
779 * Break if the type with number nr was created.
783 * Break if the type name was created.
787 * Show all Firm internal breakpoints.
791 * Enables breakpoint nr.
795 * Disables breakpoint nr.
797 * @b .setmask name lvl
799 * Sets the debug module name to level lvl.
801 * @b .setoutfile name file
803 * Redirects debug output of module name to file.
810 * The Firm debugger extension can be accessed using the function firm_debug().
811 * The following example shows how to set a creation breakpoint in GDB when
812 * node 2101 is created.
814 * -# set FIRMDBG=".init"
815 * -# start gdb with your compiler
816 * -# after gdb breaks, issue
818 * p firm_debug(".create 2101")
820 * On the console the following text should be issued:
822 * Firm BP 1: creation of Node 2101
825 * @section gdb_macro GDB macro
827 * Add the following to your .gdbinit file:
830 # define firm "cmd" Firm debugger extension
837 * Then, all Firm debugger extension commands can be access in the gdb
838 * console using the firm prefix, eg.:
840 * firm ".create 2101"