2 * This file is part of libFirm.
3 * Copyright (C) 2012 University of Karlsruhe.
8 * @brief Helper function for integrated debug support
17 #define WIN32_LEAN_AND_MEAN
35 #include "irgraph_t.h"
39 #include "iredges_t.h"
45 /* Break into the debugger. The Win32 way. */
46 void firm_debug_break(void)
50 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
51 /* Break into the debugger. The ia32/x86_64 way under GCC. */
52 void firm_debug_break(void)
54 __asm__ __volatile__("int3");
57 /* Break into the debugger. Poor Unix way. */
58 void firm_debug_break(void)
64 /** supported breakpoint kinds */
66 BP_NR = 'n', /**< break on node number. */
67 BP_IDENT = 'i' /**< break on ident. */
71 * Reasons for node number breakpoints.
73 typedef enum bp_reasons_t {
74 BP_ON_NEW_THING, /**< break if node, entity or type with number is created */
75 BP_ON_REPLACE, /**< break if node with number is replaced */
76 BP_ON_LOWER, /**< break if node with number is lowered */
77 BP_ON_REMIRG, /**< break if an IRG is removed */
78 BP_ON_NEW_ENT, /**< break if a new entity is created */
83 typedef struct breakpoint {
84 bp_kind kind; /**< the kind of this break point */
85 unsigned bpnr; /**< break point number */
86 int active; /**< non-zero, if this break point is active */
87 bp_reasons_t reason; /**< reason for the breakpoint */
88 struct breakpoint *next; /**< link to the next one */
91 /** A number breakpoint. */
93 breakpoint bp; /**< the breakpoint data */
94 long nr; /**< the node number */
97 /** Calculate the hash value for a node breakpoint. */
98 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
100 /** An ident breakpoint. */
102 breakpoint bp; /**< the breakpoint data */
103 ident *id; /**< the ident */
106 /** Calculate the hash value for an ident breakpoint. */
107 #define HASH_IDENT_BP(key) (hash_ptr((key).id) ^ (key).bp.reason)
109 /** The set containing the breakpoints on node numbers. */
110 static set *bp_numbers;
112 /** The set containing the breakpoints on idents. */
113 static set *bp_idents;
115 /**< the list of all breakpoints */
116 static breakpoint *bp_list;
118 /** number of the current break point */
119 static unsigned bp_num = 0;
121 /** set if break on init command was issued. */
122 static int break_on_init = 0;
124 /** the hook entries for the Firm debugger module. */
125 static hook_entry_t debugger_hooks[hook_last];
127 /** number of active breakpoints to maintain hooks. */
128 static unsigned num_active_bp[BP_MAX_REASON];
131 * The debug message buffer
133 static char firm_dbg_msg_buf[2048];
136 * If set, the debug extension writes all output to the
137 * firm_dbg_msg_buf buffer
139 static int redir_output = 0;
142 * Is set to one, if the debug extension is active
144 static int is_active = 0;
146 /** hook the hook h with function fkt. */
147 #define HOOK(h, fkt) \
149 debugger_hooks[h].hook._##h = fkt; \
150 register_hook(h, &debugger_hooks[h]); \
153 /** unhook the hook h */
156 unregister_hook(h, &debugger_hooks[h]); \
157 debugger_hooks[h].hook._##h = NULL; \
160 /** returns non-zero if a entry hook h is used */
161 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
163 /* some macros needed to create the info string */
164 #define _DBG_VERSION(major, minor) #major "." #minor
165 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
166 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
168 /* the API version: change if needed */
169 #define FIRM_DBG_MAJOR 1
170 #define FIRM_DBG_MINOR 0
172 /** for automatic detection of the debug extension */
173 static const char __attribute__((used)) firm_debug_info_string[] =
174 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
176 int firm_debug_active(void)
182 * Reset the debug text buffer.
184 static void reset_dbg_buf(void)
186 firm_dbg_msg_buf[0] = '\0';
189 const char *firm_debug_text(void)
191 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
192 return firm_dbg_msg_buf;
198 static void dbg_printf(const char *fmt, ...)
208 size_t const cur = strlen(firm_dbg_msg_buf);
209 ir_vsnprintf(firm_dbg_msg_buf + cur, sizeof(firm_dbg_msg_buf) - cur, fmt, args);
211 ir_vprintf(fmt, args);
217 * A new node is created.
219 * @param ctx the hook context
220 * @param irg the IR graph on which the node is created
221 * @param node the new IR node that was created
223 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
229 key.nr = get_irn_node_nr(node);
230 key.bp.reason = BP_ON_NEW_THING;
232 elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
233 if (elem && elem->bp.active) {
234 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
240 * A node is replaced.
242 * @param ctx the hook context
243 * @param old the IR node the is replaced
244 * @param nw the new IR node that will replace old
246 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
251 key.nr = get_irn_node_nr(old);
252 key.bp.reason = BP_ON_REPLACE;
254 elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
255 if (elem && elem->bp.active) {
256 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
262 * A new node is lowered.
264 * @param ctx the hook context
265 * @param node the new IR node that will be lowered
267 static void dbg_lower(void *ctx, ir_node *node)
272 key.nr = get_irn_node_nr(node);
273 key.bp.reason = BP_ON_LOWER;
275 elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
276 if (elem && elem->bp.active) {
277 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
283 * A graph will be deleted.
285 * @param ctx the hook context
286 * @param irg the IR graph that will be deleted
288 static void dbg_free_graph(void *ctx, ir_graph *irg)
293 key.nr = get_irg_graph_nr(irg);
294 key.bp.reason = BP_ON_REMIRG;
296 elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
297 if (elem && elem->bp.active) {
298 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
303 bp_ident_t key, *elem;
304 ir_entity *ent = get_irg_entity(irg);
309 key.id = get_entity_ident(ent);
310 key.bp.reason = BP_ON_REMIRG;
312 elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
313 if (elem && elem->bp.active) {
314 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
321 * An entity was created.
323 * @param ctx the hook context
324 * @param ent the newly created entity
326 static void dbg_new_entity(void *ctx, ir_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_ident_t, 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_THING;
347 elem = set_find(bp_nr_t, 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, ir_type *tp)
367 key.nr = get_type_nr(tp);
368 key.bp.reason = BP_ON_NEW_THING;
370 elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
371 if (elem && elem->bp.active) {
372 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
379 * Return the reason string.
381 static const char *reason_str(bp_reasons_t reason)
384 case BP_ON_NEW_THING: return "node, entity or type creation";
385 case BP_ON_REPLACE: return "node replace";
386 case BP_ON_LOWER: return "node lowering";
387 case BP_ON_REMIRG: return "removing IRG";
388 case BP_ON_NEW_ENT: return "entity creation";
389 case BP_MAX_REASON: break;
391 panic("unsupported reason");
395 * Compare two number breakpoints.
397 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
399 const bp_nr_t *e1 = (const bp_nr_t*)elt;
400 const bp_nr_t *e2 = (const bp_nr_t*)key;
403 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
407 * Compare two ident breakpoints.
409 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
411 const bp_ident_t *e1 = (const bp_ident_t*)elt;
412 const bp_ident_t *e2 = (const bp_ident_t*)key;
415 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
421 static void update_hooks(breakpoint *bp)
423 #define CASE_ON(a, hook, handler) case a: if (! IS_HOOKED(hook)) HOOK(hook, handler); break
424 #define CASE_OFF(a, hook) case a: if (IS_HOOKED(hook)) UNHOOK(hook); break
427 ++num_active_bp[bp->reason];
429 --num_active_bp[bp->reason];
431 if (num_active_bp[bp->reason] > 0) {
432 /* register the hooks on demand */
433 switch (bp->reason) {
434 CASE_ON(BP_ON_REPLACE, hook_replace, dbg_replace);
435 CASE_ON(BP_ON_LOWER, hook_lower, dbg_lower);
436 CASE_ON(BP_ON_REMIRG, hook_free_graph, dbg_free_graph);
437 CASE_ON(BP_ON_NEW_ENT, hook_new_entity, dbg_new_entity);
438 case BP_ON_NEW_THING:
439 if (!IS_HOOKED(hook_new_node))
440 HOOK(hook_new_node, dbg_new_node);
441 if (!IS_HOOKED(hook_new_type))
442 HOOK(hook_new_type, dbg_new_type);
443 if (!IS_HOOKED(hook_new_entity))
444 HOOK(hook_new_entity, dbg_new_entity);
451 /* unregister the hook on demand */
452 switch (bp->reason) {
453 CASE_OFF(BP_ON_REPLACE, hook_replace);
454 CASE_OFF(BP_ON_LOWER, hook_lower);
455 CASE_OFF(BP_ON_REMIRG, hook_free_graph);
456 CASE_OFF(BP_ON_NEW_ENT, hook_new_entity);
457 case BP_ON_NEW_THING:
458 if (IS_HOOKED(hook_new_node))
459 UNHOOK(hook_new_node);
460 if (IS_HOOKED(hook_new_type))
461 UNHOOK(hook_new_type);
462 if (IS_HOOKED(hook_new_entity))
463 UNHOOK(hook_new_entity);
474 * Break if nr is reached.
476 static void break_on_nr(long nr, bp_reasons_t reason)
483 key.bp.reason = reason;
486 elem = set_insert(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
488 if (elem->bp.bpnr == 0) {
489 /* new break point */
490 elem->bp.bpnr = ++bp_num;
491 elem->bp.next = bp_list;
494 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
496 update_hooks(&elem->bp);
501 * Break if ident name is reached.
503 static void break_on_ident(const char *name, bp_reasons_t reason)
505 bp_ident_t key, *elem;
507 key.bp.kind = BP_IDENT;
510 key.bp.reason = reason;
511 key.id = new_id_from_str(name);
513 elem = set_insert(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
515 if (elem->bp.bpnr == 0) {
516 /* new break point */
517 elem->bp.bpnr = ++bp_num;
518 elem->bp.next = bp_list;
521 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
523 update_hooks(&elem->bp);
528 * Sets/resets the active flag of breakpoint bp.
530 static void bp_activate(unsigned bp, int active)
534 for (p = bp_list; p; p = p->next) {
536 if (p->active != active) {
541 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
545 dbg_printf("Error: Firm BP %u not exists.\n", bp);
550 * Show a list of supported commands
552 static void show_commands(void)
554 dbg_printf("Internal Firm debugger extension commands:\n"
555 "init break after initialization\n"
556 "create nr break if node nr was created\n"
557 "replace nr break if node nr is replaced by another node\n"
558 "lower nr break before node nr is lowered\n"
559 "remirg nr|name break if the irg of nr or entity name is deleted\n"
560 "newent nr|name break if the entity nr or name was created\n"
561 "newtype nr|name break if the type nr or name was created\n"
562 "bp show all breakpoints\n"
563 "enable nr enable breakpoint nr\n"
564 "disable nr disable breakpoint nr\n"
565 "showtype nr|name show content of the type nr or name\n"
566 "showent nr|name show content of the entity nr or name\n"
567 "setmask name msk sets the debug module name to mask msk\n"
568 "setlvl 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 "irgname name prints address and graph number of a method given by its name\n"
571 "irgldname ldname prints address and graph number of a method given by its ldname\n"
572 "initialnodenr n|rand set initial node number to n or random number\n"
573 "help list all commands\n"
578 * Shows all Firm breakpoints.
580 static void show_bp(void)
587 dbg_printf("Firm Breakpoints:");
588 for (p = bp_list; p; p = p->next) {
590 dbg_printf("+\n BP %u: ", p->bpnr);
594 node_p = (bp_nr_t *)p;
595 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
599 ident_p = (bp_ident_t *)p;
600 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
604 dbg_printf(p->active ? "+enabled" : "+disabled");
606 dbg_printf(have_one ? "+\n" : "+ NONE\n");
610 * firm_dbg_register() expects that the name is stored persistent.
611 * So we need this little helper function
613 static firm_dbg_module_t *dbg_register(const char *name)
615 ident *id = new_id_from_str(name);
617 return firm_dbg_register(get_id_str(id));
621 * Sets the debug mask of module name to lvl
623 static void set_dbg_level(const char *name, unsigned lvl)
625 firm_dbg_module_t *module = dbg_register(name);
627 if (firm_dbg_get_mask(module) != lvl) {
628 firm_dbg_set_mask(module, lvl);
630 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
635 * Redirects the debug output of module name to fname
637 static void set_dbg_outfile(const char *name, const char *fname)
639 firm_dbg_module_t *module = dbg_register(name);
640 FILE *f = fopen(fname, "w");
647 firm_dbg_set_file(module, f);
648 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
652 * Show info about a firm thing.
654 static void show_firm_object(void *firm_thing)
658 if (firm_thing == NULL) {
659 fprintf(f, "<NULL>\n");
662 switch (get_kind(firm_thing)) {
664 fprintf(f, "BAD: (%p)\n", firm_thing);
667 dump_entity_to_file(f, (ir_entity*)firm_thing);
670 dump_type_to_file(f, (ir_type*)firm_thing);
682 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
687 * Find a firm type by its number.
689 static ir_type *find_type_nr(long nr)
691 int i, n = get_irp_n_types();
694 for (i = 0; i < n; ++i) {
695 tp = get_irp_type(i);
696 if (get_type_nr(tp) == nr)
699 tp = get_glob_type();
700 if (get_type_nr(tp) == nr)
706 * Find a firm type by its name.
708 static ir_type *find_type_name(const char *name)
710 int i, n = get_irp_n_types();
713 for (i = 0; i < n; ++i) {
714 tp = get_irp_type(i);
715 if (!is_compound_type(tp))
718 if (strcmp(get_compound_name(tp), name) == 0)
721 tp = get_glob_type();
722 if (strcmp(get_compound_name(tp), name) == 0)
727 /** The environment for the entity search functions. */
728 typedef struct find_env {
730 long nr; /**< the number that is searched for */
731 const char *name; /**< the name that is searched for */
733 ir_entity *res; /**< the result */
737 * Type-walker: Find an entity with given number.
739 static void check_ent_nr(type_or_ent tore, void *ctx)
741 find_env_t *env = (find_env_t*)ctx;
743 if (is_entity(tore.ent)) {
744 if (get_entity_nr(tore.ent) == env->u.nr) {
751 * Type-walker: Find an entity with given name.
753 static void check_ent_name(type_or_ent tore, void *ctx)
755 find_env_t *env = (find_env_t*)ctx;
757 if (is_entity(tore.ent))
758 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
764 * Find a firm entity by its number.
766 static ir_entity *find_entity_nr(long nr)
772 type_walk(check_ent_nr, NULL, &env);
777 * Find a firm entity by its name.
779 static ir_entity *find_entity_name(const char *name)
785 type_walk(check_ent_name, NULL, &env);
790 * Search methods for a name.
792 static void show_by_name(type_or_ent tore, void *env)
794 ident *id = (ident *)env;
796 if (is_entity(tore.ent)) {
797 ir_entity *ent = tore.ent;
799 if (is_method_entity(ent)) {
800 if (get_entity_ident(ent) == id) {
801 ir_type *owner = get_entity_owner(ent);
802 ir_graph *irg = get_entity_irg(ent);
804 if (owner != get_glob_type()) {
805 printf("%s::%s", get_compound_name(owner), get_id_str(id));
807 printf("%s", get_id_str(id));
810 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
819 * Search methods for a ldname.
821 static void show_by_ldname(type_or_ent tore, void *env)
823 ident *id = (ident *)env;
825 if (is_entity(tore.ent)) {
826 ir_entity *ent = tore.ent;
828 if (is_method_entity(ent)) {
829 if (get_entity_ld_ident(ent) == id) {
830 ir_type *owner = get_entity_owner(ent);
831 ir_graph *irg = get_entity_irg(ent);
833 if (owner != get_glob_type()) {
834 printf("%s::%s", get_compound_name(owner), get_id_str(id));
836 printf("%s", get_id_str(id));
839 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
848 * prints the address and graph number of all irgs with given name
850 static void irg_name(const char *name)
852 ident *id = new_id_from_str(name);
854 type_walk(show_by_name, NULL, (void *)id);
858 * prints the address and graph number of all irgs with given ld_name
860 static void irg_ld_name(const char *name)
862 ident *id = new_id_from_str(name);
864 type_walk(show_by_ldname, NULL, (void *)id);
869 tok_bp = first_token,
894 static const char *reserved[] = {
919 static struct lexer {
920 int has_token; /**< set if a token is cached. */
921 unsigned cur_token; /**< current token. */
922 unsigned number; /**< current token attribute. */
923 const char *s; /**< current token attribute. */
924 size_t len; /**< current token attribute. */
926 const char *curr_pos;
928 const char *tok_start;
932 * Initialize the lexer.
934 static void init_lexer(const char *input)
937 lexer.curr_pos = input;
938 lexer.end_pos = input + strlen(input);
943 * Get the next char from the input.
945 static char next_char(void)
947 if (lexer.curr_pos >= lexer.end_pos)
949 return *lexer.curr_pos++;
952 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
955 #define MIN(a, b) (a) < (b) ? (a) : (b)
960 static unsigned get_token(void)
965 /* skip white space */
968 } while (c != '\0' && isspace((unsigned char)c));
970 lexer.tok_start = lexer.curr_pos - 1;
971 if (c == '.' || isalpha((unsigned char)c)) {
972 /* command begins here */
974 const char* tok_start;
979 } while (isgraph((unsigned char)c));
982 tok_start = lexer.tok_start;
983 if (*tok_start == '.') {
987 for (i = ARRAY_SIZE(reserved); i-- != 0;) {
988 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
989 return first_token + i;
993 lexer.s = lexer.tok_start;
994 lexer.len = lexer.curr_pos - lexer.s;
995 return tok_identifier;
996 } else if (isdigit((unsigned char)c) || c == '-') {
1000 /* we support negative numbers as well, so one can easily set all bits with -1 */
1009 if (c == 'x' || c == 'X') {
1013 if (! isxdigit((unsigned char)c))
1015 if (isdigit((unsigned char)c))
1016 number = (number << 4) | (c - '0');
1018 number = (number << 4) | (toupper((unsigned char)c) - 'A' + 10);
1021 lexer.number = number;
1026 if (! isdigit((unsigned char)c))
1028 number = number * 10 + (c - '0');
1032 lexer.number = sign ? 0 - number : number;
1040 void firm_debug(const char *cmd)
1042 char name[1024], fname[1024];
1050 token = get_token();
1057 token = get_token();
1058 if (token != tok_number)
1060 break_on_nr(lexer.number, BP_ON_NEW_THING);
1064 token = get_token();
1065 if (token != tok_number)
1067 break_on_nr(lexer.number, BP_ON_REPLACE);
1071 token = get_token();
1072 if (token != tok_number)
1074 break_on_nr(lexer.number, BP_ON_LOWER);
1078 token = get_token();
1080 if (token == tok_number)
1081 break_on_nr(lexer.number, BP_ON_REMIRG);
1082 else if (token == tok_identifier) {
1083 len = MIN(lexer.len, 1023);
1084 strncpy(name, lexer.s, len);
1086 break_on_ident(name, BP_ON_REMIRG);
1092 token = get_token();
1094 if (token == tok_number)
1095 break_on_nr(lexer.number, BP_ON_NEW_THING);
1096 else if (token == tok_identifier) {
1097 len = MIN(lexer.len, 1023);
1098 strncpy(name, lexer.s, len);
1100 break_on_ident(name, BP_ON_NEW_ENT);
1106 token = get_token();
1108 if (token == tok_number)
1109 show_firm_object(find_type_nr(lexer.number));
1110 else if (token == tok_identifier) {
1111 len = MIN(lexer.len, 1023);
1112 strncpy(name, lexer.s, len);
1114 show_firm_object(find_type_name(name));
1120 token = get_token();
1122 if (token == tok_number)
1123 show_firm_object(find_entity_nr(lexer.number));
1124 else if (token == tok_identifier) {
1125 len = MIN(lexer.len, 1023);
1126 strncpy(name, lexer.s, len);
1128 show_firm_object(find_entity_name(name));
1142 token = get_token();
1143 if (token != tok_number)
1145 bp_activate(lexer.number, 1);
1149 token = get_token();
1150 if (token != tok_number)
1152 bp_activate(lexer.number, 0);
1156 token = get_token();
1157 if (token != tok_identifier)
1159 len = MIN(lexer.len, 1023);
1160 strncpy(name, lexer.s, len);
1163 token = get_token();
1164 if (token != tok_number)
1166 set_dbg_level(name, lexer.number);
1170 token = get_token();
1171 if (token != tok_identifier)
1173 len = MIN(lexer.len, 1023);
1174 strncpy(name, lexer.s, len);
1177 token = get_token();
1178 if (token != tok_number)
1180 set_dbg_level(name, (1 << lexer.number) - 1);
1183 case tok_setoutfile:
1184 token = get_token();
1185 if (token != tok_identifier)
1187 len = MIN(lexer.len, 1023);
1188 strncpy(name, lexer.s, len);
1191 token = get_token();
1192 if (token != tok_identifier)
1194 len = MIN(lexer.len, 1023);
1195 strncpy(fname, lexer.s, len);
1197 set_dbg_outfile(name, fname);
1201 token = get_token();
1202 if (token != tok_identifier)
1204 len = MIN(lexer.len, 1023);
1205 strncpy(name, lexer.s, len);
1210 case tok_initialnodenr:
1211 token = get_token();
1212 if (token == tok_number) {
1213 dbg_printf("Setting initial node number to %u\n", lexer.number);
1214 irp->max_node_nr = lexer.number;
1215 } else if (token == tok_identifier && !strcmp(lexer.s, "rand")) {
1216 dbg_printf("Randomizing initial node number\n");
1218 irp->max_node_nr += rand() % 6666;
1224 token = get_token();
1225 if (token != tok_identifier)
1227 len = MIN(lexer.len, 1023);
1228 strncpy(name, lexer.s, len);
1233 case tok_dumpfilter:
1234 token = get_token();
1235 if (token != tok_identifier)
1237 len = MIN(lexer.len, 1023);
1238 strncpy(name, lexer.s, len);
1240 ir_set_dump_filter(name);
1250 printf("Error: before %s\n", lexer.tok_start);
1255 token = get_token();
1256 if (token == tok_eof)
1265 void firm_init_debugger(void)
1269 bp_numbers = new_set(cmp_nr_bp, 8);
1270 bp_idents = new_set(cmp_ident_bp, 8);
1272 env = getenv("FIRMDBG");
1283 void firm_finish_debugger(void)
1285 del_set(bp_numbers);
1290 * A gdb helper function to print firm objects.
1292 const char *gdb_node_helper(void *firm_object)
1294 static char buf[1024];
1295 ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
1299 const char *gdb_tarval_helper(void *tv_object)
1301 static char buf[1024];
1302 ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
1306 const char *gdb_out_edge_helper(const ir_node *node)
1308 static char buf[4*1024];
1311 size_t len = sizeof(buf);
1312 foreach_out_edge(node, edge) {
1313 ir_node *n = get_edge_src_irn(edge);
1315 ir_snprintf(b, len, "%+F ", n);
1326 /* some picky compiler do not allow empty files */
1327 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1332 * @page debugger The Firm debugger extension
1334 * Firm contains a debugger extension. This allows to set debugger breakpoints
1335 * an various events.
1336 * The extension uses a text interface which can be accessed from most debuggers.
1337 * More than one command can be given separated by ';'.
1339 * @section sec_cmd Supported commands
1341 * Historically all debugger commands start with a dot. This isn't needed in newer
1342 * versions, but still supported, ie the commands ".init" and "init" are equal.
1343 * The following commands are currently supported:
1347 * Break immediately after the debugger extension was initialized.
1348 * Typically this command is used in the environment to stop the execution
1349 * of a Firm compiler right after the initialization, like this:
1351 * $export FIRMDBG=".init"
1355 * Break if a new IR-node with node number nr was created.
1356 * Typically used to find the place where wrong nodes are created.
1360 * Break before IR-node with node number nr is replaced by another node.
1364 * Break before IR-node with node number nr is lowered.
1368 * Break if the irg with graph number nr is deleted.
1372 * Break if the irg of entity name is deleted.
1376 * Break if the entity with number nr was created.
1380 * Break if the entity name was created.
1384 * Break if the type with number nr was created.
1388 * Break if the type name was created.
1392 * Show all Firm internal breakpoints.
1396 * Enables breakpoint nr.
1400 * Disables breakpoint nr.
1404 * Show the content of entity nr.
1408 * Show the content of entity name.
1412 * Show the content of type nr.
1416 * Show the content of type name.
1418 * @b setmask name msk
1420 * Sets the debug module name to mask msk.
1422 * @b setlvl name lvl
1424 * Sets the debug module name to level lvl.
1426 * @b setoutfile name file
1428 * Redirects debug output of module name to file.
1432 * Prints address and graph number of a method given by its name.
1436 * Prints address and graph number of a method given by its linker name.
1440 * List all commands.
1443 * The Firm debugger extension can be accessed using the function firm_debug().
1444 * The following example shows how to set a creation breakpoint in GDB when
1445 * node 2101 is created.
1447 * -# set FIRMDBG="init"
1448 * -# start gdb with your compiler
1449 * -# after gdb breaks, issue
1451 * call firm_debug("create 2101")
1453 * On the console the following text should be issued:
1455 * Firm BP 1: creation of Node 2101
1458 * @section gdb_macro GDB macro
1460 * Add the following to your .gdbinit file:
1463 # define firm "cmd" Firm debugger extension
1466 call firm_debug($arg0)
1470 * Then, all Firm debugger extension commands can be accessed in the gdb
1471 * console using the firm prefix, eg.:
1473 * firm "create 2101"