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
50 #include "irgraph_t.h"
54 #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_NODE, /**< break if node 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 */
93 BP_ON_NEW_TYPE, /**< break if a new type is created */
98 typedef struct _breakpoint {
99 bp_kind kind; /**< the kind of this break point */
100 unsigned bpnr; /**< break point number */
101 int active; /**< non-zero, if this break point is active */
102 bp_reasons_t reason; /**< reason for the breakpoint */
103 struct _breakpoint *next; /**< link to the next one */
106 /** A number breakpoint. */
108 breakpoint bp; /**< the breakpoint data */
109 long nr; /**< the node number */
112 /** Calculate the hash value for a node breakpoint. */
113 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
115 /** An ident breakpoint. */
117 breakpoint bp; /**< the breakpoint data */
118 ident *id; /**< the ident */
121 /** Calculate the hash value for an ident breakpoint. */
122 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
124 /** The set containing the breakpoints on node numbers. */
125 static set *bp_numbers;
127 /** The set containing the breakpoints on idents. */
128 static set *bp_idents;
130 /**< the list of all breakpoints */
131 static breakpoint *bp_list;
133 /** number of the current break point */
134 static unsigned bp_num = 0;
136 /** set if break on init command was issued. */
137 static int break_on_init = 0;
139 /** the hook entries for the Firm debugger module. */
140 static hook_entry_t debugger_hooks[hook_last];
142 /** number of active breakpoints to maintain hooks. */
143 static unsigned num_active_bp[BP_MAX_REASON];
146 * The debug message buffer
148 static char firm_dbg_msg_buf[2048];
151 * If set, the debug extension writes all output to the
152 * firm_dbg_msg_buf buffer
154 static int redir_output = 0;
157 * Is set to one, if the debug extension is active
159 static int is_active = 0;
161 /** hook the hook h with function fkt. */
162 #define HOOK(h, fkt) \
164 debugger_hooks[h].hook._##h = fkt; \
165 register_hook(h, &debugger_hooks[h]); \
168 /** unhook the hook h */
171 unregister_hook(h, &debugger_hooks[h]); \
172 debugger_hooks[h].hook._##h = NULL; \
175 /** returns non-zero if a entry hook h is used */
176 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
178 /* some macros needed to create the info string */
179 #define _DBG_VERSION(major, minor) #major "." #minor
180 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
181 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
183 /* the API version: change if needed */
184 #define FIRM_DBG_MAJOR 1
185 #define FIRM_DBG_MINOR 0
187 /** for automatic detection of the debug extension */
188 static const char firm_debug_info_string[] =
189 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
192 * Returns non-zero, if the debug extension is active
194 int firm_debug_active(void)
197 } /* firm_debug_active */
200 * Reset the debug text buffer.
202 static void reset_dbg_buf(void)
204 firm_dbg_msg_buf[0] = '\0';
205 } /* reset_dbg_buf */
208 * Add text to the debug text buffer.
210 static void add_to_dbg_buf(const char *buf)
212 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
213 } /* add_to_dbg_buf */
216 * Return the content of the debug text buffer.
218 * To be called from the debugger.
220 const char *firm_debug_text(void)
222 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
223 return firm_dbg_msg_buf;
224 } /* firm_debug_text */
229 static void dbg_printf(const char *fmt, ...)
241 ir_vsnprintf(buf, sizeof(buf), fmt, args);
251 * A new node is created.
253 * @param ctx the hook context
254 * @param irg the IR graph on which the node is created
255 * @param node the new IR node that was created
257 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
263 key.nr = get_irn_node_nr(node);
264 key.bp.reason = BP_ON_NEW_NODE;
266 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
267 if (elem && elem->bp.active) {
268 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
274 * A node is replaced.
276 * @param ctx the hook context
277 * @param old the IR node the is replaced
278 * @param nw the new IR node that will replace old
280 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
285 key.nr = get_irn_node_nr(old);
286 key.bp.reason = BP_ON_REPLACE;
288 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
289 if (elem && elem->bp.active) {
290 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
296 * A new node is lowered.
298 * @param ctx the hook context
299 * @param node the new IR node that will be lowered
301 static void dbg_lower(void *ctx, ir_node *node)
306 key.nr = get_irn_node_nr(node);
307 key.bp.reason = BP_ON_LOWER;
309 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
310 if (elem && elem->bp.active) {
311 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
317 * A graph will be deleted.
319 * @param ctx the hook context
320 * @param irg the IR graph that will be deleted
322 static void dbg_free_graph(void *ctx, ir_graph *irg)
327 key.nr = get_irg_graph_nr(irg);
328 key.bp.reason = BP_ON_REMIRG;
330 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
331 if (elem && elem->bp.active) {
332 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
337 bp_ident_t key, *elem;
338 ir_entity *ent = get_irg_entity(irg);
343 key.id = get_entity_ident(ent);
344 key.bp.reason = BP_ON_REMIRG;
346 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
347 if (elem && elem->bp.active) {
348 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
352 } /* dbg_free_graph */
355 * An entity was created.
357 * @param ctx the hook context
358 * @param ent the newly created entity
360 static void dbg_new_entity(void *ctx, ir_entity *ent)
364 bp_ident_t key, *elem;
366 key.id = get_entity_ident(ent);
367 key.bp.reason = BP_ON_NEW_ENT;
369 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
370 if (elem && elem->bp.active) {
371 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
378 key.nr = get_entity_nr(ent);
379 key.bp.reason = BP_ON_NEW_ENT;
381 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
382 if (elem && elem->bp.active) {
383 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
387 } /* dbg_new_entity */
390 * A type was created.
392 * @param ctx the hook context
393 * @param tp the newly created type
395 static void dbg_new_type(void *ctx, ir_type *tp)
401 key.nr = get_type_nr(tp);
402 key.bp.reason = BP_ON_NEW_TYPE;
404 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
405 if (elem && elem->bp.active) {
406 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
413 * Return the reason string.
415 static const char *reason_str(bp_reasons_t reason)
418 case BP_ON_NEW_NODE: return "node creation";
419 case BP_ON_REPLACE: return "node replace";
420 case BP_ON_LOWER: return "node lowering";
421 case BP_ON_REMIRG: return "removing IRG";
422 case BP_ON_NEW_ENT: return "entity creation";
423 case BP_ON_NEW_TYPE: return "type creation";
424 case BP_MAX_REASON: break;
426 panic("unsupported reason");
430 * Compare two number breakpoints.
432 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
434 const bp_nr_t *e1 = elt;
435 const bp_nr_t *e2 = key;
438 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
442 * Compare two ident breakpoints.
444 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
446 const bp_ident_t *e1 = elt;
447 const bp_ident_t *e2 = key;
450 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
456 static void update_hooks(breakpoint *bp)
458 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
459 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
462 ++num_active_bp[bp->reason];
464 --num_active_bp[bp->reason];
466 if (num_active_bp[bp->reason] > 0) {
467 /* register the hooks on demand */
468 switch (bp->reason) {
469 CASE_ON(BP_ON_NEW_NODE, new_node);
470 CASE_ON(BP_ON_REPLACE, replace);
471 CASE_ON(BP_ON_LOWER, lower);
472 CASE_ON(BP_ON_REMIRG, free_graph);
473 CASE_ON(BP_ON_NEW_ENT, new_entity);
474 CASE_ON(BP_ON_NEW_TYPE, new_type);
480 /* unregister the hook on demand */
481 switch (bp->reason) {
482 CASE_OFF(BP_ON_NEW_NODE, new_node);
483 CASE_OFF(BP_ON_REPLACE, replace);
484 CASE_OFF(BP_ON_LOWER, lower);
485 CASE_OFF(BP_ON_REMIRG, free_graph);
486 CASE_OFF(BP_ON_NEW_ENT, new_entity);
487 CASE_OFF(BP_ON_NEW_TYPE, new_type);
497 * Break if nr is reached.
499 static void break_on_nr(long nr, bp_reasons_t reason)
506 key.bp.reason = reason;
509 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
511 if (elem->bp.bpnr == 0) {
512 /* new break point */
513 elem->bp.bpnr = ++bp_num;
514 elem->bp.next = bp_list;
517 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
519 update_hooks(&elem->bp);
524 * Break if ident name is reached.
526 static void break_on_ident(const char *name, bp_reasons_t reason)
528 bp_ident_t key, *elem;
530 key.bp.kind = BP_IDENT;
533 key.bp.reason = reason;
534 key.id = new_id_from_str(name);
536 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
538 if (elem->bp.bpnr == 0) {
539 /* new break point */
540 elem->bp.bpnr = ++bp_num;
541 elem->bp.next = bp_list;
544 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
546 update_hooks(&elem->bp);
548 } /* break_on_ident */
551 * Sets/resets the active flag of breakpoint bp.
553 static void bp_activate(unsigned bp, int active)
557 for (p = bp_list; p; p = p->next) {
559 if (p->active != active) {
564 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
568 dbg_printf("Error: Firm BP %u not exists.\n", bp);
573 * Show a list of supported commands
575 static void show_commands(void)
577 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
578 "init break after initialization\n"
579 "create nr break if node nr was created\n"
580 "replace nr break if node nr is replaced by another node\n"
581 "lower nr break before node nr is lowered\n"
582 "remirg nr|name break if the irg of nr or entity name is deleted\n"
583 "newent nr|name break if the entity nr or name was created\n"
584 "newtype nr|name break if the type nr or name was created\n"
585 "bp show all breakpoints\n"
586 "enable nr enable breakpoint nr\n"
587 "disable nr disable breakpoint nr\n"
588 "showtype nr|name show content of the type nr or name\n"
589 "showent nr|name show content of the entity nr or name\n"
590 "setmask name msk sets the debug module name to mask msk\n"
591 "setlvl name lvl sets the debug module name to level lvl\n"
592 "setoutfile name file redirects debug output of module name to file\n"
593 "irgname name prints address and graph number of a method given by its name\n"
594 "irgldname ldname prints address and graph number of a method given by its ldname\n"
595 "help list all commands\n"
597 } /* show_commands */
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);
654 } /* set_dbg_level */
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);
671 } /* set_dbg_outfile */
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, firm_thing, dump_verbosity_max);
692 dump_type_to_file(f, firm_thing, dump_verbosity_max);
700 case k_ir_compound_graph_path:
706 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
708 } /* show_firm_object */
711 * Find a firm type by its number.
713 static ir_type *find_type_nr(long nr)
715 int i, n = get_irp_n_types();
718 for (i = 0; i < n; ++i) {
719 tp = get_irp_type(i);
720 if (get_type_nr(tp) == nr)
723 tp = get_glob_type();
724 if (get_type_nr(tp) == nr)
730 * Find a firm type by its name.
732 static ir_type *find_type_name(const char *name)
734 int i, n = get_irp_n_types();
737 for (i = 0; i < n; ++i) {
738 tp = get_irp_type(i);
739 if (!is_compound_type(tp))
742 if (strcmp(get_compound_name(tp), name) == 0)
745 tp = get_glob_type();
746 if (strcmp(get_compound_name(tp), name) == 0)
749 } /* find_type_name */
751 /** The environment for the entity search functions. */
752 typedef struct find_env {
754 long nr; /**< the number that is searched for */
755 const char *name; /**< the name that is searched for */
757 ir_entity *res; /**< the result */
761 * Type-walker: Find an entity with given number.
763 static void check_ent_nr(type_or_ent tore, void *ctx)
765 find_env_t *env = ctx;
767 if (is_entity(tore.ent)) {
768 if (get_entity_nr(tore.ent) == env->u.nr) {
775 * Type-walker: Find an entity with given name.
777 static void check_ent_name(type_or_ent tore, void *ctx)
779 find_env_t *env = ctx;
781 if (is_entity(tore.ent))
782 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
785 } /* check_ent_name */
788 * Find a firm entity by its number.
790 static ir_entity *find_entity_nr(long nr)
796 type_walk(check_ent_nr, NULL, &env);
798 } /* find_entity_nr */
801 * Find a firm entity by its name.
803 static ir_entity *find_entity_name(const char *name)
809 type_walk(check_ent_name, NULL, &env);
811 } /* find_entity_name */
814 * Search methods for a name.
816 static void show_by_name(type_or_ent tore, void *env)
818 ident *id = (ident *)env;
820 if (is_entity(tore.ent)) {
821 ir_entity *ent = tore.ent;
823 if (is_method_entity(ent)) {
824 if (get_entity_ident(ent) == id) {
825 ir_type *owner = get_entity_owner(ent);
826 ir_graph *irg = get_entity_irg(ent);
828 if (owner != get_glob_type()) {
829 printf("%s::%s", get_compound_name(owner), get_id_str(id));
831 printf("%s", get_id_str(id));
834 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
843 * Search methods for a ldname.
845 static void show_by_ldname(type_or_ent tore, void *env)
847 ident *id = (ident *)env;
849 if (is_entity(tore.ent)) {
850 ir_entity *ent = tore.ent;
852 if (is_method_entity(ent)) {
853 if (get_entity_ld_ident(ent) == id) {
854 ir_type *owner = get_entity_owner(ent);
855 ir_graph *irg = get_entity_irg(ent);
857 if (owner != get_glob_type()) {
858 printf("%s::%s", get_compound_name(owner), get_id_str(id));
860 printf("%s", get_id_str(id));
863 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
869 } /* show_by_ldname */
872 * prints the address and graph number of all irgs with given name
874 static void irg_name(const char *name)
876 ident *id = new_id_from_str(name);
878 type_walk(show_by_name, NULL, (void *)id);
882 * prints the address and graph number of all irgs with given ld_name
884 static void irg_ld_name(const char *name)
886 ident *id = new_id_from_str(name);
888 type_walk(show_by_ldname, NULL, (void *)id);
916 static const char *reserved[] = {
940 static struct lexer {
941 int has_token; /**< set if a token is cached. */
942 unsigned cur_token; /**< current token. */
943 unsigned number; /**< current token attribute. */
944 const char *s; /**< current token attribute. */
945 unsigned len; /**< current token attribute. */
947 const char *curr_pos;
949 const char *tok_start;
953 * Initialize the lexer.
955 static void init_lexer(const char *input)
958 lexer.curr_pos = input;
959 lexer.end_pos = input + strlen(input);
964 * Get the next char from the input.
966 static char next_char(void)
968 if (lexer.curr_pos >= lexer.end_pos)
970 return *lexer.curr_pos++;
973 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
976 #define MIN(a, b) (a) < (b) ? (a) : (b)
981 static unsigned get_token(void)
986 /* skip white space */
989 } while (c != '\0' && isspace(c));
991 lexer.tok_start = lexer.curr_pos - 1;
992 if (c == '.' || isalpha(c)) {
993 /* command begins here */
995 const char* tok_start;
1000 } while (isgraph(c));
1003 tok_start = lexer.tok_start;
1004 if (*tok_start == '.') {
1008 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
1009 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
1014 lexer.s = lexer.tok_start;
1015 lexer.len = lexer.curr_pos - lexer.s;
1016 return tok_identifier;
1017 } else if (isdigit(c) || c == '-') {
1018 unsigned number = 0;
1021 /* we support negative numbers as well, so one can easily set all bits with -1 */
1030 if (c == 'x' || c == 'X') {
1037 number = (number << 4) | (c - '0');
1039 number = (number << 4) | (toupper(c) - 'A' + 10);
1042 lexer.number = number;
1049 number = number * 10 + (c - '0');
1053 lexer.number = sign ? 0 - number : number;
1062 * High level function to use from debugger interface
1064 * See show_commands() for supported commands.
1066 void firm_debug(const char *cmd)
1068 char name[1024], fname[1024];
1076 token = get_token();
1083 token = get_token();
1084 if (token != tok_number)
1086 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1090 token = get_token();
1091 if (token != tok_number)
1093 break_on_nr(lexer.number, BP_ON_REPLACE);
1097 token = get_token();
1098 if (token != tok_number)
1100 break_on_nr(lexer.number, BP_ON_LOWER);
1104 token = get_token();
1106 if (token == tok_number)
1107 break_on_nr(lexer.number, BP_ON_REMIRG);
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_REMIRG);
1118 token = get_token();
1120 if (token == tok_number)
1121 break_on_nr(lexer.number, BP_ON_NEW_ENT);
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_ENT);
1132 token = get_token();
1134 if (token == tok_number)
1135 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1136 else if (token == tok_identifier) {
1137 len = MIN(lexer.len, 1023);
1138 strncpy(name, lexer.s, len);
1140 break_on_ident(name, BP_ON_NEW_TYPE);
1146 token = get_token();
1148 if (token == tok_number)
1149 show_firm_object(find_type_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_type_name(name));
1160 token = get_token();
1162 if (token == tok_number)
1163 show_firm_object(find_entity_nr(lexer.number));
1164 else if (token == tok_identifier) {
1165 len = MIN(lexer.len, 1023);
1166 strncpy(name, lexer.s, len);
1168 show_firm_object(find_entity_name(name));
1182 token = get_token();
1183 if (token != tok_number)
1185 bp_activate(lexer.number, 1);
1189 token = get_token();
1190 if (token != tok_number)
1192 bp_activate(lexer.number, 0);
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, lexer.number);
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_number)
1220 set_dbg_level(name, (1 << lexer.number) - 1);
1223 case tok_setoutfile:
1224 token = get_token();
1225 if (token != tok_identifier)
1227 len = MIN(lexer.len, 1023);
1228 strncpy(name, lexer.s, len);
1231 token = get_token();
1232 if (token != tok_identifier)
1234 len = MIN(lexer.len, 1023);
1235 strncpy(fname, lexer.s, len);
1237 set_dbg_outfile(name, fname);
1240 token = get_token();
1241 if (token != tok_identifier)
1243 len = MIN(lexer.len, 1023);
1244 strncpy(name, lexer.s, len);
1249 token = get_token();
1250 if (token != tok_identifier)
1252 len = MIN(lexer.len, 1023);
1253 strncpy(name, lexer.s, len);
1265 printf("Error: before %s\n", lexer.tok_start);
1270 token = get_token();
1271 if (token == tok_eof)
1280 /* creates the debugger tables */
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");
1297 } /* firm_init_debugger */
1300 * A gdb helper function to print firm objects.
1302 const char *gdb_node_helper(void *firm_object)
1304 static char buf[1024];
1305 ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
1310 * A gdb helper function to print tarvals.
1312 const char *gdb_tarval_helper(void *tv_object)
1314 static char buf[1024];
1315 ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
1319 const char *gdb_out_edge_helper(const ir_node *node)
1321 static char buf[4*1024];
1324 size_t len = sizeof(buf);
1325 const ir_edge_t *edge;
1326 foreach_out_edge(node, edge) {
1327 ir_node *n = get_edge_src_irn(edge);
1329 ir_snprintf(b, len, "%+F ", n);
1340 /* some picky compiler do not allow empty files */
1341 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1346 * @page debugger The Firm debugger extension
1348 * Firm contains a debugger extension. This allows to set debugger breakpoints
1349 * an various events.
1350 * The extension uses a text interface which can be accessed from most debuggers.
1351 * More than one command can be given separated by ';'.
1353 * @section sec_cmd Supported commands
1355 * Historically all debugger commands start with a dot. This isn't needed in newer
1356 * versions, but still supported, ie the commands ".init" and "init" are equal.
1357 * The following commands are currently supported:
1361 * Break immediately after the debugger extension was initialized.
1362 * Typically this command is used in the environment to stop the execution
1363 * of a Firm compiler right after the initialization, like this:
1365 * $export FIRMDBG=".init"
1369 * Break if a new IR-node with node number nr was created.
1370 * Typically used to find the place where wrong nodes are created.
1374 * Break before IR-node with node number nr is replaced by another node.
1378 * Break before IR-node with node number nr is lowered.
1382 * Break if the irg with graph number nr is deleted.
1386 * Break if the irg of entity name is deleted.
1390 * Break if the entity with number nr was created.
1394 * Break if the entity name was created.
1398 * Break if the type with number nr was created.
1402 * Break if the type name was created.
1406 * Show all Firm internal breakpoints.
1410 * Enables breakpoint nr.
1414 * Disables breakpoint nr.
1418 * Show the content of entity nr.
1422 * Show the content of entity name.
1426 * Show the content of type nr.
1430 * Show the content of type name.
1432 * @b setmask name msk
1434 * Sets the debug module name to mask msk.
1436 * @b setlvl name lvl
1438 * Sets the debug module name to level lvl.
1440 * @b setoutfile name file
1442 * Redirects debug output of module name to file.
1446 * Prints address and graph number of a method given by its name.
1450 * Prints address and graph number of a method given by its linker name.
1454 * List all commands.
1457 * The Firm debugger extension can be accessed using the function firm_debug().
1458 * The following example shows how to set a creation breakpoint in GDB when
1459 * node 2101 is created.
1461 * -# set FIRMDBG="init"
1462 * -# start gdb with your compiler
1463 * -# after gdb breaks, issue
1465 * call firm_debug("create 2101")
1467 * On the console the following text should be issued:
1469 * Firm BP 1: creation of Node 2101
1472 * @section gdb_macro GDB macro
1474 * Add the following to your .gdbinit file:
1477 # define firm "cmd" Firm debugger extension
1480 call firm_debug($arg0)
1484 * Then, all Firm debugger extension commands can be accessed in the gdb
1485 * console using the firm prefix, eg.:
1487 * firm "create 2101"