2 * Copyright (C) 1995-2008 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
32 #define WIN32_LEAN_AND_MEAN
52 #include "irgraph_t.h"
56 #include "iredges_t.h"
61 /* Break into the debugger. The Win32 way. */
62 void firm_debug_break(void)
66 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
67 /* Break into the debugger. The ia32/x86_64 way under GCC. */
68 void firm_debug_break(void)
70 __asm__ __volatile__("int3");
73 /* Break into the debugger. Poor Unix way. */
74 void firm_debug_break(void)
80 /** supported breakpoint kinds */
82 BP_NR = 'n', /**< break on node number. */
83 BP_IDENT = 'i' /**< break on ident. */
87 * Reasons for node number breakpoints.
89 typedef enum _bp_reasons_t {
90 BP_ON_NEW_NODE, /**< break if node with number is created */
91 BP_ON_REPLACE, /**< break if node with number is replaced */
92 BP_ON_LOWER, /**< break if node with number is lowered */
93 BP_ON_REMIRG, /**< break if an IRG is removed */
94 BP_ON_NEW_ENT, /**< break if a new entity is created */
95 BP_ON_NEW_TYPE, /**< break if a new type is created */
100 typedef struct _breakpoint {
101 bp_kind kind; /**< the kind of this break point */
102 unsigned bpnr; /**< break point number */
103 int active; /**< non-zero, if this break point is active */
104 bp_reasons_t reason; /**< reason for the breakpoint */
105 struct _breakpoint *next; /**< link to the next one */
108 /** A number breakpoint. */
110 breakpoint bp; /**< the breakpoint data */
111 long nr; /**< the node number */
114 /** Calculate the hash value for a node breakpoint. */
115 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
117 /** An ident breakpoint. */
119 breakpoint bp; /**< the breakpoint data */
120 ident *id; /**< the ident */
123 /** Calculate the hash value for an ident breakpoint. */
124 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
126 /** The set containing the breakpoints on node numbers. */
127 static set *bp_numbers;
129 /** The set containing the breakpoints on idents. */
130 static set *bp_idents;
132 /**< the list of all breakpoints */
133 static breakpoint *bp_list;
135 /** number of the current break point */
136 static unsigned bp_num = 0;
138 /** set if break on init command was issued. */
139 static int break_on_init = 0;
141 /** the hook entries for the Firm debugger module. */
142 static hook_entry_t debugger_hooks[hook_last];
144 /** number of active breakpoints to maintain hooks. */
145 static unsigned num_active_bp[BP_MAX_REASON];
148 * The debug message buffer
150 static char firm_dbg_msg_buf[2048];
153 * If set, the debug extension writes all output to the
154 * firm_dbg_msg_buf buffer
156 static int redir_output = 0;
159 * Is set to one, if the debug extension is active
161 static int is_active = 0;
163 /** hook the hook h with function fkt. */
164 #define HOOK(h, fkt) \
166 debugger_hooks[h].hook._##h = fkt; \
167 register_hook(h, &debugger_hooks[h]); \
170 /** unhook the hook h */
173 unregister_hook(h, &debugger_hooks[h]); \
174 debugger_hooks[h].hook._##h = NULL; \
177 /** returns non-zero if a entry hook h is used */
178 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
180 /* some macros needed to create the info string */
181 #define _DBG_VERSION(major, minor) #major "." #minor
182 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
183 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
185 /* the API version: change if needed */
186 #define FIRM_DBG_MAJOR 1
187 #define FIRM_DBG_MINOR 0
189 /** for automatic detection of the debug extension */
190 static const char __attribute__((used)) firm_debug_info_string[] =
191 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
193 int firm_debug_active(void)
196 } /* firm_debug_active */
199 * Reset the debug text buffer.
201 static void reset_dbg_buf(void)
203 firm_dbg_msg_buf[0] = '\0';
204 } /* reset_dbg_buf */
206 static void add_to_dbg_buf(const char *buf)
208 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
209 } /* add_to_dbg_buf */
211 const char *firm_debug_text(void)
213 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
214 return firm_dbg_msg_buf;
215 } /* firm_debug_text */
220 static void dbg_printf(const char *fmt, ...)
232 ir_vsnprintf(buf, sizeof(buf), fmt, args);
242 * A new node is created.
244 * @param ctx the hook context
245 * @param irg the IR graph on which the node is created
246 * @param node the new IR node that was created
248 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
254 key.nr = get_irn_node_nr(node);
255 key.bp.reason = BP_ON_NEW_NODE;
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 created\n", elem->bp.bpnr, node);
265 * A node is replaced.
267 * @param ctx the hook context
268 * @param old the IR node the is replaced
269 * @param nw the new IR node that will replace old
271 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
276 key.nr = get_irn_node_nr(old);
277 key.bp.reason = BP_ON_REPLACE;
279 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
280 if (elem && elem->bp.active) {
281 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
287 * A new node is lowered.
289 * @param ctx the hook context
290 * @param node the new IR node that will be lowered
292 static void dbg_lower(void *ctx, ir_node *node)
297 key.nr = get_irn_node_nr(node);
298 key.bp.reason = BP_ON_LOWER;
300 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
301 if (elem && elem->bp.active) {
302 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
308 * A graph will be deleted.
310 * @param ctx the hook context
311 * @param irg the IR graph that will be deleted
313 static void dbg_free_graph(void *ctx, ir_graph *irg)
318 key.nr = get_irg_graph_nr(irg);
319 key.bp.reason = BP_ON_REMIRG;
321 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
322 if (elem && elem->bp.active) {
323 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
328 bp_ident_t key, *elem;
329 ir_entity *ent = get_irg_entity(irg);
334 key.id = get_entity_ident(ent);
335 key.bp.reason = BP_ON_REMIRG;
337 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
338 if (elem && elem->bp.active) {
339 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
343 } /* dbg_free_graph */
346 * An entity was created.
348 * @param ctx the hook context
349 * @param ent the newly created entity
351 static void dbg_new_entity(void *ctx, ir_entity *ent)
355 bp_ident_t key, *elem;
357 key.id = get_entity_ident(ent);
358 key.bp.reason = BP_ON_NEW_ENT;
360 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
361 if (elem && elem->bp.active) {
362 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
369 key.nr = get_entity_nr(ent);
370 key.bp.reason = BP_ON_NEW_ENT;
372 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
373 if (elem && elem->bp.active) {
374 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
378 } /* dbg_new_entity */
381 * A type was created.
383 * @param ctx the hook context
384 * @param tp the newly created type
386 static void dbg_new_type(void *ctx, ir_type *tp)
392 key.nr = get_type_nr(tp);
393 key.bp.reason = BP_ON_NEW_TYPE;
395 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
396 if (elem && elem->bp.active) {
397 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
404 * Return the reason string.
406 static const char *reason_str(bp_reasons_t reason)
409 case BP_ON_NEW_NODE: return "node creation";
410 case BP_ON_REPLACE: return "node replace";
411 case BP_ON_LOWER: return "node lowering";
412 case BP_ON_REMIRG: return "removing IRG";
413 case BP_ON_NEW_ENT: return "entity creation";
414 case BP_ON_NEW_TYPE: return "type creation";
415 case BP_MAX_REASON: break;
417 panic("unsupported reason");
421 * Compare two number breakpoints.
423 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
425 const bp_nr_t *e1 = elt;
426 const bp_nr_t *e2 = key;
429 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
433 * Compare two ident breakpoints.
435 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
437 const bp_ident_t *e1 = elt;
438 const bp_ident_t *e2 = key;
441 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
447 static void update_hooks(breakpoint *bp)
449 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
450 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
453 ++num_active_bp[bp->reason];
455 --num_active_bp[bp->reason];
457 if (num_active_bp[bp->reason] > 0) {
458 /* register the hooks on demand */
459 switch (bp->reason) {
460 CASE_ON(BP_ON_NEW_NODE, new_node);
461 CASE_ON(BP_ON_REPLACE, replace);
462 CASE_ON(BP_ON_LOWER, lower);
463 CASE_ON(BP_ON_REMIRG, free_graph);
464 CASE_ON(BP_ON_NEW_ENT, new_entity);
465 CASE_ON(BP_ON_NEW_TYPE, new_type);
471 /* unregister the hook on demand */
472 switch (bp->reason) {
473 CASE_OFF(BP_ON_NEW_NODE, new_node);
474 CASE_OFF(BP_ON_REPLACE, replace);
475 CASE_OFF(BP_ON_LOWER, lower);
476 CASE_OFF(BP_ON_REMIRG, free_graph);
477 CASE_OFF(BP_ON_NEW_ENT, new_entity);
478 CASE_OFF(BP_ON_NEW_TYPE, new_type);
488 * Break if nr is reached.
490 static void break_on_nr(long nr, bp_reasons_t reason)
497 key.bp.reason = reason;
500 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
502 if (elem->bp.bpnr == 0) {
503 /* new break point */
504 elem->bp.bpnr = ++bp_num;
505 elem->bp.next = bp_list;
508 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
510 update_hooks(&elem->bp);
515 * Break if ident name is reached.
517 static void break_on_ident(const char *name, bp_reasons_t reason)
519 bp_ident_t key, *elem;
521 key.bp.kind = BP_IDENT;
524 key.bp.reason = reason;
525 key.id = new_id_from_str(name);
527 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
529 if (elem->bp.bpnr == 0) {
530 /* new break point */
531 elem->bp.bpnr = ++bp_num;
532 elem->bp.next = bp_list;
535 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
537 update_hooks(&elem->bp);
539 } /* break_on_ident */
542 * Sets/resets the active flag of breakpoint bp.
544 static void bp_activate(unsigned bp, int active)
548 for (p = bp_list; p; p = p->next) {
550 if (p->active != active) {
555 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
559 dbg_printf("Error: Firm BP %u not exists.\n", bp);
564 * Show a list of supported commands
566 static void show_commands(void)
568 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
569 "init break after initialization\n"
570 "create nr break if node nr was created\n"
571 "replace nr break if node nr is replaced by another node\n"
572 "lower nr break before node nr is lowered\n"
573 "remirg nr|name break if the irg of nr or entity name is deleted\n"
574 "newent nr|name break if the entity nr or name was created\n"
575 "newtype nr|name break if the type nr or name was created\n"
576 "bp show all breakpoints\n"
577 "enable nr enable breakpoint nr\n"
578 "disable nr disable breakpoint nr\n"
579 "showtype nr|name show content of the type nr or name\n"
580 "showent nr|name show content of the entity nr or name\n"
581 "setmask name msk sets the debug module name to mask msk\n"
582 "setlvl name lvl sets the debug module name to level lvl\n"
583 "setoutfile name file redirects debug output of module name to file\n"
584 "irgname name prints address and graph number of a method given by its name\n"
585 "irgldname ldname prints address and graph number of a method given by its ldname\n"
586 "help list all commands\n"
588 } /* show_commands */
591 * Shows all Firm breakpoints.
593 static void show_bp(void)
600 dbg_printf("Firm Breakpoints:");
601 for (p = bp_list; p; p = p->next) {
603 dbg_printf("+\n BP %u: ", p->bpnr);
607 node_p = (bp_nr_t *)p;
608 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
612 ident_p = (bp_ident_t *)p;
613 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
617 dbg_printf(p->active ? "+enabled" : "+disabled");
619 dbg_printf(have_one ? "+\n" : "+ NONE\n");
623 * firm_dbg_register() expects that the name is stored persistent.
624 * So we need this little helper function
626 static firm_dbg_module_t *dbg_register(const char *name)
628 ident *id = new_id_from_str(name);
630 return firm_dbg_register(get_id_str(id));
634 * Sets the debug mask of module name to lvl
636 static void set_dbg_level(const char *name, unsigned lvl)
638 firm_dbg_module_t *module = dbg_register(name);
640 if (firm_dbg_get_mask(module) != lvl) {
641 firm_dbg_set_mask(module, lvl);
643 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
645 } /* set_dbg_level */
648 * Redirects the debug output of module name to fname
650 static void set_dbg_outfile(const char *name, const char *fname)
652 firm_dbg_module_t *module = dbg_register(name);
653 FILE *f = fopen(fname, "w");
660 firm_dbg_set_file(module, f);
661 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
662 } /* set_dbg_outfile */
665 * Show info about a firm thing.
667 static void show_firm_object(void *firm_thing)
671 if (firm_thing == NULL) {
672 fprintf(f, "<NULL>\n");
675 switch (get_kind(firm_thing)) {
677 fprintf(f, "BAD: (%p)\n", firm_thing);
680 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
683 dump_type_to_file(f, firm_thing, dump_verbosity_max);
691 case k_ir_compound_graph_path:
697 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
699 } /* show_firm_object */
702 * Find a firm type by its number.
704 static ir_type *find_type_nr(long nr)
706 int i, n = get_irp_n_types();
709 for (i = 0; i < n; ++i) {
710 tp = get_irp_type(i);
711 if (get_type_nr(tp) == nr)
714 tp = get_glob_type();
715 if (get_type_nr(tp) == nr)
721 * Find a firm type by its name.
723 static ir_type *find_type_name(const char *name)
725 int i, n = get_irp_n_types();
728 for (i = 0; i < n; ++i) {
729 tp = get_irp_type(i);
730 if (!is_compound_type(tp))
733 if (strcmp(get_compound_name(tp), name) == 0)
736 tp = get_glob_type();
737 if (strcmp(get_compound_name(tp), name) == 0)
740 } /* find_type_name */
742 /** The environment for the entity search functions. */
743 typedef struct find_env {
745 long nr; /**< the number that is searched for */
746 const char *name; /**< the name that is searched for */
748 ir_entity *res; /**< the result */
752 * Type-walker: Find an entity with given number.
754 static void check_ent_nr(type_or_ent tore, void *ctx)
756 find_env_t *env = ctx;
758 if (is_entity(tore.ent)) {
759 if (get_entity_nr(tore.ent) == env->u.nr) {
766 * Type-walker: Find an entity with given name.
768 static void check_ent_name(type_or_ent tore, void *ctx)
770 find_env_t *env = ctx;
772 if (is_entity(tore.ent))
773 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
776 } /* check_ent_name */
779 * Find a firm entity by its number.
781 static ir_entity *find_entity_nr(long nr)
787 type_walk(check_ent_nr, NULL, &env);
789 } /* find_entity_nr */
792 * Find a firm entity by its name.
794 static ir_entity *find_entity_name(const char *name)
800 type_walk(check_ent_name, NULL, &env);
802 } /* find_entity_name */
805 * Search methods for a name.
807 static void show_by_name(type_or_ent tore, void *env)
809 ident *id = (ident *)env;
811 if (is_entity(tore.ent)) {
812 ir_entity *ent = tore.ent;
814 if (is_method_entity(ent)) {
815 if (get_entity_ident(ent) == id) {
816 ir_type *owner = get_entity_owner(ent);
817 ir_graph *irg = get_entity_irg(ent);
819 if (owner != get_glob_type()) {
820 printf("%s::%s", get_compound_name(owner), get_id_str(id));
822 printf("%s", get_id_str(id));
825 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
834 * Search methods for a ldname.
836 static void show_by_ldname(type_or_ent tore, void *env)
838 ident *id = (ident *)env;
840 if (is_entity(tore.ent)) {
841 ir_entity *ent = tore.ent;
843 if (is_method_entity(ent)) {
844 if (get_entity_ld_ident(ent) == id) {
845 ir_type *owner = get_entity_owner(ent);
846 ir_graph *irg = get_entity_irg(ent);
848 if (owner != get_glob_type()) {
849 printf("%s::%s", get_compound_name(owner), get_id_str(id));
851 printf("%s", get_id_str(id));
854 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
860 } /* show_by_ldname */
863 * prints the address and graph number of all irgs with given name
865 static void irg_name(const char *name)
867 ident *id = new_id_from_str(name);
869 type_walk(show_by_name, NULL, (void *)id);
873 * prints the address and graph number of all irgs with given ld_name
875 static void irg_ld_name(const char *name)
877 ident *id = new_id_from_str(name);
879 type_walk(show_by_ldname, NULL, (void *)id);
907 static const char *reserved[] = {
931 static struct lexer {
932 int has_token; /**< set if a token is cached. */
933 unsigned cur_token; /**< current token. */
934 unsigned number; /**< current token attribute. */
935 const char *s; /**< current token attribute. */
936 unsigned len; /**< current token attribute. */
938 const char *curr_pos;
940 const char *tok_start;
944 * Initialize the lexer.
946 static void init_lexer(const char *input)
949 lexer.curr_pos = input;
950 lexer.end_pos = input + strlen(input);
955 * Get the next char from the input.
957 static char next_char(void)
959 if (lexer.curr_pos >= lexer.end_pos)
961 return *lexer.curr_pos++;
964 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
967 #define MIN(a, b) (a) < (b) ? (a) : (b)
972 static unsigned get_token(void)
977 /* skip white space */
980 } while (c != '\0' && isspace(c));
982 lexer.tok_start = lexer.curr_pos - 1;
983 if (c == '.' || isalpha(c)) {
984 /* command begins here */
986 const char* tok_start;
991 } while (isgraph(c));
994 tok_start = lexer.tok_start;
995 if (*tok_start == '.') {
999 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
1000 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
1005 lexer.s = lexer.tok_start;
1006 lexer.len = lexer.curr_pos - lexer.s;
1007 return tok_identifier;
1008 } else if (isdigit(c) || c == '-') {
1009 unsigned number = 0;
1012 /* we support negative numbers as well, so one can easily set all bits with -1 */
1021 if (c == 'x' || c == 'X') {
1028 number = (number << 4) | (c - '0');
1030 number = (number << 4) | (toupper(c) - 'A' + 10);
1033 lexer.number = number;
1040 number = number * 10 + (c - '0');
1044 lexer.number = sign ? 0 - number : number;
1052 void firm_debug(const char *cmd)
1054 char name[1024], fname[1024];
1062 token = get_token();
1069 token = get_token();
1070 if (token != tok_number)
1072 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1076 token = get_token();
1077 if (token != tok_number)
1079 break_on_nr(lexer.number, BP_ON_REPLACE);
1083 token = get_token();
1084 if (token != tok_number)
1086 break_on_nr(lexer.number, BP_ON_LOWER);
1090 token = get_token();
1092 if (token == tok_number)
1093 break_on_nr(lexer.number, BP_ON_REMIRG);
1094 else if (token == tok_identifier) {
1095 len = MIN(lexer.len, 1023);
1096 strncpy(name, lexer.s, len);
1098 break_on_ident(name, BP_ON_REMIRG);
1104 token = get_token();
1106 if (token == tok_number)
1107 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1108 else if (token == tok_identifier) {
1109 len = MIN(lexer.len, 1023);
1110 strncpy(name, lexer.s, len);
1112 break_on_ident(name, BP_ON_NEW_ENT);
1118 token = get_token();
1120 if (token == tok_number)
1121 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1122 else if (token == tok_identifier) {
1123 len = MIN(lexer.len, 1023);
1124 strncpy(name, lexer.s, len);
1126 break_on_ident(name, BP_ON_NEW_TYPE);
1132 token = get_token();
1134 if (token == tok_number)
1135 show_firm_object(find_type_nr(lexer.number));
1136 else if (token == tok_identifier) {
1137 len = MIN(lexer.len, 1023);
1138 strncpy(name, lexer.s, len);
1140 show_firm_object(find_type_name(name));
1146 token = get_token();
1148 if (token == tok_number)
1149 show_firm_object(find_entity_nr(lexer.number));
1150 else if (token == tok_identifier) {
1151 len = MIN(lexer.len, 1023);
1152 strncpy(name, lexer.s, len);
1154 show_firm_object(find_entity_name(name));
1168 token = get_token();
1169 if (token != tok_number)
1171 bp_activate(lexer.number, 1);
1175 token = get_token();
1176 if (token != tok_number)
1178 bp_activate(lexer.number, 0);
1182 token = get_token();
1183 if (token != tok_identifier)
1185 len = MIN(lexer.len, 1023);
1186 strncpy(name, lexer.s, len);
1189 token = get_token();
1190 if (token != tok_number)
1192 set_dbg_level(name, lexer.number);
1196 token = get_token();
1197 if (token != tok_identifier)
1199 len = MIN(lexer.len, 1023);
1200 strncpy(name, lexer.s, len);
1203 token = get_token();
1204 if (token != tok_number)
1206 set_dbg_level(name, (1 << lexer.number) - 1);
1209 case tok_setoutfile:
1210 token = get_token();
1211 if (token != tok_identifier)
1213 len = MIN(lexer.len, 1023);
1214 strncpy(name, lexer.s, len);
1217 token = get_token();
1218 if (token != tok_identifier)
1220 len = MIN(lexer.len, 1023);
1221 strncpy(fname, lexer.s, len);
1223 set_dbg_outfile(name, fname);
1226 token = get_token();
1227 if (token != tok_identifier)
1229 len = MIN(lexer.len, 1023);
1230 strncpy(name, lexer.s, len);
1235 token = get_token();
1236 if (token != tok_identifier)
1238 len = MIN(lexer.len, 1023);
1239 strncpy(name, lexer.s, len);
1251 printf("Error: before %s\n", lexer.tok_start);
1256 token = get_token();
1257 if (token == tok_eof)
1266 void firm_init_debugger(void)
1270 bp_numbers = new_set(cmp_nr_bp, 8);
1271 bp_idents = new_set(cmp_ident_bp, 8);
1273 env = getenv("FIRMDBG");
1282 } /* firm_init_debugger */
1285 * A gdb helper function to print firm objects.
1287 const char *gdb_node_helper(void *firm_object)
1289 static char buf[1024];
1290 ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
1294 const char *gdb_tarval_helper(void *tv_object)
1296 static char buf[1024];
1297 ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
1301 const char *gdb_out_edge_helper(const ir_node *node)
1303 static char buf[4*1024];
1306 size_t len = sizeof(buf);
1307 const ir_edge_t *edge;
1308 foreach_out_edge(node, edge) {
1309 ir_node *n = get_edge_src_irn(edge);
1311 ir_snprintf(b, len, "%+F ", n);
1322 /* some picky compiler do not allow empty files */
1323 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1328 * @page debugger The Firm debugger extension
1330 * Firm contains a debugger extension. This allows to set debugger breakpoints
1331 * an various events.
1332 * The extension uses a text interface which can be accessed from most debuggers.
1333 * More than one command can be given separated by ';'.
1335 * @section sec_cmd Supported commands
1337 * Historically all debugger commands start with a dot. This isn't needed in newer
1338 * versions, but still supported, ie the commands ".init" and "init" are equal.
1339 * The following commands are currently supported:
1343 * Break immediately after the debugger extension was initialized.
1344 * Typically this command is used in the environment to stop the execution
1345 * of a Firm compiler right after the initialization, like this:
1347 * $export FIRMDBG=".init"
1351 * Break if a new IR-node with node number nr was created.
1352 * Typically used to find the place where wrong nodes are created.
1356 * Break before IR-node with node number nr is replaced by another node.
1360 * Break before IR-node with node number nr is lowered.
1364 * Break if the irg with graph number nr is deleted.
1368 * Break if the irg of entity name is deleted.
1372 * Break if the entity with number nr was created.
1376 * Break if the entity name was created.
1380 * Break if the type with number nr was created.
1384 * Break if the type name was created.
1388 * Show all Firm internal breakpoints.
1392 * Enables breakpoint nr.
1396 * Disables breakpoint nr.
1400 * Show the content of entity nr.
1404 * Show the content of entity name.
1408 * Show the content of type nr.
1412 * Show the content of type name.
1414 * @b setmask name msk
1416 * Sets the debug module name to mask msk.
1418 * @b setlvl name lvl
1420 * Sets the debug module name to level lvl.
1422 * @b setoutfile name file
1424 * Redirects debug output of module name to file.
1428 * Prints address and graph number of a method given by its name.
1432 * Prints address and graph number of a method given by its linker name.
1436 * List all commands.
1439 * The Firm debugger extension can be accessed using the function firm_debug().
1440 * The following example shows how to set a creation breakpoint in GDB when
1441 * node 2101 is created.
1443 * -# set FIRMDBG="init"
1444 * -# start gdb with your compiler
1445 * -# after gdb breaks, issue
1447 * call firm_debug("create 2101")
1449 * On the console the following text should be issued:
1451 * Firm BP 1: creation of Node 2101
1454 * @section gdb_macro GDB macro
1456 * Add the following to your .gdbinit file:
1459 # define firm "cmd" Firm debugger extension
1462 call firm_debug($arg0)
1466 * Then, all Firm debugger extension commands can be accessed in the gdb
1467 * console using the firm prefix, eg.:
1469 * firm "create 2101"