3 * File name: ir/debug/debugger.c
4 * Purpose: Helper function for integerated debug support
9 * Copyright: (c) 2001-2007 Universität Karlsruhe
10 * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE.
19 #define WIN32_LEAN_AND_MEAN
22 #define strncasecmp strnicmp
41 #include "irgraph_t.h"
49 /* Break into the debugger. The Win32 way. */
50 void firm_debug_break(void) {
53 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
54 /* Break into the debugger. The ia32/x86_64 way under GCC. */
55 void firm_debug_break(void) {
56 __asm__ __volatile__("int3");
59 /* Break into the debugger. Poor Unix way. */
60 void firm_debug_break(void) {
65 /** supported breakpoint kinds */
67 BP_NR = 'n', /**< break on node number. */
68 BP_IDENT = 'i' /**< break on ident. */
72 * Reasons for node number breakpoints.
74 typedef enum _bp_reasons_t {
75 BP_ON_NEW_NODE, /**< break if node with number is created */
76 BP_ON_REPLACE, /**< break if node with number is replaced */
77 BP_ON_LOWER, /**< break if node with number is lowered */
78 BP_ON_REMIRG, /**< break if an IRG is removed */
79 BP_ON_NEW_ENT, /**< break if a new entity is created */
80 BP_ON_NEW_TYPE, /**< break if a new type is created */
85 typedef struct _breakpoint {
86 bp_kind kind; /**< the kind of this break point */
87 unsigned bpnr; /**< break point number */
88 int active; /**< non-zero, if this break point is active */
89 bp_reasons_t reason; /**< reason for the breakpoint */
90 struct _breakpoint *next; /**< link to the next one */
93 /** A number breakpoint. */
95 breakpoint bp; /**< the breakpoint data */
96 long nr; /**< the node number */
99 /** Calculate the hash value for a node breakpoint. */
100 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
102 /** An ident breakpoint. */
104 breakpoint bp; /**< the breakpoint data */
105 ident *id; /**< the ident */
108 /** Calculate the hash value for an ident breakpoint. */
109 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
111 /** The set containing the breakpoints on node numbers. */
112 static set *bp_numbers;
114 /** The set containing the breakpoints on idents. */
115 static set *bp_idents;
117 /**< the list of all breakpoints */
118 static breakpoint *bp_list;
120 /** number of the current break point */
121 static unsigned bp_num = 0;
123 /** set if break on init command was issued. */
124 static int break_on_init = 0;
126 /** the hook entries for the Firm debugger module. */
127 static hook_entry_t debugger_hooks[hook_last];
129 /** number of active breakpoints to maintain hooks. */
130 static unsigned num_active_bp[BP_MAX_REASON];
133 * The debug message buffer
135 static char firm_dbg_msg_buf[2048];
138 * If set, the debug extension writes all output to the
139 * firm_dbg_msg_buf buffer
141 static int redir_output = 0;
144 * Is set to one, if the debug extension is active
146 static int is_active = 0;
148 /** hook the hook h with function fkt. */
149 #define HOOK(h, fkt) \
151 debugger_hooks[h].hook._##h = fkt; \
152 register_hook(h, &debugger_hooks[h]); \
155 /** unhook the hook h */
158 unregister_hook(h, &debugger_hooks[h]); \
159 debugger_hooks[h].hook._##h = NULL; \
162 /** returns non-zero if a entry hook h is used */
163 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
165 /* some macros needed to create the info string */
166 #define _DBG_VERSION(major, minor) #major "." #minor
167 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
168 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
170 /* the API version: change if needed */
171 #define FIRM_DBG_MAJOR 1
172 #define FIRM_DBG_MINOR 0
174 /** for automatic detection of the debug extension */
175 static const char *firm_debug_info_string =
176 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
179 * Returns non-zero, if the debug extension is active
181 int firm_debug_active(void) {
183 } /* firm_debug_active */
186 * Reset the debug text buffer.
188 static void reset_dbg_buf(void) {
189 firm_dbg_msg_buf[0] = '\0';
190 } /* reset_dbg_buf */
193 * Add text to the debug text buffer.
195 static void add_to_dbg_buf(const char *buf) {
196 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
197 } /* add_to_dbg_buf */
200 * Return the content of the debug text buffer.
202 * To be called from the debugger.
204 const char *firm_debug_text(void) {
205 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
206 return firm_dbg_msg_buf;
207 } /* firm_debug_text */
212 static void dbg_printf(const char *fmt, ...)
224 ir_vsnprintf(buf, sizeof(buf), fmt, args);
234 * A new node is created.
236 * @param ctx the hook context
237 * @param irg the IR graph on which the node is created
238 * @param node the new IR node that was created
240 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
244 key.nr = get_irn_node_nr(node);
245 key.bp.reason = BP_ON_NEW_NODE;
247 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
248 if (elem && elem->bp.active) {
249 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
255 * A node is replaced.
257 * @param ctx the hook context
258 * @param old the IR node the is replaced
259 * @param nw the new IR node that will replace old
261 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
265 key.nr = get_irn_node_nr(old);
266 key.bp.reason = BP_ON_REPLACE;
268 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
269 if (elem && elem->bp.active) {
270 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
276 * A new node is lowered.
278 * @param ctx the hook context
279 * @param node the new IR node that will be lowered
281 static void dbg_lower(void *ctx, ir_node *node)
285 key.nr = get_irn_node_nr(node);
286 key.bp.reason = BP_ON_LOWER;
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 lowered\n", elem->bp.bpnr, node);
296 * A graph will be deleted.
298 * @param ctx the hook context
299 * @param irg the IR graph that will be deleted
301 static void dbg_free_graph(void *ctx, ir_graph *irg)
305 key.nr = get_irg_graph_nr(irg);
306 key.bp.reason = BP_ON_REMIRG;
308 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
309 if (elem && elem->bp.active) {
310 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
315 bp_ident_t key, *elem;
316 ir_entity *ent = get_irg_entity(irg);
321 key.id = get_entity_ident(ent);
322 key.bp.reason = BP_ON_REMIRG;
324 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
325 if (elem && elem->bp.active) {
326 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
330 } /* dbg_free_graph */
333 * An entity was created.
335 * @param ctx the hook context
336 * @param ent the newly created entity
338 static void dbg_new_entity(void *ctx, ir_entity *ent)
341 bp_ident_t key, *elem;
343 key.id = get_entity_ident(ent);
344 key.bp.reason = BP_ON_NEW_ENT;
346 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
347 if (elem && elem->bp.active) {
348 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
355 key.nr = get_entity_nr(ent);
356 key.bp.reason = BP_ON_NEW_ENT;
358 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
359 if (elem && elem->bp.active) {
360 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
364 } /* dbg_new_entity */
367 * A type was created.
369 * @param ctx the hook context
370 * @param tp the newly created type
372 static void dbg_new_type(void *ctx, ir_type *tp)
377 key.nr = get_type_nr(tp);
378 key.bp.reason = BP_ON_NEW_TYPE;
380 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
381 if (elem && elem->bp.active) {
382 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
387 bp_ident_t key, *elem;
389 key.id = get_type_ident(tp);
390 key.bp.reason = BP_ON_NEW_TYPE;
392 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
393 if (elem && elem->bp.active) {
394 dbg_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";
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 = elt;
423 const bp_nr_t *e2 = 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 = elt;
434 const bp_ident_t *e2 = key;
436 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
442 static void update_hooks(breakpoint *bp)
444 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
445 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
448 ++num_active_bp[bp->reason];
450 --num_active_bp[bp->reason];
452 if (num_active_bp[bp->reason] > 0) {
453 /* register the hooks on demand */
454 switch (bp->reason) {
455 CASE_ON(BP_ON_NEW_NODE, new_node);
456 CASE_ON(BP_ON_REPLACE, replace);
457 CASE_ON(BP_ON_LOWER, lower);
458 CASE_ON(BP_ON_REMIRG, free_graph);
459 CASE_ON(BP_ON_NEW_ENT, new_entity);
460 CASE_ON(BP_ON_NEW_TYPE, new_type);
466 /* unregister the hook on demand */
467 switch (bp->reason) {
468 CASE_OFF(BP_ON_NEW_NODE, new_node);
469 CASE_OFF(BP_ON_REPLACE, replace);
470 CASE_OFF(BP_ON_LOWER, lower);
471 CASE_OFF(BP_ON_REMIRG, free_graph);
472 CASE_OFF(BP_ON_NEW_ENT, new_entity);
473 CASE_OFF(BP_ON_NEW_TYPE, new_type);
483 * Break if nr is reached.
485 static void break_on_nr(long nr, bp_reasons_t reason)
492 key.bp.reason = reason;
495 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
497 if (elem->bp.bpnr == 0) {
498 /* new break point */
499 elem->bp.bpnr = ++bp_num;
500 elem->bp.next = bp_list;
503 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
505 update_hooks(&elem->bp);
510 * Break if ident name is reached.
512 static void break_on_ident(const char *name, bp_reasons_t reason) {
513 bp_ident_t key, *elem;
515 key.bp.kind = BP_IDENT;
518 key.bp.reason = reason;
519 key.id = new_id_from_str(name);
521 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
523 if (elem->bp.bpnr == 0) {
524 /* new break point */
525 elem->bp.bpnr = ++bp_num;
526 elem->bp.next = bp_list;
529 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
531 update_hooks(&elem->bp);
533 } /* break_on_ident */
536 * Sets/resets the active flag of breakpoint bp.
538 static void bp_activate(unsigned bp, int active)
542 for (p = bp_list; p; p = p->next) {
544 if (p->active != active) {
549 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
553 dbg_printf("Error: Firm BP %u not exists.\n", bp);
558 * Show a list of supported commands
560 static void show_commands(void) {
561 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
562 ".init break after initialization\n"
563 ".create nr break if node nr was created\n"
564 ".replace nr break if node nr is replaced by another node\n"
565 ".lower nr break before node nr is lowered\n"
566 ".remirg nr|name break if the irg of nr or entity name is deleted\n"
567 ".newent nr|name break if the entity nr or name was created\n"
568 ".newtype nr|name break if the type nr or name was created\n"
569 ".bp show all breakpoints\n"
570 ".enable nr enable breakpoint nr\n"
571 ".disable nr disable breakpoint nr\n"
572 ".showtype nr|name show content of the type nr or name\n"
573 ".showent nr|name show content of the entity nr or name\n"
574 ".setmask name msk sets the debug module name to mask msk\n"
575 ".setlvl name lvl sets the debug module name to level lvl\n"
576 ".setoutfile name file redirects debug output of module name to file\n"
577 ".irgname name prints address and graph number of a method given by its name\n"
578 ".irgldname ldname prints address and graph number of a method given by its ldname\n"
579 ".help list all commands\n"
581 } /* show_commands */
584 * Shows all Firm breakpoints.
586 static void show_bp(void) {
592 dbg_printf("Firm Breakpoints:");
593 for (p = bp_list; p; p = p->next) {
595 dbg_printf("+\n BP %u: ", p->bpnr);
599 node_p = (bp_nr_t *)p;
600 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
604 ident_p = (bp_ident_t *)p;
605 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
609 dbg_printf(p->active ? "+enabled" : "+disabled");
611 dbg_printf(have_one ? "+\n" : "+ NONE\n");
615 * firm_dbg_register() expects that the name is stored persistent.
616 * So we need this little helper function
618 static firm_dbg_module_t *dbg_register(const char *name) {
619 ident *id = new_id_from_str(name);
621 return firm_dbg_register(get_id_str(id));
625 * Sets the debug mask of module name to lvl
627 static void set_dbg_level(const char *name, unsigned lvl)
629 firm_dbg_module_t *module = dbg_register(name);
631 if (firm_dbg_get_mask(module) != lvl) {
632 firm_dbg_set_mask(module, lvl);
634 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
636 } /* set_dbg_level */
639 * Redirects the debug output of module name to fname
641 static void set_dbg_outfile(const char *name, const char *fname)
643 firm_dbg_module_t *module = dbg_register(name);
644 FILE *f = fopen(fname, "w");
651 firm_dbg_set_file(module, f);
652 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
653 } /* set_dbg_outfile */
656 * Show info about a firm thing.
658 static void show_firm_object(void *firm_thing) {
661 if (firm_thing == NULL) {
662 fprintf(f, "<NULL>\n");
665 switch (get_kind(firm_thing)) {
667 fprintf(f, "BAD: (%p)\n", firm_thing);
670 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
673 dump_type_to_file(f, firm_thing, dump_verbosity_max);
681 case k_ir_compound_graph_path:
687 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
689 } /* show_firm_object */
692 * Find a firm type by its number.
694 static ir_type *find_type_nr(long nr) {
695 int i, n = get_irp_n_types();
698 for (i = 0; i < n; ++i) {
699 tp = get_irp_type(i);
700 if (get_type_nr(tp) == nr)
703 tp = get_glob_type();
704 if (get_type_nr(tp) == nr)
710 * Find a firm type by its name.
712 static ir_type *find_type_name(const char *name) {
713 int i, n = get_irp_n_types();
716 for (i = 0; i < n; ++i) {
717 tp = get_irp_type(i);
718 if (strcmp(get_type_name(tp), name) == 0)
721 tp = get_glob_type();
722 if (strcmp(get_type_name(tp), name) == 0)
725 } /* find_type_name */
727 /** The environment for the entity search functions. */
728 typedef struct find_env {
730 long nr; /**< the number that is searched for */
731 const char *name; /**< the name that is searched for */
733 ir_entity *res; /**< the result */
737 * Type-walker: Find an entity with given number.
739 static void check_ent_nr(type_or_ent *tore, void *ctx) {
740 ir_entity *ent = (ir_entity *)tore;
741 find_env_t *env = ctx;
744 if (get_entity_nr(ent) == env->u.nr) {
750 * Type-walker: Find an entity with given name.
752 static void check_ent_name(type_or_ent *tore, void *ctx) {
753 ir_entity *ent = (ir_entity *)tore;
754 find_env_t *env = ctx;
757 if (strcmp(get_entity_name(ent), env->u.name) == 0) {
760 } /* check_ent_name */
763 * Find a firm entity by its number.
765 static ir_entity *find_entity_nr(long nr) {
770 type_walk(check_ent_nr, NULL, &env);
772 } /* find_entity_nr */
775 * Find a firm entity by its name.
777 static ir_entity *find_entity_name(const char *name) {
782 type_walk(check_ent_name, NULL, &env);
784 } /* find_entity_name */
787 * Search methods for a name.
789 static void show_by_name(type_or_ent *tore, void *env) {
790 ident *id = (ident *)env;
792 if (is_entity(tore)) {
793 ir_entity *ent = (ir_entity *)tore;
795 if (is_method_entity(ent)) {
796 if (get_entity_ident(ent) == id) {
797 ir_type *owner = get_entity_owner(ent);
798 ir_graph *irg = get_entity_irg(ent);
800 if (owner != get_glob_type()) {
801 printf("%s::%s", get_type_name(owner), get_id_str(id));
803 printf("%s", get_id_str(id));
806 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
815 * Search methods for a ldname.
817 static void show_by_ldname(type_or_ent *tore, void *env) {
818 ident *id = (ident *)env;
820 if (is_entity(tore)) {
821 ir_entity *ent = (ir_entity *)tore;
823 if (is_method_entity(ent)) {
824 if (get_entity_ld_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_type_name(owner), get_id_str(id));
831 printf("%s", get_id_str(id));
834 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
840 } /* show_by_ldname */
843 * prints the address and graph number of all irgs with given name
845 static void irg_name(const char *name) {
846 ident *id = new_id_from_str(name);
848 type_walk(show_by_name, NULL, (void *)id);
852 * prints the address and graph number of all irgs with given ld_name
854 static void irg_ld_name(const char *name) {
855 ident *id = new_id_from_str(name);
857 type_walk(show_by_ldname, NULL, (void *)id);
885 static const char *reserved[] = {
909 static struct lexer {
910 int has_token; /**< set if a token is cached. */
911 unsigned cur_token; /**< current token. */
912 unsigned number; /**< current token attribute. */
913 const char *s; /**< current token attribute. */
914 unsigned len; /**< current token attribute. */
916 const char *curr_pos;
918 const char *tok_start;
922 * Initialize the lexer.
924 static void init_lexer(const char *input) {
926 lexer.curr_pos = input;
927 lexer.end_pos = input + strlen(input);
932 * Get the next char from the input.
934 static char next_char(void) {
935 if (lexer.curr_pos >= lexer.end_pos)
937 return *lexer.curr_pos++;
940 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
943 #define MIN(a, b) (a) < (b) ? (a) : (b)
948 static unsigned get_token(void) {
952 /* skip white space */
955 } while (c != '\0' && isspace(c));
957 lexer.tok_start = lexer.curr_pos - 1;
959 /* command begins here */
965 } while (isalpha(c));
969 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
970 if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
976 } else if (isalpha(c)) {
978 lexer.s = lexer.curr_pos - 1;
982 } while (c == '_' || isalnum(c));
984 lexer.len = lexer.curr_pos - lexer.s;
985 return tok_identifier;
986 } else if (isdigit(c)) {
992 if (c == 'x' || c == 'X') {
999 number = (number << 4) | (c - '0');
1001 number = (number << 4) | (toupper(c) - 'A' + 10);
1004 lexer.number = number;
1011 number = (number << 4) | (c - '0');
1015 lexer.number = number;
1024 * returns the next token.
1026 static unsigned next_token(void) {
1027 if (! lexer.has_token) {
1028 lexer.cur_token = get_token();
1029 lexer.has_token = 1;
1031 return lexer.cur_token;
1034 #define drop_token() lexer.has_token = 0
1037 * High level function to use from debugger interface
1039 * Supported commands:
1040 * .create nr break if node nr was created
1041 * .help list all commands
1043 void firm_debug(const char *cmd) {
1044 char name[1024], fname[1024];
1052 token = get_token();
1059 token = get_token();
1060 if (token != tok_number)
1062 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1066 token = get_token();
1067 if (token != tok_number)
1069 break_on_nr(lexer.number, BP_ON_REPLACE);
1073 token = get_token();
1074 if (token != tok_number)
1076 break_on_nr(lexer.number, BP_ON_LOWER);
1080 token = get_token();
1082 if (token == tok_number)
1083 break_on_nr(lexer.number, BP_ON_REMIRG);
1084 else if (token == tok_identifier) {
1085 len = MIN(lexer.len, 1023);
1086 strncpy(name, lexer.s, len);
1088 break_on_ident(name, BP_ON_REMIRG);
1094 token = get_token();
1096 if (token == tok_number)
1097 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1098 else if (token == tok_identifier) {
1099 len = MIN(lexer.len, 1023);
1100 strncpy(name, lexer.s, len);
1102 break_on_ident(name, BP_ON_NEW_ENT);
1108 token = get_token();
1110 if (token == tok_number)
1111 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1112 else if (token == tok_identifier) {
1113 len = MIN(lexer.len, 1023);
1114 strncpy(name, lexer.s, len);
1116 break_on_ident(name, BP_ON_NEW_TYPE);
1122 token = get_token();
1124 if (token == tok_number)
1125 show_firm_object(find_type_nr(lexer.number));
1126 else if (token == tok_identifier) {
1127 len = MIN(lexer.len, 1023);
1128 strncpy(name, lexer.s, len);
1130 show_firm_object(find_type_name(name));
1136 token = get_token();
1138 if (token == tok_number)
1139 show_firm_object(find_entity_nr(lexer.number));
1140 else if (token == tok_identifier) {
1141 len = MIN(lexer.len, 1023);
1142 strncpy(name, lexer.s, len);
1144 show_firm_object(find_entity_name(name));
1158 token = get_token();
1159 if (token != tok_number)
1161 bp_activate(lexer.number, 1);
1165 token = get_token();
1166 if (token != tok_number)
1168 bp_activate(lexer.number, 0);
1172 token = get_token();
1173 if (token != tok_identifier)
1175 len = MIN(lexer.len, 1023);
1176 strncpy(name, lexer.s, len);
1179 token = get_token();
1180 if (token != tok_number)
1182 set_dbg_level(name, lexer.number);
1186 token = get_token();
1187 if (token != tok_identifier)
1189 len = MIN(lexer.len, 1023);
1190 strncpy(name, lexer.s, len);
1193 token = get_token();
1194 if (token != tok_number)
1196 set_dbg_level(name, (1 << lexer.number) - 1);
1199 case tok_setoutfile:
1200 token = get_token();
1201 if (token != tok_identifier)
1203 len = MIN(lexer.len, 1023);
1204 strncpy(name, lexer.s, len);
1207 token = get_token();
1208 if (token != tok_identifier)
1210 len = MIN(lexer.len, 1023);
1211 strncpy(fname, lexer.s, len);
1213 set_dbg_outfile(name, fname);
1216 token = get_token();
1217 if (token != tok_identifier)
1219 len = MIN(lexer.len, 1023);
1220 strncpy(name, lexer.s, len);
1225 token = get_token();
1226 if (token != tok_identifier)
1228 len = MIN(lexer.len, 1023);
1229 strncpy(name, lexer.s, len);
1241 printf("Error: before %s\n", lexer.tok_start);
1246 token = get_token();
1247 if (token == tok_eof)
1256 /* creates the debugger tables */
1257 void firm_init_debugger(void)
1261 bp_numbers = new_set(cmp_nr_bp, 8);
1262 bp_idents = new_set(cmp_ident_bp, 8);
1264 env = getenv("FIRMDBG");
1273 } /* firm_init_debugger */
1277 /* some picky compiler do not allow empty files */
1278 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
1283 * @page debugger The Firm debugger extension
1285 * Firm contains a debugger extension. This allows to set debugger breakpoints
1286 * an various events.
1287 * The extension uses a text interface which can be accessed from most debuggers.
1288 * More than one command can be given separated by ';'.
1290 * @section sec_cmd Supported commands
1292 * The following commands are currently supported:
1296 * Break immediately after the debugger extension was initialized.
1297 * Typically this command is used in the environment to stop the execution
1298 * of a Firm compiler right after the initialization, like this:
1300 * $export FIRMDBG=".init"
1304 * Break if a new IR-node with node number nr was created.
1305 * Typically used to find the place where wrong nodes are created.
1309 * Break before IR-node with node number nr is replaced by another node.
1313 * Break before IR-node with node number nr is lowered.
1317 * Break if the irg with graph number nr is deleted.
1321 * Break if the irg of entity name is deleted.
1325 * Break if the entity with number nr was created.
1329 * Break if the entity name was created.
1333 * Break if the type with number nr was created.
1337 * Break if the type name was created.
1341 * Show all Firm internal breakpoints.
1345 * Enables breakpoint nr.
1349 * Disables breakpoint nr.
1353 * Show the content of entity nr.
1357 * Show the content of entity name.
1361 * Show the content of type nr.
1365 * Show the content of type name.
1367 * @b .setmask name msk
1369 * Sets the debug module name to mask msk.
1371 * @b .setlvl name lvl
1373 * Sets the debug module name to level lvl.
1375 * @b .setoutfile name file
1377 * Redirects debug output of module name to file.
1381 * Prints address and graph number of a method given by its name.
1383 * @b .irgldname name
1385 * Prints address and graph number of a method given by its linker name.
1389 * List all commands.
1392 * The Firm debugger extension can be accessed using the function firm_debug().
1393 * The following example shows how to set a creation breakpoint in GDB when
1394 * node 2101 is created.
1396 * -# set FIRMDBG=".init"
1397 * -# start gdb with your compiler
1398 * -# after gdb breaks, issue
1400 * call firm_debug(".create 2101")
1402 * On the console the following text should be issued:
1404 * Firm BP 1: creation of Node 2101
1407 * @section gdb_macro GDB macro
1409 * Add the following to your .gdbinit file:
1412 # define firm "cmd" Firm debugger extension
1415 call firm_debug($arg0)
1419 * Then, all Firm debugger extension commands can be accessed in the gdb
1420 * console using the firm prefix, eg.:
1422 * firm ".create 2101"