2 * Copyright (C) 1995-2010 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Helper function for integrated debug support
23 * @author Michael Beck
31 #define WIN32_LEAN_AND_MEAN
49 #include "irgraph_t.h"
53 #include "iredges_t.h"
59 /* Break into the debugger. The Win32 way. */
60 void firm_debug_break(void)
64 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
65 /* Break into the debugger. The ia32/x86_64 way under GCC. */
66 void firm_debug_break(void)
68 __asm__ __volatile__("int3");
71 /* Break into the debugger. Poor Unix way. */
72 void firm_debug_break(void)
78 /** supported breakpoint kinds */
80 BP_NR = 'n', /**< break on node number. */
81 BP_IDENT = 'i' /**< break on ident. */
85 * Reasons for node number breakpoints.
87 typedef enum bp_reasons_t {
88 BP_ON_NEW_THING, /**< break if node, entity or type with number is created */
89 BP_ON_REPLACE, /**< break if node with number is replaced */
90 BP_ON_LOWER, /**< break if node with number is lowered */
91 BP_ON_REMIRG, /**< break if an IRG is removed */
92 BP_ON_NEW_ENT, /**< break if a new entity is created */
97 typedef struct breakpoint {
98 bp_kind kind; /**< the kind of this break point */
99 unsigned bpnr; /**< break point number */
100 int active; /**< non-zero, if this break point is active */
101 bp_reasons_t reason; /**< reason for the breakpoint */
102 struct breakpoint *next; /**< link to the next one */
105 /** A number breakpoint. */
107 breakpoint bp; /**< the breakpoint data */
108 long nr; /**< the node number */
111 /** Calculate the hash value for a node breakpoint. */
112 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
114 /** An ident breakpoint. */
116 breakpoint bp; /**< the breakpoint data */
117 ident *id; /**< the ident */
120 /** Calculate the hash value for an ident breakpoint. */
121 #define HASH_IDENT_BP(key) (hash_ptr((key).id) ^ (key).bp.reason)
123 /** The set containing the breakpoints on node numbers. */
124 static set *bp_numbers;
126 /** The set containing the breakpoints on idents. */
127 static set *bp_idents;
129 /**< the list of all breakpoints */
130 static breakpoint *bp_list;
132 /** number of the current break point */
133 static unsigned bp_num = 0;
135 /** set if break on init command was issued. */
136 static int break_on_init = 0;
138 /** the hook entries for the Firm debugger module. */
139 static hook_entry_t debugger_hooks[hook_last];
141 /** number of active breakpoints to maintain hooks. */
142 static unsigned num_active_bp[BP_MAX_REASON];
145 * The debug message buffer
147 static char firm_dbg_msg_buf[2048];
150 * If set, the debug extension writes all output to the
151 * firm_dbg_msg_buf buffer
153 static int redir_output = 0;
156 * Is set to one, if the debug extension is active
158 static int is_active = 0;
160 /** hook the hook h with function fkt. */
161 #define HOOK(h, fkt) \
163 debugger_hooks[h].hook._##h = fkt; \
164 register_hook(h, &debugger_hooks[h]); \
167 /** unhook the hook h */
170 unregister_hook(h, &debugger_hooks[h]); \
171 debugger_hooks[h].hook._##h = NULL; \
174 /** returns non-zero if a entry hook h is used */
175 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
177 /* some macros needed to create the info string */
178 #define _DBG_VERSION(major, minor) #major "." #minor
179 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
180 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
182 /* the API version: change if needed */
183 #define FIRM_DBG_MAJOR 1
184 #define FIRM_DBG_MINOR 0
186 /** for automatic detection of the debug extension */
187 static const char __attribute__((used)) firm_debug_info_string[] =
188 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
190 int firm_debug_active(void)
196 * Reset the debug text buffer.
198 static void reset_dbg_buf(void)
200 firm_dbg_msg_buf[0] = '\0';
203 static void add_to_dbg_buf(const char *buf)
205 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
208 const char *firm_debug_text(void)
210 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
211 return firm_dbg_msg_buf;
217 static void dbg_printf(const char *fmt, ...)
219 static char buf[2048];
229 ir_vsnprintf(buf, sizeof(buf), fmt, args);
239 * A new node is created.
241 * @param ctx the hook context
242 * @param irg the IR graph on which the node is created
243 * @param node the new IR node that was created
245 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
251 key.nr = get_irn_node_nr(node);
252 key.bp.reason = BP_ON_NEW_THING;
254 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
255 if (elem && elem->bp.active) {
256 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
262 * A node is replaced.
264 * @param ctx the hook context
265 * @param old the IR node the is replaced
266 * @param nw the new IR node that will replace old
268 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
273 key.nr = get_irn_node_nr(old);
274 key.bp.reason = BP_ON_REPLACE;
276 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
277 if (elem && elem->bp.active) {
278 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
284 * A new node is lowered.
286 * @param ctx the hook context
287 * @param node the new IR node that will be lowered
289 static void dbg_lower(void *ctx, ir_node *node)
294 key.nr = get_irn_node_nr(node);
295 key.bp.reason = BP_ON_LOWER;
297 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
298 if (elem && elem->bp.active) {
299 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
305 * A graph will be deleted.
307 * @param ctx the hook context
308 * @param irg the IR graph that will be deleted
310 static void dbg_free_graph(void *ctx, ir_graph *irg)
315 key.nr = get_irg_graph_nr(irg);
316 key.bp.reason = BP_ON_REMIRG;
318 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
319 if (elem && elem->bp.active) {
320 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
325 bp_ident_t key, *elem;
326 ir_entity *ent = get_irg_entity(irg);
331 key.id = get_entity_ident(ent);
332 key.bp.reason = BP_ON_REMIRG;
334 elem = (bp_ident_t*)set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
335 if (elem && elem->bp.active) {
336 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
343 * An entity was created.
345 * @param ctx the hook context
346 * @param ent the newly created entity
348 static void dbg_new_entity(void *ctx, ir_entity *ent)
352 bp_ident_t key, *elem;
354 key.id = get_entity_ident(ent);
355 key.bp.reason = BP_ON_NEW_ENT;
357 elem = (bp_ident_t*)set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
358 if (elem && elem->bp.active) {
359 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
366 key.nr = get_entity_nr(ent);
367 key.bp.reason = BP_ON_NEW_THING;
369 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
370 if (elem && elem->bp.active) {
371 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
378 * A type was created.
380 * @param ctx the hook context
381 * @param tp the newly created type
383 static void dbg_new_type(void *ctx, ir_type *tp)
389 key.nr = get_type_nr(tp);
390 key.bp.reason = BP_ON_NEW_THING;
392 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
393 if (elem && elem->bp.active) {
394 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
401 * Return the reason string.
403 static const char *reason_str(bp_reasons_t reason)
406 case BP_ON_NEW_THING: return "node, entity or type creation";
407 case BP_ON_REPLACE: return "node replace";
408 case BP_ON_LOWER: return "node lowering";
409 case BP_ON_REMIRG: return "removing IRG";
410 case BP_ON_NEW_ENT: return "entity creation";
411 case BP_MAX_REASON: break;
413 panic("unsupported reason");
417 * Compare two number breakpoints.
419 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
421 const bp_nr_t *e1 = (const bp_nr_t*)elt;
422 const bp_nr_t *e2 = (const bp_nr_t*)key;
425 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
429 * Compare two ident breakpoints.
431 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
433 const bp_ident_t *e1 = (const bp_ident_t*)elt;
434 const bp_ident_t *e2 = (const bp_ident_t*)key;
437 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
443 static void update_hooks(breakpoint *bp)
445 #define CASE_ON(a, hook, handler) case a: if (! IS_HOOKED(hook)) HOOK(hook, handler); break
446 #define CASE_OFF(a, hook) case a: if (IS_HOOKED(hook)) UNHOOK(hook); break
449 ++num_active_bp[bp->reason];
451 --num_active_bp[bp->reason];
453 if (num_active_bp[bp->reason] > 0) {
454 /* register the hooks on demand */
455 switch (bp->reason) {
456 CASE_ON(BP_ON_REPLACE, hook_replace, dbg_replace);
457 CASE_ON(BP_ON_LOWER, hook_lower, dbg_lower);
458 CASE_ON(BP_ON_REMIRG, hook_free_graph, dbg_free_graph);
459 CASE_ON(BP_ON_NEW_ENT, hook_new_entity, dbg_new_entity);
460 case BP_ON_NEW_THING:
461 if (!IS_HOOKED(hook_new_node))
462 HOOK(hook_new_node, dbg_new_node);
463 if (!IS_HOOKED(hook_new_type))
464 HOOK(hook_new_type, dbg_new_type);
465 if (!IS_HOOKED(hook_new_entity))
466 HOOK(hook_new_entity, dbg_new_entity);
473 /* unregister the hook on demand */
474 switch (bp->reason) {
475 CASE_OFF(BP_ON_REPLACE, hook_replace);
476 CASE_OFF(BP_ON_LOWER, hook_lower);
477 CASE_OFF(BP_ON_REMIRG, hook_free_graph);
478 CASE_OFF(BP_ON_NEW_ENT, hook_new_entity);
479 case BP_ON_NEW_THING:
480 if (IS_HOOKED(hook_new_node))
481 UNHOOK(hook_new_node);
482 if (IS_HOOKED(hook_new_type))
483 UNHOOK(hook_new_type);
484 if (IS_HOOKED(hook_new_entity))
485 UNHOOK(hook_new_entity);
496 * Break if nr is reached.
498 static void break_on_nr(long nr, bp_reasons_t reason)
505 key.bp.reason = reason;
508 elem = (bp_nr_t*)set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
510 if (elem->bp.bpnr == 0) {
511 /* new break point */
512 elem->bp.bpnr = ++bp_num;
513 elem->bp.next = bp_list;
516 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
518 update_hooks(&elem->bp);
523 * Break if ident name is reached.
525 static void break_on_ident(const char *name, bp_reasons_t reason)
527 bp_ident_t key, *elem;
529 key.bp.kind = BP_IDENT;
532 key.bp.reason = reason;
533 key.id = new_id_from_str(name);
535 elem = (bp_ident_t*)set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
537 if (elem->bp.bpnr == 0) {
538 /* new break point */
539 elem->bp.bpnr = ++bp_num;
540 elem->bp.next = bp_list;
543 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
545 update_hooks(&elem->bp);
550 * Sets/resets the active flag of breakpoint bp.
552 static void bp_activate(unsigned bp, int active)
556 for (p = bp_list; p; p = p->next) {
558 if (p->active != active) {
563 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
567 dbg_printf("Error: Firm BP %u not exists.\n", bp);
572 * Show a list of supported commands
574 static void show_commands(void)
576 dbg_printf("Internal Firm debugger extension commands:\n"
577 "init break after initialization\n"
578 "create nr break if node nr was created\n"
579 "replace nr break if node nr is replaced by another node\n"
580 "lower nr break before node nr is lowered\n"
581 "remirg nr|name break if the irg of nr or entity name is deleted\n"
582 "newent nr|name break if the entity nr or name was created\n"
583 "newtype nr|name break if the type nr or name was created\n"
584 "bp show all breakpoints\n"
585 "enable nr enable breakpoint nr\n"
586 "disable nr disable breakpoint nr\n"
587 "showtype nr|name show content of the type nr or name\n"
588 "showent nr|name show content of the entity nr or name\n"
589 "setmask name msk sets the debug module name to mask msk\n"
590 "setlvl name lvl sets the debug module name to level lvl\n"
591 "setoutfile name file redirects debug output of module name to file\n"
592 "irgname name prints address and graph number of a method given by its name\n"
593 "irgldname ldname prints address and graph number of a method given by its ldname\n"
594 "randnodenr randomize initial node number\n"
595 "help list all commands\n"
600 * Shows all Firm breakpoints.
602 static void show_bp(void)
609 dbg_printf("Firm Breakpoints:");
610 for (p = bp_list; p; p = p->next) {
612 dbg_printf("+\n BP %u: ", p->bpnr);
616 node_p = (bp_nr_t *)p;
617 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
621 ident_p = (bp_ident_t *)p;
622 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
626 dbg_printf(p->active ? "+enabled" : "+disabled");
628 dbg_printf(have_one ? "+\n" : "+ NONE\n");
632 * firm_dbg_register() expects that the name is stored persistent.
633 * So we need this little helper function
635 static firm_dbg_module_t *dbg_register(const char *name)
637 ident *id = new_id_from_str(name);
639 return firm_dbg_register(get_id_str(id));
643 * Sets the debug mask of module name to lvl
645 static void set_dbg_level(const char *name, unsigned lvl)
647 firm_dbg_module_t *module = dbg_register(name);
649 if (firm_dbg_get_mask(module) != lvl) {
650 firm_dbg_set_mask(module, lvl);
652 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
657 * Redirects the debug output of module name to fname
659 static void set_dbg_outfile(const char *name, const char *fname)
661 firm_dbg_module_t *module = dbg_register(name);
662 FILE *f = fopen(fname, "w");
669 firm_dbg_set_file(module, f);
670 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
674 * Show info about a firm thing.
676 static void show_firm_object(void *firm_thing)
680 if (firm_thing == NULL) {
681 fprintf(f, "<NULL>\n");
684 switch (get_kind(firm_thing)) {
686 fprintf(f, "BAD: (%p)\n", firm_thing);
689 dump_entity_to_file(f, (ir_entity*)firm_thing);
692 dump_type_to_file(f, (ir_type*)firm_thing);
700 case k_ir_compound_graph_path:
705 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
710 * Find a firm type by its number.
712 static ir_type *find_type_nr(long nr)
714 int i, n = get_irp_n_types();
717 for (i = 0; i < n; ++i) {
718 tp = get_irp_type(i);
719 if (get_type_nr(tp) == nr)
722 tp = get_glob_type();
723 if (get_type_nr(tp) == nr)
729 * Find a firm type by its name.
731 static ir_type *find_type_name(const char *name)
733 int i, n = get_irp_n_types();
736 for (i = 0; i < n; ++i) {
737 tp = get_irp_type(i);
738 if (!is_compound_type(tp))
741 if (strcmp(get_compound_name(tp), name) == 0)
744 tp = get_glob_type();
745 if (strcmp(get_compound_name(tp), name) == 0)
750 /** The environment for the entity search functions. */
751 typedef struct find_env {
753 long nr; /**< the number that is searched for */
754 const char *name; /**< the name that is searched for */
756 ir_entity *res; /**< the result */
760 * Type-walker: Find an entity with given number.
762 static void check_ent_nr(type_or_ent tore, void *ctx)
764 find_env_t *env = (find_env_t*)ctx;
766 if (is_entity(tore.ent)) {
767 if (get_entity_nr(tore.ent) == env->u.nr) {
774 * Type-walker: Find an entity with given name.
776 static void check_ent_name(type_or_ent tore, void *ctx)
778 find_env_t *env = (find_env_t*)ctx;
780 if (is_entity(tore.ent))
781 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
787 * Find a firm entity by its number.
789 static ir_entity *find_entity_nr(long nr)
795 type_walk(check_ent_nr, NULL, &env);
800 * Find a firm entity by its name.
802 static ir_entity *find_entity_name(const char *name)
808 type_walk(check_ent_name, NULL, &env);
813 * Search methods for a name.
815 static void show_by_name(type_or_ent tore, void *env)
817 ident *id = (ident *)env;
819 if (is_entity(tore.ent)) {
820 ir_entity *ent = tore.ent;
822 if (is_method_entity(ent)) {
823 if (get_entity_ident(ent) == id) {
824 ir_type *owner = get_entity_owner(ent);
825 ir_graph *irg = get_entity_irg(ent);
827 if (owner != get_glob_type()) {
828 printf("%s::%s", get_compound_name(owner), get_id_str(id));
830 printf("%s", get_id_str(id));
833 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
842 * Search methods for a ldname.
844 static void show_by_ldname(type_or_ent tore, void *env)
846 ident *id = (ident *)env;
848 if (is_entity(tore.ent)) {
849 ir_entity *ent = tore.ent;
851 if (is_method_entity(ent)) {
852 if (get_entity_ld_ident(ent) == id) {
853 ir_type *owner = get_entity_owner(ent);
854 ir_graph *irg = get_entity_irg(ent);
856 if (owner != get_glob_type()) {
857 printf("%s::%s", get_compound_name(owner), get_id_str(id));
859 printf("%s", get_id_str(id));
862 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
871 * prints the address and graph number of all irgs with given name
873 static void irg_name(const char *name)
875 ident *id = new_id_from_str(name);
877 type_walk(show_by_name, NULL, (void *)id);
881 * prints the address and graph number of all irgs with given ld_name
883 static void irg_ld_name(const char *name)
885 ident *id = new_id_from_str(name);
887 type_walk(show_by_ldname, NULL, (void *)id);
892 tok_bp = first_token,
917 static const char *reserved[] = {
942 static struct lexer {
943 int has_token; /**< set if a token is cached. */
944 unsigned cur_token; /**< current token. */
945 unsigned number; /**< current token attribute. */
946 const char *s; /**< current token attribute. */
947 size_t len; /**< current token attribute. */
949 const char *curr_pos;
951 const char *tok_start;
955 * Initialize the lexer.
957 static void init_lexer(const char *input)
960 lexer.curr_pos = input;
961 lexer.end_pos = input + strlen(input);
966 * Get the next char from the input.
968 static char next_char(void)
970 if (lexer.curr_pos >= lexer.end_pos)
972 return *lexer.curr_pos++;
975 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
978 #define MIN(a, b) (a) < (b) ? (a) : (b)
983 static unsigned get_token(void)
988 /* skip white space */
991 } while (c != '\0' && isspace((unsigned char)c));
993 lexer.tok_start = lexer.curr_pos - 1;
994 if (c == '.' || isalpha((unsigned char)c)) {
995 /* command begins here */
997 const char* tok_start;
1002 } while (isgraph((unsigned char)c));
1005 tok_start = lexer.tok_start;
1006 if (*tok_start == '.') {
1010 for (i = ARRAY_SIZE(reserved); i-- != 0;) {
1011 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
1012 return first_token + i;
1016 lexer.s = lexer.tok_start;
1017 lexer.len = lexer.curr_pos - lexer.s;
1018 return tok_identifier;
1019 } else if (isdigit((unsigned char)c) || c == '-') {
1020 unsigned number = 0;
1023 /* we support negative numbers as well, so one can easily set all bits with -1 */
1032 if (c == 'x' || c == 'X') {
1036 if (! isxdigit((unsigned char)c))
1038 if (isdigit((unsigned char)c))
1039 number = (number << 4) | (c - '0');
1041 number = (number << 4) | (toupper((unsigned char)c) - 'A' + 10);
1044 lexer.number = number;
1049 if (! isdigit((unsigned char)c))
1051 number = number * 10 + (c - '0');
1055 lexer.number = sign ? 0 - number : number;
1063 void firm_debug(const char *cmd)
1065 char name[1024], fname[1024];
1073 token = get_token();
1080 token = get_token();
1081 if (token != tok_number)
1083 break_on_nr(lexer.number, BP_ON_NEW_THING);
1087 token = get_token();
1088 if (token != tok_number)
1090 break_on_nr(lexer.number, BP_ON_REPLACE);
1094 token = get_token();
1095 if (token != tok_number)
1097 break_on_nr(lexer.number, BP_ON_LOWER);
1101 token = get_token();
1103 if (token == tok_number)
1104 break_on_nr(lexer.number, BP_ON_REMIRG);
1105 else if (token == tok_identifier) {
1106 len = MIN(lexer.len, 1023);
1107 strncpy(name, lexer.s, len);
1109 break_on_ident(name, BP_ON_REMIRG);
1115 token = get_token();
1117 if (token == tok_number)
1118 break_on_nr(lexer.number, BP_ON_NEW_THING);
1119 else if (token == tok_identifier) {
1120 len = MIN(lexer.len, 1023);
1121 strncpy(name, lexer.s, len);
1123 break_on_ident(name, BP_ON_NEW_ENT);
1129 token = get_token();
1131 if (token == tok_number)
1132 show_firm_object(find_type_nr(lexer.number));
1133 else if (token == tok_identifier) {
1134 len = MIN(lexer.len, 1023);
1135 strncpy(name, lexer.s, len);
1137 show_firm_object(find_type_name(name));
1143 token = get_token();
1145 if (token == tok_number)
1146 show_firm_object(find_entity_nr(lexer.number));
1147 else if (token == tok_identifier) {
1148 len = MIN(lexer.len, 1023);
1149 strncpy(name, lexer.s, len);
1151 show_firm_object(find_entity_name(name));
1165 token = get_token();
1166 if (token != tok_number)
1168 bp_activate(lexer.number, 1);
1172 token = get_token();
1173 if (token != tok_number)
1175 bp_activate(lexer.number, 0);
1179 token = get_token();
1180 if (token != tok_identifier)
1182 len = MIN(lexer.len, 1023);
1183 strncpy(name, lexer.s, len);
1186 token = get_token();
1187 if (token != tok_number)
1189 set_dbg_level(name, lexer.number);
1193 token = get_token();
1194 if (token != tok_identifier)
1196 len = MIN(lexer.len, 1023);
1197 strncpy(name, lexer.s, len);
1200 token = get_token();
1201 if (token != tok_number)
1203 set_dbg_level(name, (1 << lexer.number) - 1);
1206 case tok_setoutfile:
1207 token = get_token();
1208 if (token != tok_identifier)
1210 len = MIN(lexer.len, 1023);
1211 strncpy(name, lexer.s, len);
1214 token = get_token();
1215 if (token != tok_identifier)
1217 len = MIN(lexer.len, 1023);
1218 strncpy(fname, lexer.s, len);
1220 set_dbg_outfile(name, fname);
1224 token = get_token();
1225 if (token != tok_identifier)
1227 len = MIN(lexer.len, 1023);
1228 strncpy(name, lexer.s, len);
1233 case tok_randnodenr:
1234 dbg_printf("Randomizing initial node number\n");
1236 irp->max_node_nr += rand() % 6666;
1240 token = get_token();
1241 if (token != tok_identifier)
1243 len = MIN(lexer.len, 1023);
1244 strncpy(name, lexer.s, len);
1249 case tok_dumpfilter:
1250 token = get_token();
1251 if (token != tok_identifier)
1253 len = MIN(lexer.len, 1023);
1254 strncpy(name, lexer.s, len);
1256 ir_set_dump_filter(name);
1266 printf("Error: before %s\n", lexer.tok_start);
1271 token = get_token();
1272 if (token == tok_eof)
1281 void firm_init_debugger(void)
1285 bp_numbers = new_set(cmp_nr_bp, 8);
1286 bp_idents = new_set(cmp_ident_bp, 8);
1288 env = getenv("FIRMDBG");
1299 void firm_finish_debugger(void)
1301 del_set(bp_numbers);
1306 * A gdb helper function to print firm objects.
1308 const char *gdb_node_helper(void *firm_object)
1310 static char buf[1024];
1311 ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
1315 const char *gdb_tarval_helper(void *tv_object)
1317 static char buf[1024];
1318 ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
1322 const char *gdb_out_edge_helper(const ir_node *node)
1324 static char buf[4*1024];
1327 size_t len = sizeof(buf);
1328 const ir_edge_t *edge;
1329 foreach_out_edge(node, edge) {
1330 ir_node *n = get_edge_src_irn(edge);
1332 ir_snprintf(b, len, "%+F ", n);
1343 /* some picky compiler do not allow empty files */
1344 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1349 * @page debugger The Firm debugger extension
1351 * Firm contains a debugger extension. This allows to set debugger breakpoints
1352 * an various events.
1353 * The extension uses a text interface which can be accessed from most debuggers.
1354 * More than one command can be given separated by ';'.
1356 * @section sec_cmd Supported commands
1358 * Historically all debugger commands start with a dot. This isn't needed in newer
1359 * versions, but still supported, ie the commands ".init" and "init" are equal.
1360 * The following commands are currently supported:
1364 * Break immediately after the debugger extension was initialized.
1365 * Typically this command is used in the environment to stop the execution
1366 * of a Firm compiler right after the initialization, like this:
1368 * $export FIRMDBG=".init"
1372 * Break if a new IR-node with node number nr was created.
1373 * Typically used to find the place where wrong nodes are created.
1377 * Break before IR-node with node number nr is replaced by another node.
1381 * Break before IR-node with node number nr is lowered.
1385 * Break if the irg with graph number nr is deleted.
1389 * Break if the irg of entity name is deleted.
1393 * Break if the entity with number nr was created.
1397 * Break if the entity name was created.
1401 * Break if the type with number nr was created.
1405 * Break if the type name was created.
1409 * Show all Firm internal breakpoints.
1413 * Enables breakpoint nr.
1417 * Disables breakpoint nr.
1421 * Show the content of entity nr.
1425 * Show the content of entity name.
1429 * Show the content of type nr.
1433 * Show the content of type name.
1435 * @b setmask name msk
1437 * Sets the debug module name to mask msk.
1439 * @b setlvl name lvl
1441 * Sets the debug module name to level lvl.
1443 * @b setoutfile name file
1445 * Redirects debug output of module name to file.
1449 * Prints address and graph number of a method given by its name.
1453 * Prints address and graph number of a method given by its linker name.
1457 * List all commands.
1460 * The Firm debugger extension can be accessed using the function firm_debug().
1461 * The following example shows how to set a creation breakpoint in GDB when
1462 * node 2101 is created.
1464 * -# set FIRMDBG="init"
1465 * -# start gdb with your compiler
1466 * -# after gdb breaks, issue
1468 * call firm_debug("create 2101")
1470 * On the console the following text should be issued:
1472 * Firm BP 1: creation of Node 2101
1475 * @section gdb_macro GDB macro
1477 * Add the following to your .gdbinit file:
1480 # define firm "cmd" Firm debugger extension
1483 call firm_debug($arg0)
1487 * Then, all Firm debugger extension commands can be accessed in the gdb
1488 * console using the firm prefix, eg.:
1490 * firm "create 2101"