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
59 #include "irgraph_t.h"
67 /* Break into the debugger. The Win32 way. */
68 void firm_debug_break(void) {
71 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
72 /* Break into the debugger. The ia32/x86_64 way under GCC. */
73 void firm_debug_break(void) {
74 __asm__ __volatile__("int3");
77 /* Break into the debugger. Poor Unix way. */
78 void firm_debug_break(void) {
83 /** supported breakpoint kinds */
85 BP_NR = 'n', /**< break on node number. */
86 BP_IDENT = 'i' /**< break on ident. */
90 * Reasons for node number breakpoints.
92 typedef enum _bp_reasons_t {
93 BP_ON_NEW_NODE, /**< break if node with number is created */
94 BP_ON_REPLACE, /**< break if node with number is replaced */
95 BP_ON_LOWER, /**< break if node with number is lowered */
96 BP_ON_REMIRG, /**< break if an IRG is removed */
97 BP_ON_NEW_ENT, /**< break if a new entity is created */
98 BP_ON_NEW_TYPE, /**< break if a new type is created */
103 typedef struct _breakpoint {
104 bp_kind kind; /**< the kind of this break point */
105 unsigned bpnr; /**< break point number */
106 int active; /**< non-zero, if this break point is active */
107 bp_reasons_t reason; /**< reason for the breakpoint */
108 struct _breakpoint *next; /**< link to the next one */
111 /** A number breakpoint. */
113 breakpoint bp; /**< the breakpoint data */
114 long nr; /**< the node number */
117 /** Calculate the hash value for a node breakpoint. */
118 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
120 /** An ident breakpoint. */
122 breakpoint bp; /**< the breakpoint data */
123 ident *id; /**< the ident */
126 /** Calculate the hash value for an ident breakpoint. */
127 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
129 /** The set containing the breakpoints on node numbers. */
130 static set *bp_numbers;
132 /** The set containing the breakpoints on idents. */
133 static set *bp_idents;
135 /**< the list of all breakpoints */
136 static breakpoint *bp_list;
138 /** number of the current break point */
139 static unsigned bp_num = 0;
141 /** set if break on init command was issued. */
142 static int break_on_init = 0;
144 /** the hook entries for the Firm debugger module. */
145 static hook_entry_t debugger_hooks[hook_last];
147 /** number of active breakpoints to maintain hooks. */
148 static unsigned num_active_bp[BP_MAX_REASON];
151 * The debug message buffer
153 static char firm_dbg_msg_buf[2048];
156 * If set, the debug extension writes all output to the
157 * firm_dbg_msg_buf buffer
159 static int redir_output = 0;
162 * Is set to one, if the debug extension is active
164 static int is_active = 0;
166 /** hook the hook h with function fkt. */
167 #define HOOK(h, fkt) \
169 debugger_hooks[h].hook._##h = fkt; \
170 register_hook(h, &debugger_hooks[h]); \
173 /** unhook the hook h */
176 unregister_hook(h, &debugger_hooks[h]); \
177 debugger_hooks[h].hook._##h = NULL; \
180 /** returns non-zero if a entry hook h is used */
181 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
183 /* some macros needed to create the info string */
184 #define _DBG_VERSION(major, minor) #major "." #minor
185 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
186 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
188 /* the API version: change if needed */
189 #define FIRM_DBG_MAJOR 1
190 #define FIRM_DBG_MINOR 0
192 /** for automatic detection of the debug extension */
193 static const char *firm_debug_info_string =
194 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
197 * Returns non-zero, if the debug extension is active
199 int firm_debug_active(void) {
201 } /* firm_debug_active */
204 * Reset the debug text buffer.
206 static void reset_dbg_buf(void) {
207 firm_dbg_msg_buf[0] = '\0';
208 } /* reset_dbg_buf */
211 * Add text to the debug text buffer.
213 static void add_to_dbg_buf(const char *buf) {
214 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
215 } /* add_to_dbg_buf */
218 * Return the content of the debug text buffer.
220 * To be called from the debugger.
222 const char *firm_debug_text(void) {
223 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
224 return firm_dbg_msg_buf;
225 } /* firm_debug_text */
230 static void dbg_printf(const char *fmt, ...)
242 ir_vsnprintf(buf, sizeof(buf), fmt, args);
252 * A new node is created.
254 * @param ctx the hook context
255 * @param irg the IR graph on which the node is created
256 * @param node the new IR node that was created
258 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
262 key.nr = get_irn_node_nr(node);
263 key.bp.reason = BP_ON_NEW_NODE;
265 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
266 if (elem && elem->bp.active) {
267 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
273 * A node is replaced.
275 * @param ctx the hook context
276 * @param old the IR node the is replaced
277 * @param nw the new IR node that will replace old
279 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
283 key.nr = get_irn_node_nr(old);
284 key.bp.reason = BP_ON_REPLACE;
286 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
287 if (elem && elem->bp.active) {
288 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
294 * A new node is lowered.
296 * @param ctx the hook context
297 * @param node the new IR node that will be lowered
299 static void dbg_lower(void *ctx, ir_node *node)
303 key.nr = get_irn_node_nr(node);
304 key.bp.reason = BP_ON_LOWER;
306 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
307 if (elem && elem->bp.active) {
308 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
314 * A graph will be deleted.
316 * @param ctx the hook context
317 * @param irg the IR graph that will be deleted
319 static void dbg_free_graph(void *ctx, ir_graph *irg)
323 key.nr = get_irg_graph_nr(irg);
324 key.bp.reason = BP_ON_REMIRG;
326 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
327 if (elem && elem->bp.active) {
328 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
333 bp_ident_t key, *elem;
334 ir_entity *ent = get_irg_entity(irg);
339 key.id = get_entity_ident(ent);
340 key.bp.reason = BP_ON_REMIRG;
342 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
343 if (elem && elem->bp.active) {
344 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
348 } /* dbg_free_graph */
351 * An entity was created.
353 * @param ctx the hook context
354 * @param ent the newly created entity
356 static void dbg_new_entity(void *ctx, ir_entity *ent)
359 bp_ident_t key, *elem;
361 key.id = get_entity_ident(ent);
362 key.bp.reason = BP_ON_NEW_ENT;
364 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
365 if (elem && elem->bp.active) {
366 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
373 key.nr = get_entity_nr(ent);
374 key.bp.reason = BP_ON_NEW_ENT;
376 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
377 if (elem && elem->bp.active) {
378 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
382 } /* dbg_new_entity */
385 * A type was created.
387 * @param ctx the hook context
388 * @param tp the newly created type
390 static void dbg_new_type(void *ctx, ir_type *tp)
395 key.nr = get_type_nr(tp);
396 key.bp.reason = BP_ON_NEW_TYPE;
398 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
399 if (elem && elem->bp.active) {
400 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
405 bp_ident_t key, *elem;
407 key.id = get_type_ident(tp);
408 key.bp.reason = BP_ON_NEW_TYPE;
410 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
411 if (elem && elem->bp.active) {
412 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
419 * Return the reason string.
421 static const char *reason_str(bp_reasons_t reason)
424 case BP_ON_NEW_NODE: return "node creation";
425 case BP_ON_REPLACE: return "node replace";
426 case BP_ON_LOWER: return "node lowering";
427 case BP_ON_REMIRG: return "removing IRG";
428 case BP_ON_NEW_ENT: return "entity creation";
429 case BP_ON_NEW_TYPE: return "type creation";
436 * Compare two number breakpoints.
438 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
440 const bp_nr_t *e1 = elt;
441 const bp_nr_t *e2 = key;
443 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
447 * Compare two ident breakpoints.
449 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
451 const bp_ident_t *e1 = elt;
452 const bp_ident_t *e2 = key;
454 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
460 static void update_hooks(breakpoint *bp)
462 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
463 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
466 ++num_active_bp[bp->reason];
468 --num_active_bp[bp->reason];
470 if (num_active_bp[bp->reason] > 0) {
471 /* register the hooks on demand */
472 switch (bp->reason) {
473 CASE_ON(BP_ON_NEW_NODE, new_node);
474 CASE_ON(BP_ON_REPLACE, replace);
475 CASE_ON(BP_ON_LOWER, lower);
476 CASE_ON(BP_ON_REMIRG, free_graph);
477 CASE_ON(BP_ON_NEW_ENT, new_entity);
478 CASE_ON(BP_ON_NEW_TYPE, new_type);
484 /* unregister the hook on demand */
485 switch (bp->reason) {
486 CASE_OFF(BP_ON_NEW_NODE, new_node);
487 CASE_OFF(BP_ON_REPLACE, replace);
488 CASE_OFF(BP_ON_LOWER, lower);
489 CASE_OFF(BP_ON_REMIRG, free_graph);
490 CASE_OFF(BP_ON_NEW_ENT, new_entity);
491 CASE_OFF(BP_ON_NEW_TYPE, new_type);
501 * Break if nr is reached.
503 static void break_on_nr(long nr, bp_reasons_t reason)
510 key.bp.reason = reason;
513 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
515 if (elem->bp.bpnr == 0) {
516 /* new break point */
517 elem->bp.bpnr = ++bp_num;
518 elem->bp.next = bp_list;
521 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
523 update_hooks(&elem->bp);
528 * Break if ident name is reached.
530 static void break_on_ident(const char *name, bp_reasons_t reason) {
531 bp_ident_t key, *elem;
533 key.bp.kind = BP_IDENT;
536 key.bp.reason = reason;
537 key.id = new_id_from_str(name);
539 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
541 if (elem->bp.bpnr == 0) {
542 /* new break point */
543 elem->bp.bpnr = ++bp_num;
544 elem->bp.next = bp_list;
547 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
549 update_hooks(&elem->bp);
551 } /* break_on_ident */
554 * Sets/resets the active flag of breakpoint bp.
556 static void bp_activate(unsigned bp, int active)
560 for (p = bp_list; p; p = p->next) {
562 if (p->active != active) {
567 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
571 dbg_printf("Error: Firm BP %u not exists.\n", bp);
576 * Show a list of supported commands
578 static void show_commands(void) {
579 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
580 ".init break after initialization\n"
581 ".create nr break if node nr was created\n"
582 ".replace nr break if node nr is replaced by another node\n"
583 ".lower nr break before node nr is lowered\n"
584 ".remirg nr|name break if the irg of nr or entity name is deleted\n"
585 ".newent nr|name break if the entity nr or name was created\n"
586 ".newtype nr|name break if the type nr or name was created\n"
587 ".bp show all breakpoints\n"
588 ".enable nr enable breakpoint nr\n"
589 ".disable nr disable breakpoint nr\n"
590 ".showtype nr|name show content of the type nr or name\n"
591 ".showent nr|name show content of the entity nr or name\n"
592 ".setmask name msk sets the debug module name to mask msk\n"
593 ".setlvl name lvl sets the debug module name to level lvl\n"
594 ".setoutfile name file redirects debug output of module name to file\n"
595 ".irgname name prints address and graph number of a method given by its name\n"
596 ".irgldname ldname prints address and graph number of a method given by its ldname\n"
597 ".help list all commands\n"
599 } /* show_commands */
602 * Shows all Firm breakpoints.
604 static void show_bp(void) {
610 dbg_printf("Firm Breakpoints:");
611 for (p = bp_list; p; p = p->next) {
613 dbg_printf("+\n BP %u: ", p->bpnr);
617 node_p = (bp_nr_t *)p;
618 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
622 ident_p = (bp_ident_t *)p;
623 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
627 dbg_printf(p->active ? "+enabled" : "+disabled");
629 dbg_printf(have_one ? "+\n" : "+ NONE\n");
633 * firm_dbg_register() expects that the name is stored persistent.
634 * So we need this little helper function
636 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) {
679 if (firm_thing == NULL) {
680 fprintf(f, "<NULL>\n");
683 switch (get_kind(firm_thing)) {
685 fprintf(f, "BAD: (%p)\n", firm_thing);
688 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
691 dump_type_to_file(f, firm_thing, dump_verbosity_max);
699 case k_ir_compound_graph_path:
705 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
707 } /* show_firm_object */
710 * Find a firm type by its number.
712 static ir_type *find_type_nr(long nr) {
713 int i, n = get_irp_n_types();
716 for (i = 0; i < n; ++i) {
717 tp = get_irp_type(i);
718 if (get_type_nr(tp) == nr)
721 tp = get_glob_type();
722 if (get_type_nr(tp) == nr)
728 * Find a firm type by its name.
730 static ir_type *find_type_name(const char *name) {
731 int i, n = get_irp_n_types();
734 for (i = 0; i < n; ++i) {
735 tp = get_irp_type(i);
736 if (strcmp(get_type_name(tp), name) == 0)
739 tp = get_glob_type();
740 if (strcmp(get_type_name(tp), name) == 0)
743 } /* find_type_name */
745 /** The environment for the entity search functions. */
746 typedef struct find_env {
748 long nr; /**< the number that is searched for */
749 const char *name; /**< the name that is searched for */
751 ir_entity *res; /**< the result */
755 * Type-walker: Find an entity with given number.
757 static void check_ent_nr(type_or_ent *tore, void *ctx) {
758 ir_entity *ent = (ir_entity *)tore;
759 find_env_t *env = ctx;
762 if (get_entity_nr(ent) == env->u.nr) {
768 * Type-walker: Find an entity with given name.
770 static void check_ent_name(type_or_ent *tore, void *ctx) {
771 ir_entity *ent = (ir_entity *)tore;
772 find_env_t *env = ctx;
775 if (strcmp(get_entity_name(ent), env->u.name) == 0) {
778 } /* check_ent_name */
781 * Find a firm entity by its number.
783 static ir_entity *find_entity_nr(long nr) {
788 type_walk(check_ent_nr, NULL, &env);
790 } /* find_entity_nr */
793 * Find a firm entity by its name.
795 static ir_entity *find_entity_name(const char *name) {
800 type_walk(check_ent_name, NULL, &env);
802 } /* find_entity_name */
805 * Search methods for a name.
807 static void show_by_name(type_or_ent *tore, void *env) {
808 ident *id = (ident *)env;
810 if (is_entity(tore)) {
811 ir_entity *ent = (ir_entity *)tore;
813 if (is_method_entity(ent)) {
814 if (get_entity_ident(ent) == id) {
815 ir_type *owner = get_entity_owner(ent);
816 ir_graph *irg = get_entity_irg(ent);
818 if (owner != get_glob_type()) {
819 printf("%s::%s", get_type_name(owner), get_id_str(id));
821 printf("%s", get_id_str(id));
824 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
833 * Search methods for a ldname.
835 static void show_by_ldname(type_or_ent *tore, void *env) {
836 ident *id = (ident *)env;
838 if (is_entity(tore)) {
839 ir_entity *ent = (ir_entity *)tore;
841 if (is_method_entity(ent)) {
842 if (get_entity_ld_ident(ent) == id) {
843 ir_type *owner = get_entity_owner(ent);
844 ir_graph *irg = get_entity_irg(ent);
846 if (owner != get_glob_type()) {
847 printf("%s::%s", get_type_name(owner), get_id_str(id));
849 printf("%s", get_id_str(id));
852 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
858 } /* show_by_ldname */
861 * prints the address and graph number of all irgs with given name
863 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) {
873 ident *id = new_id_from_str(name);
875 type_walk(show_by_ldname, NULL, (void *)id);
903 static const char *reserved[] = {
927 static struct lexer {
928 int has_token; /**< set if a token is cached. */
929 unsigned cur_token; /**< current token. */
930 unsigned number; /**< current token attribute. */
931 const char *s; /**< current token attribute. */
932 unsigned len; /**< current token attribute. */
934 const char *curr_pos;
936 const char *tok_start;
940 * Initialize the lexer.
942 static void init_lexer(const char *input) {
944 lexer.curr_pos = input;
945 lexer.end_pos = input + strlen(input);
950 * Get the next char from the input.
952 static char next_char(void) {
953 if (lexer.curr_pos >= lexer.end_pos)
955 return *lexer.curr_pos++;
958 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
961 #define MIN(a, b) (a) < (b) ? (a) : (b)
966 static unsigned get_token(void) {
970 /* skip white space */
973 } while (c != '\0' && isspace(c));
975 lexer.tok_start = lexer.curr_pos - 1;
977 /* command begins here */
983 } while (isalpha(c));
987 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
988 if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
994 } else if (isalpha(c)) {
996 lexer.s = lexer.curr_pos - 1;
1000 } while (isgraph(c));
1002 lexer.len = lexer.curr_pos - lexer.s;
1003 return tok_identifier;
1004 } else if (isdigit(c) || c == '-') {
1005 unsigned number = 0;
1008 /* we support negative numbers as well, so one can easily set all bits with -1 */
1017 if (c == 'x' || c == 'X') {
1024 number = (number << 4) | (c - '0');
1026 number = (number << 4) | (toupper(c) - 'A' + 10);
1029 lexer.number = number;
1036 number = number * 10 + (c - '0');
1040 lexer.number = sign ? 0 - number : number;
1049 * High level function to use from debugger interface
1051 * Supported commands:
1052 * .create nr break if node nr was created
1053 * .help list all commands
1055 void firm_debug(const char *cmd) {
1056 char name[1024], fname[1024];
1064 token = get_token();
1071 token = get_token();
1072 if (token != tok_number)
1074 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1078 token = get_token();
1079 if (token != tok_number)
1081 break_on_nr(lexer.number, BP_ON_REPLACE);
1085 token = get_token();
1086 if (token != tok_number)
1088 break_on_nr(lexer.number, BP_ON_LOWER);
1092 token = get_token();
1094 if (token == tok_number)
1095 break_on_nr(lexer.number, BP_ON_REMIRG);
1096 else if (token == tok_identifier) {
1097 len = MIN(lexer.len, 1023);
1098 strncpy(name, lexer.s, len);
1100 break_on_ident(name, BP_ON_REMIRG);
1106 token = get_token();
1108 if (token == tok_number)
1109 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1110 else if (token == tok_identifier) {
1111 len = MIN(lexer.len, 1023);
1112 strncpy(name, lexer.s, len);
1114 break_on_ident(name, BP_ON_NEW_ENT);
1120 token = get_token();
1122 if (token == tok_number)
1123 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1124 else if (token == tok_identifier) {
1125 len = MIN(lexer.len, 1023);
1126 strncpy(name, lexer.s, len);
1128 break_on_ident(name, BP_ON_NEW_TYPE);
1134 token = get_token();
1136 if (token == tok_number)
1137 show_firm_object(find_type_nr(lexer.number));
1138 else if (token == tok_identifier) {
1139 len = MIN(lexer.len, 1023);
1140 strncpy(name, lexer.s, len);
1142 show_firm_object(find_type_name(name));
1148 token = get_token();
1150 if (token == tok_number)
1151 show_firm_object(find_entity_nr(lexer.number));
1152 else if (token == tok_identifier) {
1153 len = MIN(lexer.len, 1023);
1154 strncpy(name, lexer.s, len);
1156 show_firm_object(find_entity_name(name));
1170 token = get_token();
1171 if (token != tok_number)
1173 bp_activate(lexer.number, 1);
1177 token = get_token();
1178 if (token != tok_number)
1180 bp_activate(lexer.number, 0);
1184 token = get_token();
1185 if (token != tok_identifier)
1187 len = MIN(lexer.len, 1023);
1188 strncpy(name, lexer.s, len);
1191 token = get_token();
1192 if (token != tok_number)
1194 set_dbg_level(name, lexer.number);
1198 token = get_token();
1199 if (token != tok_identifier)
1201 len = MIN(lexer.len, 1023);
1202 strncpy(name, lexer.s, len);
1205 token = get_token();
1206 if (token != tok_number)
1208 set_dbg_level(name, (1 << lexer.number) - 1);
1211 case tok_setoutfile:
1212 token = get_token();
1213 if (token != tok_identifier)
1215 len = MIN(lexer.len, 1023);
1216 strncpy(name, lexer.s, len);
1219 token = get_token();
1220 if (token != tok_identifier)
1222 len = MIN(lexer.len, 1023);
1223 strncpy(fname, lexer.s, len);
1225 set_dbg_outfile(name, fname);
1228 token = get_token();
1229 if (token != tok_identifier)
1231 len = MIN(lexer.len, 1023);
1232 strncpy(name, lexer.s, len);
1237 token = get_token();
1238 if (token != tok_identifier)
1240 len = MIN(lexer.len, 1023);
1241 strncpy(name, lexer.s, len);
1253 printf("Error: before %s\n", lexer.tok_start);
1258 token = get_token();
1259 if (token == tok_eof)
1268 /* creates the debugger tables */
1269 void firm_init_debugger(void)
1273 bp_numbers = new_set(cmp_nr_bp, 8);
1274 bp_idents = new_set(cmp_ident_bp, 8);
1276 env = getenv("FIRMDBG");
1285 } /* firm_init_debugger */
1289 /* some picky compiler do not allow empty files */
1290 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
1295 * @page debugger The Firm debugger extension
1297 * Firm contains a debugger extension. This allows to set debugger breakpoints
1298 * an various events.
1299 * The extension uses a text interface which can be accessed from most debuggers.
1300 * More than one command can be given separated by ';'.
1302 * @section sec_cmd Supported commands
1304 * The following commands are currently supported:
1308 * Break immediately after the debugger extension was initialized.
1309 * Typically this command is used in the environment to stop the execution
1310 * of a Firm compiler right after the initialization, like this:
1312 * $export FIRMDBG=".init"
1316 * Break if a new IR-node with node number nr was created.
1317 * Typically used to find the place where wrong nodes are created.
1321 * Break before IR-node with node number nr is replaced by another node.
1325 * Break before IR-node with node number nr is lowered.
1329 * Break if the irg with graph number nr is deleted.
1333 * Break if the irg of entity name is deleted.
1337 * Break if the entity with number nr was created.
1341 * Break if the entity name was created.
1345 * Break if the type with number nr was created.
1349 * Break if the type name was created.
1353 * Show all Firm internal breakpoints.
1357 * Enables breakpoint nr.
1361 * Disables breakpoint nr.
1365 * Show the content of entity nr.
1369 * Show the content of entity name.
1373 * Show the content of type nr.
1377 * Show the content of type name.
1379 * @b .setmask name msk
1381 * Sets the debug module name to mask msk.
1383 * @b .setlvl name lvl
1385 * Sets the debug module name to level lvl.
1387 * @b .setoutfile name file
1389 * Redirects debug output of module name to file.
1393 * Prints address and graph number of a method given by its name.
1395 * @b .irgldname name
1397 * Prints address and graph number of a method given by its linker name.
1401 * List all commands.
1404 * The Firm debugger extension can be accessed using the function firm_debug().
1405 * The following example shows how to set a creation breakpoint in GDB when
1406 * node 2101 is created.
1408 * -# set FIRMDBG=".init"
1409 * -# start gdb with your compiler
1410 * -# after gdb breaks, issue
1412 * call firm_debug(".create 2101")
1414 * On the console the following text should be issued:
1416 * Firm BP 1: creation of Node 2101
1419 * @section gdb_macro GDB macro
1421 * Add the following to your .gdbinit file:
1424 # define firm "cmd" Firm debugger extension
1427 call firm_debug($arg0)
1431 * Then, all Firm debugger extension commands can be accessed in the gdb
1432 * console using the firm prefix, eg.:
1434 * firm ".create 2101"