2 * Copyright (C) 1995-2007 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 integerated debug support
23 * @author Michael Beck
34 #define WIN32_LEAN_AND_MEAN
37 #define strncasecmp strnicmp
56 #include "irgraph_t.h"
64 /* Break into the debugger. The Win32 way. */
65 void firm_debug_break(void) {
68 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
69 /* Break into the debugger. The ia32/x86_64 way under GCC. */
70 void firm_debug_break(void) {
71 __asm__ __volatile__("int3");
74 /* Break into the debugger. Poor Unix way. */
75 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 *firm_debug_info_string =
191 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
194 * Returns non-zero, if the debug extension is active
196 int firm_debug_active(void) {
198 } /* firm_debug_active */
201 * Reset the debug text buffer.
203 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) {
211 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
212 } /* add_to_dbg_buf */
215 * Return the content of the debug text buffer.
217 * To be called from the debugger.
219 const char *firm_debug_text(void) {
220 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
221 return firm_dbg_msg_buf;
222 } /* firm_debug_text */
227 static void dbg_printf(const char *fmt, ...)
239 ir_vsnprintf(buf, sizeof(buf), fmt, args);
249 * A new node is created.
251 * @param ctx the hook context
252 * @param irg the IR graph on which the node is created
253 * @param node the new IR node that was created
255 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
259 key.nr = get_irn_node_nr(node);
260 key.bp.reason = BP_ON_NEW_NODE;
262 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
263 if (elem && elem->bp.active) {
264 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
270 * A node is replaced.
272 * @param ctx the hook context
273 * @param old the IR node the is replaced
274 * @param nw the new IR node that will replace old
276 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
280 key.nr = get_irn_node_nr(old);
281 key.bp.reason = BP_ON_REPLACE;
283 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
284 if (elem && elem->bp.active) {
285 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
291 * A new node is lowered.
293 * @param ctx the hook context
294 * @param node the new IR node that will be lowered
296 static void dbg_lower(void *ctx, ir_node *node)
300 key.nr = get_irn_node_nr(node);
301 key.bp.reason = BP_ON_LOWER;
303 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
304 if (elem && elem->bp.active) {
305 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
311 * A graph will be deleted.
313 * @param ctx the hook context
314 * @param irg the IR graph that will be deleted
316 static void dbg_free_graph(void *ctx, ir_graph *irg)
320 key.nr = get_irg_graph_nr(irg);
321 key.bp.reason = BP_ON_REMIRG;
323 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
324 if (elem && elem->bp.active) {
325 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
330 bp_ident_t key, *elem;
331 ir_entity *ent = get_irg_entity(irg);
336 key.id = get_entity_ident(ent);
337 key.bp.reason = BP_ON_REMIRG;
339 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
340 if (elem && elem->bp.active) {
341 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
345 } /* dbg_free_graph */
348 * An entity was created.
350 * @param ctx the hook context
351 * @param ent the newly created entity
353 static void dbg_new_entity(void *ctx, ir_entity *ent)
356 bp_ident_t key, *elem;
358 key.id = get_entity_ident(ent);
359 key.bp.reason = BP_ON_NEW_ENT;
361 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
362 if (elem && elem->bp.active) {
363 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
370 key.nr = get_entity_nr(ent);
371 key.bp.reason = BP_ON_NEW_ENT;
373 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
374 if (elem && elem->bp.active) {
375 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
379 } /* dbg_new_entity */
382 * A type was created.
384 * @param ctx the hook context
385 * @param tp the newly created type
387 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);
402 bp_ident_t key, *elem;
404 key.id = get_type_ident(tp);
405 key.bp.reason = BP_ON_NEW_TYPE;
407 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
408 if (elem && elem->bp.active) {
409 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
416 * Return the reason string.
418 static const char *reason_str(bp_reasons_t reason)
421 case BP_ON_NEW_NODE: return "node creation";
422 case BP_ON_REPLACE: return "node replace";
423 case BP_ON_LOWER: return "node lowering";
424 case BP_ON_REMIRG: return "removing IRG";
425 case BP_ON_NEW_ENT: return "entity creation";
426 case BP_ON_NEW_TYPE: return "type creation";
433 * Compare two number breakpoints.
435 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
437 const bp_nr_t *e1 = elt;
438 const bp_nr_t *e2 = key;
440 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
444 * Compare two ident breakpoints.
446 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
448 const bp_ident_t *e1 = elt;
449 const bp_ident_t *e2 = key;
451 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
457 static void update_hooks(breakpoint *bp)
459 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
460 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
463 ++num_active_bp[bp->reason];
465 --num_active_bp[bp->reason];
467 if (num_active_bp[bp->reason] > 0) {
468 /* register the hooks on demand */
469 switch (bp->reason) {
470 CASE_ON(BP_ON_NEW_NODE, new_node);
471 CASE_ON(BP_ON_REPLACE, replace);
472 CASE_ON(BP_ON_LOWER, lower);
473 CASE_ON(BP_ON_REMIRG, free_graph);
474 CASE_ON(BP_ON_NEW_ENT, new_entity);
475 CASE_ON(BP_ON_NEW_TYPE, new_type);
481 /* unregister the hook on demand */
482 switch (bp->reason) {
483 CASE_OFF(BP_ON_NEW_NODE, new_node);
484 CASE_OFF(BP_ON_REPLACE, replace);
485 CASE_OFF(BP_ON_LOWER, lower);
486 CASE_OFF(BP_ON_REMIRG, free_graph);
487 CASE_OFF(BP_ON_NEW_ENT, new_entity);
488 CASE_OFF(BP_ON_NEW_TYPE, new_type);
498 * Break if nr is reached.
500 static void break_on_nr(long nr, bp_reasons_t reason)
507 key.bp.reason = reason;
510 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
512 if (elem->bp.bpnr == 0) {
513 /* new break point */
514 elem->bp.bpnr = ++bp_num;
515 elem->bp.next = bp_list;
518 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
520 update_hooks(&elem->bp);
525 * Break if ident name is reached.
527 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) {
576 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
577 ".init break after initialization\n"
578 ".create nr break if node nr was created\n"
579 ".replace nr break if node nr is replaced by another node\n"
580 ".lower nr break before node nr is lowered\n"
581 ".remirg nr|name break if the irg of nr or entity name is deleted\n"
582 ".newent nr|name break if the entity nr or name was created\n"
583 ".newtype nr|name break if the type nr or name was created\n"
584 ".bp show all breakpoints\n"
585 ".enable nr enable breakpoint nr\n"
586 ".disable nr disable breakpoint nr\n"
587 ".showtype nr|name show content of the type nr or name\n"
588 ".showent nr|name show content of the entity nr or name\n"
589 ".setmask name msk sets the debug module name to mask msk\n"
590 ".setlvl name lvl sets the debug module name to level lvl\n"
591 ".setoutfile name file redirects debug output of module name to file\n"
592 ".irgname name prints address and graph number of a method given by its name\n"
593 ".irgldname ldname prints address and graph number of a method given by its ldname\n"
594 ".help list all commands\n"
596 } /* show_commands */
599 * Shows all Firm breakpoints.
601 static void show_bp(void) {
607 dbg_printf("Firm Breakpoints:");
608 for (p = bp_list; p; p = p->next) {
610 dbg_printf("+\n BP %u: ", p->bpnr);
614 node_p = (bp_nr_t *)p;
615 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
619 ident_p = (bp_ident_t *)p;
620 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
624 dbg_printf(p->active ? "+enabled" : "+disabled");
626 dbg_printf(have_one ? "+\n" : "+ NONE\n");
630 * firm_dbg_register() expects that the name is stored persistent.
631 * So we need this little helper function
633 static firm_dbg_module_t *dbg_register(const char *name) {
634 ident *id = new_id_from_str(name);
636 return firm_dbg_register(get_id_str(id));
640 * Sets the debug mask of module name to lvl
642 static void set_dbg_level(const char *name, unsigned lvl)
644 firm_dbg_module_t *module = dbg_register(name);
646 if (firm_dbg_get_mask(module) != lvl) {
647 firm_dbg_set_mask(module, lvl);
649 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
651 } /* set_dbg_level */
654 * Redirects the debug output of module name to fname
656 static void set_dbg_outfile(const char *name, const char *fname)
658 firm_dbg_module_t *module = dbg_register(name);
659 FILE *f = fopen(fname, "w");
666 firm_dbg_set_file(module, f);
667 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
668 } /* set_dbg_outfile */
671 * Show info about a firm thing.
673 static void show_firm_object(void *firm_thing) {
676 if (firm_thing == NULL) {
677 fprintf(f, "<NULL>\n");
680 switch (get_kind(firm_thing)) {
682 fprintf(f, "BAD: (%p)\n", firm_thing);
685 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
688 dump_type_to_file(f, firm_thing, dump_verbosity_max);
696 case k_ir_compound_graph_path:
702 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
704 } /* show_firm_object */
707 * Find a firm type by its number.
709 static ir_type *find_type_nr(long nr) {
710 int i, n = get_irp_n_types();
713 for (i = 0; i < n; ++i) {
714 tp = get_irp_type(i);
715 if (get_type_nr(tp) == nr)
718 tp = get_glob_type();
719 if (get_type_nr(tp) == nr)
725 * Find a firm type by its name.
727 static ir_type *find_type_name(const char *name) {
728 int i, n = get_irp_n_types();
731 for (i = 0; i < n; ++i) {
732 tp = get_irp_type(i);
733 if (strcmp(get_type_name(tp), name) == 0)
736 tp = get_glob_type();
737 if (strcmp(get_type_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) {
755 ir_entity *ent = (ir_entity *)tore;
756 find_env_t *env = ctx;
759 if (get_entity_nr(ent) == env->u.nr) {
765 * Type-walker: Find an entity with given name.
767 static void check_ent_name(type_or_ent *tore, void *ctx) {
768 ir_entity *ent = (ir_entity *)tore;
769 find_env_t *env = ctx;
772 if (strcmp(get_entity_name(ent), env->u.name) == 0) {
775 } /* check_ent_name */
778 * Find a firm entity by its number.
780 static ir_entity *find_entity_nr(long nr) {
785 type_walk(check_ent_nr, NULL, &env);
787 } /* find_entity_nr */
790 * Find a firm entity by its name.
792 static ir_entity *find_entity_name(const char *name) {
797 type_walk(check_ent_name, NULL, &env);
799 } /* find_entity_name */
802 * Search methods for a name.
804 static void show_by_name(type_or_ent *tore, void *env) {
805 ident *id = (ident *)env;
807 if (is_entity(tore)) {
808 ir_entity *ent = (ir_entity *)tore;
810 if (is_method_entity(ent)) {
811 if (get_entity_ident(ent) == id) {
812 ir_type *owner = get_entity_owner(ent);
813 ir_graph *irg = get_entity_irg(ent);
815 if (owner != get_glob_type()) {
816 printf("%s::%s", get_type_name(owner), get_id_str(id));
818 printf("%s", get_id_str(id));
821 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
830 * Search methods for a ldname.
832 static void show_by_ldname(type_or_ent *tore, void *env) {
833 ident *id = (ident *)env;
835 if (is_entity(tore)) {
836 ir_entity *ent = (ir_entity *)tore;
838 if (is_method_entity(ent)) {
839 if (get_entity_ld_ident(ent) == id) {
840 ir_type *owner = get_entity_owner(ent);
841 ir_graph *irg = get_entity_irg(ent);
843 if (owner != get_glob_type()) {
844 printf("%s::%s", get_type_name(owner), get_id_str(id));
846 printf("%s", get_id_str(id));
849 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
855 } /* show_by_ldname */
858 * prints the address and graph number of all irgs with given name
860 static void irg_name(const char *name) {
861 ident *id = new_id_from_str(name);
863 type_walk(show_by_name, NULL, (void *)id);
867 * prints the address and graph number of all irgs with given ld_name
869 static void irg_ld_name(const char *name) {
870 ident *id = new_id_from_str(name);
872 type_walk(show_by_ldname, NULL, (void *)id);
900 static const char *reserved[] = {
924 static struct lexer {
925 int has_token; /**< set if a token is cached. */
926 unsigned cur_token; /**< current token. */
927 unsigned number; /**< current token attribute. */
928 const char *s; /**< current token attribute. */
929 unsigned len; /**< current token attribute. */
931 const char *curr_pos;
933 const char *tok_start;
937 * Initialize the lexer.
939 static void init_lexer(const char *input) {
941 lexer.curr_pos = input;
942 lexer.end_pos = input + strlen(input);
947 * Get the next char from the input.
949 static char next_char(void) {
950 if (lexer.curr_pos >= lexer.end_pos)
952 return *lexer.curr_pos++;
955 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
958 #define MIN(a, b) (a) < (b) ? (a) : (b)
963 static unsigned get_token(void) {
967 /* skip white space */
970 } while (c != '\0' && isspace(c));
972 lexer.tok_start = lexer.curr_pos - 1;
974 /* command begins here */
980 } while (isalpha(c));
984 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
985 if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
991 } else if (isalpha(c)) {
993 lexer.s = lexer.curr_pos - 1;
997 } while (isgraph(c));
999 lexer.len = lexer.curr_pos - lexer.s;
1000 return tok_identifier;
1001 } else if (isdigit(c) || c == '-') {
1002 unsigned number = 0;
1005 /* we support negative numbers as well, so one can easily set all bits with -1 */
1014 if (c == 'x' || c == 'X') {
1021 number = (number << 4) | (c - '0');
1023 number = (number << 4) | (toupper(c) - 'A' + 10);
1026 lexer.number = number;
1033 number = number * 10 + (c - '0');
1037 lexer.number = sign ? 0 - number : number;
1046 * High level function to use from debugger interface
1048 * Supported commands:
1049 * .create nr break if node nr was created
1050 * .help list all commands
1052 void firm_debug(const char *cmd) {
1053 char name[1024], fname[1024];
1061 token = get_token();
1068 token = get_token();
1069 if (token != tok_number)
1071 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1075 token = get_token();
1076 if (token != tok_number)
1078 break_on_nr(lexer.number, BP_ON_REPLACE);
1082 token = get_token();
1083 if (token != tok_number)
1085 break_on_nr(lexer.number, BP_ON_LOWER);
1089 token = get_token();
1091 if (token == tok_number)
1092 break_on_nr(lexer.number, BP_ON_REMIRG);
1093 else if (token == tok_identifier) {
1094 len = MIN(lexer.len, 1023);
1095 strncpy(name, lexer.s, len);
1097 break_on_ident(name, BP_ON_REMIRG);
1103 token = get_token();
1105 if (token == tok_number)
1106 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1107 else if (token == tok_identifier) {
1108 len = MIN(lexer.len, 1023);
1109 strncpy(name, lexer.s, len);
1111 break_on_ident(name, BP_ON_NEW_ENT);
1117 token = get_token();
1119 if (token == tok_number)
1120 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1121 else if (token == tok_identifier) {
1122 len = MIN(lexer.len, 1023);
1123 strncpy(name, lexer.s, len);
1125 break_on_ident(name, BP_ON_NEW_TYPE);
1131 token = get_token();
1133 if (token == tok_number)
1134 show_firm_object(find_type_nr(lexer.number));
1135 else if (token == tok_identifier) {
1136 len = MIN(lexer.len, 1023);
1137 strncpy(name, lexer.s, len);
1139 show_firm_object(find_type_name(name));
1145 token = get_token();
1147 if (token == tok_number)
1148 show_firm_object(find_entity_nr(lexer.number));
1149 else if (token == tok_identifier) {
1150 len = MIN(lexer.len, 1023);
1151 strncpy(name, lexer.s, len);
1153 show_firm_object(find_entity_name(name));
1167 token = get_token();
1168 if (token != tok_number)
1170 bp_activate(lexer.number, 1);
1174 token = get_token();
1175 if (token != tok_number)
1177 bp_activate(lexer.number, 0);
1181 token = get_token();
1182 if (token != tok_identifier)
1184 len = MIN(lexer.len, 1023);
1185 strncpy(name, lexer.s, len);
1188 token = get_token();
1189 if (token != tok_number)
1191 set_dbg_level(name, lexer.number);
1195 token = get_token();
1196 if (token != tok_identifier)
1198 len = MIN(lexer.len, 1023);
1199 strncpy(name, lexer.s, len);
1202 token = get_token();
1203 if (token != tok_number)
1205 set_dbg_level(name, (1 << lexer.number) - 1);
1208 case tok_setoutfile:
1209 token = get_token();
1210 if (token != tok_identifier)
1212 len = MIN(lexer.len, 1023);
1213 strncpy(name, lexer.s, len);
1216 token = get_token();
1217 if (token != tok_identifier)
1219 len = MIN(lexer.len, 1023);
1220 strncpy(fname, lexer.s, len);
1222 set_dbg_outfile(name, fname);
1225 token = get_token();
1226 if (token != tok_identifier)
1228 len = MIN(lexer.len, 1023);
1229 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 /* creates the debugger tables */
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 */
1286 /* some picky compiler do not allow empty files */
1287 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
1292 * @page debugger The Firm debugger extension
1294 * Firm contains a debugger extension. This allows to set debugger breakpoints
1295 * an various events.
1296 * The extension uses a text interface which can be accessed from most debuggers.
1297 * More than one command can be given separated by ';'.
1299 * @section sec_cmd Supported commands
1301 * The following commands are currently supported:
1305 * Break immediately after the debugger extension was initialized.
1306 * Typically this command is used in the environment to stop the execution
1307 * of a Firm compiler right after the initialization, like this:
1309 * $export FIRMDBG=".init"
1313 * Break if a new IR-node with node number nr was created.
1314 * Typically used to find the place where wrong nodes are created.
1318 * Break before IR-node with node number nr is replaced by another node.
1322 * Break before IR-node with node number nr is lowered.
1326 * Break if the irg with graph number nr is deleted.
1330 * Break if the irg of entity name is deleted.
1334 * Break if the entity with number nr was created.
1338 * Break if the entity name was created.
1342 * Break if the type with number nr was created.
1346 * Break if the type name was created.
1350 * Show all Firm internal breakpoints.
1354 * Enables breakpoint nr.
1358 * Disables breakpoint nr.
1362 * Show the content of entity nr.
1366 * Show the content of entity name.
1370 * Show the content of type nr.
1374 * Show the content of type name.
1376 * @b .setmask name msk
1378 * Sets the debug module name to mask msk.
1380 * @b .setlvl name lvl
1382 * Sets the debug module name to level lvl.
1384 * @b .setoutfile name file
1386 * Redirects debug output of module name to file.
1390 * Prints address and graph number of a method given by its name.
1392 * @b .irgldname name
1394 * Prints address and graph number of a method given by its linker name.
1398 * List all commands.
1401 * The Firm debugger extension can be accessed using the function firm_debug().
1402 * The following example shows how to set a creation breakpoint in GDB when
1403 * node 2101 is created.
1405 * -# set FIRMDBG=".init"
1406 * -# start gdb with your compiler
1407 * -# after gdb breaks, issue
1409 * call firm_debug(".create 2101")
1411 * On the console the following text should be issued:
1413 * Firm BP 1: creation of Node 2101
1416 * @section gdb_macro GDB macro
1418 * Add the following to your .gdbinit file:
1421 # define firm "cmd" Firm debugger extension
1424 call firm_debug($arg0)
1428 * Then, all Firm debugger extension commands can be accessed in the gdb
1429 * console using the firm prefix, eg.:
1431 * firm ".create 2101"