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 static 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 static void firm_debug_break(void) {
52 __asm__ __volatile__("int3");
55 /** Break into the debugger. Poor Unix way. */
56 static 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) \
146 debugger_hooks[h].hook._##h = fkt; register_hook(h, &debugger_hooks[h])
148 /** unhook the hook h */
149 #define UNHOOK(h) unregister_hook(h, &debugger_hooks[h])
151 /** returns non-zero if a entry hook h is used */
152 #define IS_HOOKED(h) (debugger_hooks[h].next != NULL)
154 /* some macros needed to create the info string */
155 #define _DBG_VERSION(major, minor) #major "." #minor
156 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
157 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
159 /* the API version: change if needed */
160 #define FIRM_DBG_MAJOR 1
161 #define FIRM_DBG_MINOR 0
163 /** for automatic detection of the debug extension */
164 static const char *firm_debug_info_string =
165 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR)
169 * Returns non-zero, if the debug extension is active
171 int firm_debug_active(void) {
176 * reset the debug text buffer
178 static void reset_dbg_buf(void) {
179 firm_dbg_msg_buf[0] = '\0';
183 * Add text to the debug text buffer
185 static void add_to_dbg_buf(const char *buf) {
186 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
190 * Return the content of the debug text buffer.
192 * To be called from the debugger.
194 const char *firm_debug_text(void) {
195 return firm_dbg_msg_buf;
201 static void dbg_printf(const char *fmt, ...)
213 ir_vsnprintf(buf, sizeof(buf), fmt, args);
223 * A new node is created.
225 * @param ctx the hook context
226 * @param irg the IR graph on which the node is created
227 * @param node the new IR node that was created
229 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
233 key.nr = get_irn_node_nr(node);
234 key.bp.reason = BP_ON_NEW_NODE;
236 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
237 if (elem && elem->bp.active) {
238 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
244 * A node is replaced.
246 * @param ctx the hook context
247 * @param old the IR node the is replaced
248 * @param nw the new IR node that will replace old
250 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
254 key.nr = get_irn_node_nr(old);
255 key.bp.reason = BP_ON_REPLACE;
257 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
258 if (elem && elem->bp.active) {
259 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
265 * A new node is lowered.
267 * @param ctx the hook context
268 * @param node the new IR node that will be lowered
270 static void dbg_lower(void *ctx, ir_node *node)
274 key.nr = get_irn_node_nr(node);
275 key.bp.reason = BP_ON_LOWER;
277 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
278 if (elem && elem->bp.active) {
279 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
285 * A graph will be deleted.
287 * @param ctx the hook context
288 * @param irg the IR graph that will be deleted
290 static void dbg_free_graph(void *ctx, ir_graph *irg)
294 key.nr = get_irg_graph_nr(irg);
295 key.bp.reason = BP_ON_REMIRG;
297 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
298 if (elem && elem->bp.active) {
299 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
304 bp_ident_t key, *elem;
305 entity *ent = get_irg_entity(irg);
310 key.id = get_entity_ident(ent);
311 key.bp.reason = BP_ON_REMIRG;
313 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
314 if (elem && elem->bp.active) {
315 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
322 * An entity was created.
324 * @param ctx the hook context
325 * @param ent the newly created entity
327 static void dbg_new_entity(void *ctx, entity *ent)
330 bp_ident_t key, *elem;
332 key.id = get_entity_ident(ent);
333 key.bp.reason = BP_ON_NEW_ENT;
335 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
336 if (elem && elem->bp.active) {
337 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
344 key.nr = get_entity_nr(ent);
345 key.bp.reason = BP_ON_NEW_ENT;
347 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
348 if (elem && elem->bp.active) {
349 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
356 * A type was created.
358 * @param ctx the hook context
359 * @param tp the newly created type
361 static void dbg_new_type(void *ctx, type *tp)
366 key.nr = get_type_nr(tp);
367 key.bp.reason = BP_ON_NEW_TYPE;
369 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
370 if (elem && elem->bp.active) {
371 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
376 bp_ident_t key, *elem;
378 key.id = get_type_ident(tp);
379 key.bp.reason = BP_ON_NEW_TYPE;
381 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
382 if (elem && elem->bp.active) {
383 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
390 * return the reason string.
392 static const char *reason_str(bp_reasons_t reason)
395 case BP_ON_NEW_NODE: return "node creation";
396 case BP_ON_REPLACE: return "node replace";
397 case BP_ON_LOWER: return "node lowering";
398 case BP_ON_REMIRG: return "removing IRG";
399 case BP_ON_NEW_ENT: return "entity creation";
400 case BP_ON_NEW_TYPE: return "type creation";
407 * Compare two number breakpoints
409 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
411 const bp_nr_t *e1 = elt;
412 const bp_nr_t *e2 = key;
414 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
418 * Compare two ident breakpoints
420 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
422 const bp_ident_t *e1 = elt;
423 const bp_ident_t *e2 = key;
425 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
431 static void update_hooks(breakpoint *bp)
433 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
434 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
437 ++num_active_bp[bp->reason];
439 --num_active_bp[bp->reason];
441 if (num_active_bp[bp->reason] > 0) {
442 /* register the hooks on demand */
443 switch (bp->reason) {
444 CASE_ON(BP_ON_NEW_NODE, new_node);
445 CASE_ON(BP_ON_REPLACE, replace);
446 CASE_ON(BP_ON_LOWER, lower);
447 CASE_ON(BP_ON_REMIRG, free_graph);
448 CASE_ON(BP_ON_NEW_ENT, new_entity);
449 CASE_ON(BP_ON_NEW_TYPE, new_type);
455 /* unregister the hook on demand */
456 switch (bp->reason) {
457 CASE_OFF(BP_ON_NEW_NODE, new_node);
458 CASE_OFF(BP_ON_REPLACE, replace);
459 CASE_OFF(BP_ON_LOWER, lower);
460 CASE_OFF(BP_ON_REMIRG, free_graph);
461 CASE_OFF(BP_ON_NEW_ENT, new_entity);
462 CASE_OFF(BP_ON_NEW_TYPE, new_type);
472 * Break if nr is reached.
474 static void break_on_nr(long nr, bp_reasons_t reason)
481 key.bp.reason = reason;
484 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
486 if (elem->bp.bpnr == 0) {
487 /* new break point */
488 elem->bp.bpnr = ++bp_num;
489 elem->bp.next = bp_list;
492 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
494 update_hooks(&elem->bp);
499 * Break if ident name is reached.
501 static void break_on_ident(const char *name, bp_reasons_t reason) {
502 bp_ident_t key, *elem;
504 key.bp.kind = BP_IDENT;
507 key.bp.reason = reason;
508 key.id = new_id_from_str(name);
510 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
512 if (elem->bp.bpnr == 0) {
513 /* new break point */
514 elem->bp.bpnr = ++bp_num;
515 elem->bp.next = bp_list;
518 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
520 update_hooks(&elem->bp);
525 * Sets/resets the active flag of breakpoint bp.
527 static void bp_activate(unsigned bp, int active)
531 for (p = bp_list; p; p = p->next) {
533 if (p->active != active) {
538 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
542 dbg_printf("Error: Firm BP %u not exists.\n", bp);
547 * Show a list of supported commands
549 static void show_commands(void) {
550 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
551 ".init break after initialization\n"
552 ".create nr break if node nr was created\n"
553 ".replace nr break if node nr is replaced by another node\n"
554 ".lower nr break before node nr is lowered\n"
555 ".remirg nr|name break if the irg of nr or entity name is deleted\n"
556 ".newent nr|name break if the entity nr or name was created\n"
557 ".newtype nr|name break if the type nr or name was created\n"
558 ".bp show all breakpoints\n"
559 ".enable nr enable breakpoint nr\n"
560 ".disable nr disable breakpoint nr\n"
561 ".setmask name lvl sets the debug module name to level lvl\n"
562 ".setoutfile name file redirects debug output of module name to file\n"
563 ".help list all commands\n"
568 * Shows all Firm breakpoints.
570 static void show_bp(void) {
576 dbg_printf("Firm Breakpoints:");
577 for (p = bp_list; p; p = p->next) {
579 dbg_printf("+\n BP %u: ", p->bpnr);
583 node_p = (bp_nr_t *)p;
584 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
588 ident_p = (bp_ident_t *)p;
589 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
593 dbg_printf(p->active ? "+enabled" : "+disabled");
595 dbg_printf(have_one ? "+\n" : "+ NONE\n");
599 * firm_dbg_register() expects that the name is stored persistent.
600 * So we need this little helper function
602 static firm_dbg_module_t *dbg_register(const char *name) {
603 ident *id = new_id_from_str(name);
605 return firm_dbg_register(get_id_str(id));
609 * Sets the debug mask of module name to lvl
611 static void set_dbg_level(const char *name, unsigned lvl)
613 firm_dbg_module_t *module = dbg_register(name);
615 firm_dbg_set_mask(module, lvl);
617 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
621 * Redirects the debug output of module name to fname
623 static void set_dbg_outfile(const char *name, const char *fname)
625 firm_dbg_module_t *module = dbg_register(name);
626 FILE *f = fopen(fname, "w");
633 firm_dbg_set_file(module, f);
634 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
638 * High level function to use from debugger interface
640 * Supported commands:
641 * .create nr break if node nr was created
642 * .help list all commands
644 void firm_debug(const char *cmd) {
647 char name[1024], fname[1024];
650 while (isspace(*cmd)) ++cmd;
652 if (sscanf(cmd, ".create %ld\n", &nr) == 1) {
653 break_on_nr(nr, BP_ON_NEW_NODE);
655 else if (sscanf(cmd, ".replace %ld\n", &nr) == 1) {
656 break_on_nr(nr, BP_ON_REPLACE);
658 else if (sscanf(cmd, ".lower %ld\n", &nr) == 1) {
659 break_on_nr(nr, BP_ON_LOWER);
661 else if (sscanf(cmd, ".remirg %ld\n", &nr) == 1) {
662 break_on_nr(nr, BP_ON_REMIRG);
664 else if (sscanf(cmd, ".remirg %s\n", name) == 1) {
665 break_on_ident(name, BP_ON_REMIRG);
667 else if (sscanf(cmd, ".newent %ld\n", &nr) == 1) {
668 break_on_nr(nr, BP_ON_NEW_ENT);
670 else if (sscanf(cmd, ".newent %s\n", name) == 1) {
671 break_on_ident(name, BP_ON_NEW_ENT);
673 else if (sscanf(cmd, ".newtype %ld\n", &nr) == 1) {
674 break_on_nr(nr, BP_ON_NEW_TYPE);
676 else if (sscanf(cmd, ".newtype %s\n", name) == 1) {
677 break_on_ident(name, BP_ON_NEW_TYPE);
679 else if (strcmp(cmd, ".init") == 0)
681 else if (strcmp(cmd, ".bp") == 0)
683 else if (sscanf(cmd, ".enable %u", &bp) == 1)
685 else if (sscanf(cmd, ".disable %u", &bp) == 1)
687 else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2)
688 set_dbg_level(name, lvl);
689 else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2)
690 set_dbg_outfile(name, fname);
696 /* creates the debugger tables */
697 void firm_init_debugger(void)
701 bp_numbers = new_set(cmp_nr_bp, 8);
702 bp_idents = new_set(cmp_ident_bp, 8);
704 env = getenv("FIRMDBG");
717 /* some picky compiler do not allow empty files */
718 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
723 * @page debugger The Firm debugger extension
725 * Firm contains a debugger extension. This allows to set debugger breakpoints
727 * The extension uses a text interface which can be accessed from most debuggers.
729 * @section sec_cmd Supported commands
731 * The following commands are currently supported:
734 * Break immediately after the debugger extension was initialized.
735 * Typically this command is used in the environment to stop the execution
736 * of a Firm compiler right after the initialization, like this:
738 * $export FIRMDBG=".init"
743 * Break if a new IR-node with node number nr was created.
744 * Typically used to find the place where wrong nodes are created.
748 * Break before IR-node with node number nr is replaced by another node.
752 * Break before IR-node with node number nr is lowered.
756 * Break if the irg with graph number nr is deleted.
760 * Break if the irg of entity name is deleted.
764 * Break if the entity with number nr was created.
768 * Break if the entity name was created.
772 * Break if the type with number nr was created.
776 * Break if the type name was created.
780 * Show all Firm internal breakpoints.
784 * Enables breakpoint nr.
788 * Disables breakpoint nr.
790 * @b .setmask name lvl
792 * Sets the debug module name to level lvl.
794 * @b .setoutfile name file
796 * Redirects debug output of module name to file.
803 * The Firm debugger extension can be accessed using the function firm_debug().
804 * The following example shows how to set a creation breakpoint in GDB when
805 * node 2101 is created.
807 * -# set FIRMDBG=".init"
808 * -# start gdb with your compiler
809 * -# after gdb breaks, issue
811 * p firm_debug(".create 2101")
813 * On the console the following text should be issued:
815 * Firm BP 1: creation of Node 2101
818 * @section gdb_macro GDB macro
820 * Add the following to your .gdbinit file:
823 # define firm "cmd" Firm debugger extension
830 * Then, all Firm debugger extension commands can be access in the gdb
831 * console using the firm prefix, eg.:
833 * firm ".create 2101"
838 static void _firm_only_that_you_can_compile_with_NDEBUG_defined(void) __attribute__((unused));
841 static void _firm_only_that_you_can_compile_with_NDEBUG_defined(void)