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
48 #include "irgraph_t.h"
52 #include "iredges_t.h"
58 /* Break into the debugger. The Win32 way. */
59 void firm_debug_break(void)
63 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
64 /* Break into the debugger. The ia32/x86_64 way under GCC. */
65 void firm_debug_break(void)
67 __asm__ __volatile__("int3");
70 /* Break into the debugger. Poor Unix way. */
71 void firm_debug_break(void)
77 /** supported breakpoint kinds */
79 BP_NR = 'n', /**< break on node number. */
80 BP_IDENT = 'i' /**< break on ident. */
84 * Reasons for node number breakpoints.
86 typedef enum bp_reasons_t {
87 BP_ON_NEW_NODE, /**< break if node with number is created */
88 BP_ON_REPLACE, /**< break if node with number is replaced */
89 BP_ON_LOWER, /**< break if node with number is lowered */
90 BP_ON_REMIRG, /**< break if an IRG is removed */
91 BP_ON_NEW_ENT, /**< break if a new entity is created */
92 BP_ON_NEW_TYPE, /**< break if a new type 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, ...)
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_NODE;
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_ENT;
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_TYPE;
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_NODE: return "node 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_ON_NEW_TYPE: return "type creation";
412 case BP_MAX_REASON: break;
414 panic("unsupported reason");
418 * Compare two number breakpoints.
420 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
422 const bp_nr_t *e1 = (const bp_nr_t*)elt;
423 const bp_nr_t *e2 = (const bp_nr_t*)key;
426 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
430 * Compare two ident breakpoints.
432 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
434 const bp_ident_t *e1 = (const bp_ident_t*)elt;
435 const bp_ident_t *e2 = (const bp_ident_t*)key;
438 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
444 static void update_hooks(breakpoint *bp)
446 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
447 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
450 ++num_active_bp[bp->reason];
452 --num_active_bp[bp->reason];
454 if (num_active_bp[bp->reason] > 0) {
455 /* register the hooks on demand */
456 switch (bp->reason) {
457 CASE_ON(BP_ON_NEW_NODE, new_node);
458 CASE_ON(BP_ON_REPLACE, replace);
459 CASE_ON(BP_ON_LOWER, lower);
460 CASE_ON(BP_ON_REMIRG, free_graph);
461 CASE_ON(BP_ON_NEW_ENT, new_entity);
462 CASE_ON(BP_ON_NEW_TYPE, new_type);
468 /* unregister the hook on demand */
469 switch (bp->reason) {
470 CASE_OFF(BP_ON_NEW_NODE, new_node);
471 CASE_OFF(BP_ON_REPLACE, replace);
472 CASE_OFF(BP_ON_LOWER, lower);
473 CASE_OFF(BP_ON_REMIRG, free_graph);
474 CASE_OFF(BP_ON_NEW_ENT, new_entity);
475 CASE_OFF(BP_ON_NEW_TYPE, new_type);
485 * Break if nr is reached.
487 static void break_on_nr(long nr, bp_reasons_t reason)
494 key.bp.reason = reason;
497 elem = (bp_nr_t*)set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
499 if (elem->bp.bpnr == 0) {
500 /* new break point */
501 elem->bp.bpnr = ++bp_num;
502 elem->bp.next = bp_list;
505 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
507 update_hooks(&elem->bp);
512 * Break if ident name is reached.
514 static void break_on_ident(const char *name, bp_reasons_t reason)
516 bp_ident_t key, *elem;
518 key.bp.kind = BP_IDENT;
521 key.bp.reason = reason;
522 key.id = new_id_from_str(name);
524 elem = (bp_ident_t*)set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
526 if (elem->bp.bpnr == 0) {
527 /* new break point */
528 elem->bp.bpnr = ++bp_num;
529 elem->bp.next = bp_list;
532 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
534 update_hooks(&elem->bp);
539 * Sets/resets the active flag of breakpoint bp.
541 static void bp_activate(unsigned bp, int active)
545 for (p = bp_list; p; p = p->next) {
547 if (p->active != active) {
552 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
556 dbg_printf("Error: Firm BP %u not exists.\n", bp);
561 * Show a list of supported commands
563 static void show_commands(void)
565 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
566 "init break after initialization\n"
567 "create nr break if node nr was created\n"
568 "replace nr break if node nr is replaced by another node\n"
569 "lower nr break before node nr is lowered\n"
570 "remirg nr|name break if the irg of nr or entity name is deleted\n"
571 "newent nr|name break if the entity nr or name was created\n"
572 "newtype nr|name break if the type nr or name was created\n"
573 "bp show all breakpoints\n"
574 "enable nr enable breakpoint nr\n"
575 "disable nr disable breakpoint nr\n"
576 "showtype nr|name show content of the type nr or name\n"
577 "showent nr|name show content of the entity nr or name\n"
578 "setmask name msk sets the debug module name to mask msk\n"
579 "setlvl name lvl sets the debug module name to level lvl\n"
580 "setoutfile name file redirects debug output of module name to file\n"
581 "irgname name prints address and graph number of a method given by its name\n"
582 "irgldname ldname prints address and graph number of a method given by its ldname\n"
583 "help list all commands\n"
588 * Shows all Firm breakpoints.
590 static void show_bp(void)
597 dbg_printf("Firm Breakpoints:");
598 for (p = bp_list; p; p = p->next) {
600 dbg_printf("+\n BP %u: ", p->bpnr);
604 node_p = (bp_nr_t *)p;
605 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
609 ident_p = (bp_ident_t *)p;
610 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
614 dbg_printf(p->active ? "+enabled" : "+disabled");
616 dbg_printf(have_one ? "+\n" : "+ NONE\n");
620 * firm_dbg_register() expects that the name is stored persistent.
621 * So we need this little helper function
623 static firm_dbg_module_t *dbg_register(const char *name)
625 ident *id = new_id_from_str(name);
627 return firm_dbg_register(get_id_str(id));
631 * Sets the debug mask of module name to lvl
633 static void set_dbg_level(const char *name, unsigned lvl)
635 firm_dbg_module_t *module = dbg_register(name);
637 if (firm_dbg_get_mask(module) != lvl) {
638 firm_dbg_set_mask(module, lvl);
640 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
645 * Redirects the debug output of module name to fname
647 static void set_dbg_outfile(const char *name, const char *fname)
649 firm_dbg_module_t *module = dbg_register(name);
650 FILE *f = fopen(fname, "w");
657 firm_dbg_set_file(module, f);
658 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
662 * Show info about a firm thing.
664 static void show_firm_object(void *firm_thing)
668 if (firm_thing == NULL) {
669 fprintf(f, "<NULL>\n");
672 switch (get_kind(firm_thing)) {
674 fprintf(f, "BAD: (%p)\n", firm_thing);
677 dump_entity_to_file(f, (ir_entity*)firm_thing);
680 dump_type_to_file(f, (ir_type*)firm_thing);
688 case k_ir_compound_graph_path:
694 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
699 * Find a firm type by its number.
701 static ir_type *find_type_nr(long nr)
703 int i, n = get_irp_n_types();
706 for (i = 0; i < n; ++i) {
707 tp = get_irp_type(i);
708 if (get_type_nr(tp) == nr)
711 tp = get_glob_type();
712 if (get_type_nr(tp) == nr)
718 * Find a firm type by its name.
720 static ir_type *find_type_name(const char *name)
722 int i, n = get_irp_n_types();
725 for (i = 0; i < n; ++i) {
726 tp = get_irp_type(i);
727 if (!is_compound_type(tp))
730 if (strcmp(get_compound_name(tp), name) == 0)
733 tp = get_glob_type();
734 if (strcmp(get_compound_name(tp), name) == 0)
739 /** The environment for the entity search functions. */
740 typedef struct find_env {
742 long nr; /**< the number that is searched for */
743 const char *name; /**< the name that is searched for */
745 ir_entity *res; /**< the result */
749 * Type-walker: Find an entity with given number.
751 static void check_ent_nr(type_or_ent tore, void *ctx)
753 find_env_t *env = (find_env_t*)ctx;
755 if (is_entity(tore.ent)) {
756 if (get_entity_nr(tore.ent) == env->u.nr) {
763 * Type-walker: Find an entity with given name.
765 static void check_ent_name(type_or_ent tore, void *ctx)
767 find_env_t *env = (find_env_t*)ctx;
769 if (is_entity(tore.ent))
770 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
776 * Find a firm entity by its number.
778 static ir_entity *find_entity_nr(long nr)
784 type_walk(check_ent_nr, NULL, &env);
789 * Find a firm entity by its name.
791 static ir_entity *find_entity_name(const char *name)
797 type_walk(check_ent_name, NULL, &env);
802 * Search methods for a name.
804 static void show_by_name(type_or_ent tore, void *env)
806 ident *id = (ident *)env;
808 if (is_entity(tore.ent)) {
809 ir_entity *ent = tore.ent;
811 if (is_method_entity(ent)) {
812 if (get_entity_ident(ent) == id) {
813 ir_type *owner = get_entity_owner(ent);
814 ir_graph *irg = get_entity_irg(ent);
816 if (owner != get_glob_type()) {
817 printf("%s::%s", get_compound_name(owner), get_id_str(id));
819 printf("%s", get_id_str(id));
822 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
831 * Search methods for a ldname.
833 static void show_by_ldname(type_or_ent tore, void *env)
835 ident *id = (ident *)env;
837 if (is_entity(tore.ent)) {
838 ir_entity *ent = tore.ent;
840 if (is_method_entity(ent)) {
841 if (get_entity_ld_ident(ent) == id) {
842 ir_type *owner = get_entity_owner(ent);
843 ir_graph *irg = get_entity_irg(ent);
845 if (owner != get_glob_type()) {
846 printf("%s::%s", get_compound_name(owner), get_id_str(id));
848 printf("%s", get_id_str(id));
851 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
860 * prints the address and graph number of all irgs with given name
862 static void irg_name(const char *name)
864 ident *id = new_id_from_str(name);
866 type_walk(show_by_name, NULL, (void *)id);
870 * prints the address and graph number of all irgs with given ld_name
872 static void irg_ld_name(const char *name)
874 ident *id = new_id_from_str(name);
876 type_walk(show_by_ldname, NULL, (void *)id);
904 static const char *reserved[] = {
928 static struct lexer {
929 int has_token; /**< set if a token is cached. */
930 unsigned cur_token; /**< current token. */
931 unsigned number; /**< current token attribute. */
932 const char *s; /**< current token attribute. */
933 size_t len; /**< current token attribute. */
935 const char *curr_pos;
937 const char *tok_start;
941 * Initialize the lexer.
943 static void init_lexer(const char *input)
946 lexer.curr_pos = input;
947 lexer.end_pos = input + strlen(input);
952 * Get the next char from the input.
954 static char next_char(void)
956 if (lexer.curr_pos >= lexer.end_pos)
958 return *lexer.curr_pos++;
961 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
964 #define MIN(a, b) (a) < (b) ? (a) : (b)
969 static unsigned get_token(void)
974 /* skip white space */
977 } while (c != '\0' && isspace((unsigned char)c));
979 lexer.tok_start = lexer.curr_pos - 1;
980 if (c == '.' || isalpha((unsigned char)c)) {
981 /* command begins here */
983 const char* tok_start;
988 } while (isgraph((unsigned char)c));
991 tok_start = lexer.tok_start;
992 if (*tok_start == '.') {
996 for (i = ARRAY_SIZE(reserved); i-- != 0;) {
997 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
1002 lexer.s = lexer.tok_start;
1003 lexer.len = lexer.curr_pos - lexer.s;
1004 return tok_identifier;
1005 } else if (isdigit((unsigned char)c) || c == '-') {
1006 unsigned number = 0;
1009 /* we support negative numbers as well, so one can easily set all bits with -1 */
1018 if (c == 'x' || c == 'X') {
1022 if (! isxdigit((unsigned char)c))
1024 if (isdigit((unsigned char)c))
1025 number = (number << 4) | (c - '0');
1027 number = (number << 4) | (toupper((unsigned char)c) - 'A' + 10);
1030 lexer.number = number;
1035 if (! isdigit((unsigned char)c))
1037 number = number * 10 + (c - '0');
1041 lexer.number = sign ? 0 - number : number;
1049 void firm_debug(const char *cmd)
1051 char name[1024], fname[1024];
1059 token = get_token();
1066 token = get_token();
1067 if (token != tok_number)
1069 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1073 token = get_token();
1074 if (token != tok_number)
1076 break_on_nr(lexer.number, BP_ON_REPLACE);
1080 token = get_token();
1081 if (token != tok_number)
1083 break_on_nr(lexer.number, BP_ON_LOWER);
1087 token = get_token();
1089 if (token == tok_number)
1090 break_on_nr(lexer.number, BP_ON_REMIRG);
1091 else if (token == tok_identifier) {
1092 len = MIN(lexer.len, 1023);
1093 strncpy(name, lexer.s, len);
1095 break_on_ident(name, BP_ON_REMIRG);
1101 token = get_token();
1103 if (token == tok_number)
1104 break_on_nr(lexer.number, BP_ON_NEW_ENT);
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_NEW_ENT);
1115 token = get_token();
1117 if (token == tok_number)
1118 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
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_TYPE);
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);
1234 token = get_token();
1235 if (token != tok_identifier)
1237 len = MIN(lexer.len, 1023);
1238 strncpy(name, lexer.s, len);
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 const ir_edge_t *edge;
1313 foreach_out_edge(node, edge) {
1314 ir_node *n = get_edge_src_irn(edge);
1316 ir_snprintf(b, len, "%+F ", n);
1327 /* some picky compiler do not allow empty files */
1328 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1333 * @page debugger The Firm debugger extension
1335 * Firm contains a debugger extension. This allows to set debugger breakpoints
1336 * an various events.
1337 * The extension uses a text interface which can be accessed from most debuggers.
1338 * More than one command can be given separated by ';'.
1340 * @section sec_cmd Supported commands
1342 * Historically all debugger commands start with a dot. This isn't needed in newer
1343 * versions, but still supported, ie the commands ".init" and "init" are equal.
1344 * The following commands are currently supported:
1348 * Break immediately after the debugger extension was initialized.
1349 * Typically this command is used in the environment to stop the execution
1350 * of a Firm compiler right after the initialization, like this:
1352 * $export FIRMDBG=".init"
1356 * Break if a new IR-node with node number nr was created.
1357 * Typically used to find the place where wrong nodes are created.
1361 * Break before IR-node with node number nr is replaced by another node.
1365 * Break before IR-node with node number nr is lowered.
1369 * Break if the irg with graph number nr is deleted.
1373 * Break if the irg of entity name is deleted.
1377 * Break if the entity with number nr was created.
1381 * Break if the entity name was created.
1385 * Break if the type with number nr was created.
1389 * Break if the type name was created.
1393 * Show all Firm internal breakpoints.
1397 * Enables breakpoint nr.
1401 * Disables breakpoint nr.
1405 * Show the content of entity nr.
1409 * Show the content of entity name.
1413 * Show the content of type nr.
1417 * Show the content of type name.
1419 * @b setmask name msk
1421 * Sets the debug module name to mask msk.
1423 * @b setlvl name lvl
1425 * Sets the debug module name to level lvl.
1427 * @b setoutfile name file
1429 * Redirects debug output of module name to file.
1433 * Prints address and graph number of a method given by its name.
1437 * Prints address and graph number of a method given by its linker name.
1441 * List all commands.
1444 * The Firm debugger extension can be accessed using the function firm_debug().
1445 * The following example shows how to set a creation breakpoint in GDB when
1446 * node 2101 is created.
1448 * -# set FIRMDBG="init"
1449 * -# start gdb with your compiler
1450 * -# after gdb breaks, issue
1452 * call firm_debug("create 2101")
1454 * On the console the following text should be issued:
1456 * Firm BP 1: creation of Node 2101
1459 * @section gdb_macro GDB macro
1461 * Add the following to your .gdbinit file:
1464 # define firm "cmd" Firm debugger extension
1467 call firm_debug($arg0)
1471 * Then, all Firm debugger extension commands can be accessed in the gdb
1472 * console using the firm prefix, eg.:
1474 * firm "create 2101"