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"
66 /* Break into the debugger. The Win32 way. */
67 void firm_debug_break(void) {
70 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
71 /* Break into the debugger. The ia32/x86_64 way under GCC. */
72 void firm_debug_break(void) {
73 __asm__ __volatile__("int3");
76 /* Break into the debugger. Poor Unix way. */
77 void firm_debug_break(void) {
82 /** supported breakpoint kinds */
84 BP_NR = 'n', /**< break on node number. */
85 BP_IDENT = 'i' /**< break on ident. */
89 * Reasons for node number breakpoints.
91 typedef enum _bp_reasons_t {
92 BP_ON_NEW_NODE, /**< break if node with number is created */
93 BP_ON_REPLACE, /**< break if node with number is replaced */
94 BP_ON_LOWER, /**< break if node with number is lowered */
95 BP_ON_REMIRG, /**< break if an IRG is removed */
96 BP_ON_NEW_ENT, /**< break if a new entity is created */
97 BP_ON_NEW_TYPE, /**< break if a new type is created */
102 typedef struct _breakpoint {
103 bp_kind kind; /**< the kind of this break point */
104 unsigned bpnr; /**< break point number */
105 int active; /**< non-zero, if this break point is active */
106 bp_reasons_t reason; /**< reason for the breakpoint */
107 struct _breakpoint *next; /**< link to the next one */
110 /** A number breakpoint. */
112 breakpoint bp; /**< the breakpoint data */
113 long nr; /**< the node number */
116 /** Calculate the hash value for a node breakpoint. */
117 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
119 /** An ident breakpoint. */
121 breakpoint bp; /**< the breakpoint data */
122 ident *id; /**< the ident */
125 /** Calculate the hash value for an ident breakpoint. */
126 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
128 /** The set containing the breakpoints on node numbers. */
129 static set *bp_numbers;
131 /** The set containing the breakpoints on idents. */
132 static set *bp_idents;
134 /**< the list of all breakpoints */
135 static breakpoint *bp_list;
137 /** number of the current break point */
138 static unsigned bp_num = 0;
140 /** set if break on init command was issued. */
141 static int break_on_init = 0;
143 /** the hook entries for the Firm debugger module. */
144 static hook_entry_t debugger_hooks[hook_last];
146 /** number of active breakpoints to maintain hooks. */
147 static unsigned num_active_bp[BP_MAX_REASON];
150 * The debug message buffer
152 static char firm_dbg_msg_buf[2048];
155 * If set, the debug extension writes all output to the
156 * firm_dbg_msg_buf buffer
158 static int redir_output = 0;
161 * Is set to one, if the debug extension is active
163 static int is_active = 0;
165 /** hook the hook h with function fkt. */
166 #define HOOK(h, fkt) \
168 debugger_hooks[h].hook._##h = fkt; \
169 register_hook(h, &debugger_hooks[h]); \
172 /** unhook the hook h */
175 unregister_hook(h, &debugger_hooks[h]); \
176 debugger_hooks[h].hook._##h = NULL; \
179 /** returns non-zero if a entry hook h is used */
180 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
182 /* some macros needed to create the info string */
183 #define _DBG_VERSION(major, minor) #major "." #minor
184 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
185 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
187 /* the API version: change if needed */
188 #define FIRM_DBG_MAJOR 1
189 #define FIRM_DBG_MINOR 0
191 /** for automatic detection of the debug extension */
192 static const char firm_debug_info_string[] =
193 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
196 * Returns non-zero, if the debug extension is active
198 int firm_debug_active(void) {
200 } /* firm_debug_active */
203 * Reset the debug text buffer.
205 static void reset_dbg_buf(void) {
206 firm_dbg_msg_buf[0] = '\0';
207 } /* reset_dbg_buf */
210 * Add text to the debug text buffer.
212 static void add_to_dbg_buf(const char *buf) {
213 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
214 } /* add_to_dbg_buf */
217 * Return the content of the debug text buffer.
219 * To be called from the debugger.
221 const char *firm_debug_text(void) {
222 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
223 return firm_dbg_msg_buf;
224 } /* firm_debug_text */
229 static void dbg_printf(const char *fmt, ...)
241 ir_vsnprintf(buf, sizeof(buf), fmt, args);
251 * A new node is created.
253 * @param ctx the hook context
254 * @param irg the IR graph on which the node is created
255 * @param node the new IR node that was created
257 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
261 key.nr = get_irn_node_nr(node);
262 key.bp.reason = BP_ON_NEW_NODE;
264 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
265 if (elem && elem->bp.active) {
266 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
272 * A node is replaced.
274 * @param ctx the hook context
275 * @param old the IR node the is replaced
276 * @param nw the new IR node that will replace old
278 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
282 key.nr = get_irn_node_nr(old);
283 key.bp.reason = BP_ON_REPLACE;
285 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
286 if (elem && elem->bp.active) {
287 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
293 * A new node is lowered.
295 * @param ctx the hook context
296 * @param node the new IR node that will be lowered
298 static void dbg_lower(void *ctx, ir_node *node)
302 key.nr = get_irn_node_nr(node);
303 key.bp.reason = BP_ON_LOWER;
305 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
306 if (elem && elem->bp.active) {
307 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
313 * A graph will be deleted.
315 * @param ctx the hook context
316 * @param irg the IR graph that will be deleted
318 static void dbg_free_graph(void *ctx, ir_graph *irg)
322 key.nr = get_irg_graph_nr(irg);
323 key.bp.reason = BP_ON_REMIRG;
325 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
326 if (elem && elem->bp.active) {
327 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
332 bp_ident_t key, *elem;
333 ir_entity *ent = get_irg_entity(irg);
338 key.id = get_entity_ident(ent);
339 key.bp.reason = BP_ON_REMIRG;
341 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
342 if (elem && elem->bp.active) {
343 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
347 } /* dbg_free_graph */
350 * An entity was created.
352 * @param ctx the hook context
353 * @param ent the newly created entity
355 static void dbg_new_entity(void *ctx, ir_entity *ent)
358 bp_ident_t key, *elem;
360 key.id = get_entity_ident(ent);
361 key.bp.reason = BP_ON_NEW_ENT;
363 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
364 if (elem && elem->bp.active) {
365 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
372 key.nr = get_entity_nr(ent);
373 key.bp.reason = BP_ON_NEW_ENT;
375 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
376 if (elem && elem->bp.active) {
377 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
381 } /* dbg_new_entity */
384 * A type was created.
386 * @param ctx the hook context
387 * @param tp the newly created type
389 static void dbg_new_type(void *ctx, ir_type *tp)
394 key.nr = get_type_nr(tp);
395 key.bp.reason = BP_ON_NEW_TYPE;
397 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
398 if (elem && elem->bp.active) {
399 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
404 bp_ident_t key, *elem;
406 key.id = get_type_ident(tp);
407 key.bp.reason = BP_ON_NEW_TYPE;
409 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
410 if (elem && elem->bp.active) {
411 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
418 * Return the reason string.
420 static const char *reason_str(bp_reasons_t reason)
423 case BP_ON_NEW_NODE: return "node creation";
424 case BP_ON_REPLACE: return "node replace";
425 case BP_ON_LOWER: return "node lowering";
426 case BP_ON_REMIRG: return "removing IRG";
427 case BP_ON_NEW_ENT: return "entity creation";
428 case BP_ON_NEW_TYPE: return "type creation";
435 * Compare two number breakpoints.
437 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
439 const bp_nr_t *e1 = elt;
440 const bp_nr_t *e2 = key;
442 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
446 * Compare two ident breakpoints.
448 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
450 const bp_ident_t *e1 = elt;
451 const bp_ident_t *e2 = key;
453 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
459 static void update_hooks(breakpoint *bp)
461 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
462 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
465 ++num_active_bp[bp->reason];
467 --num_active_bp[bp->reason];
469 if (num_active_bp[bp->reason] > 0) {
470 /* register the hooks on demand */
471 switch (bp->reason) {
472 CASE_ON(BP_ON_NEW_NODE, new_node);
473 CASE_ON(BP_ON_REPLACE, replace);
474 CASE_ON(BP_ON_LOWER, lower);
475 CASE_ON(BP_ON_REMIRG, free_graph);
476 CASE_ON(BP_ON_NEW_ENT, new_entity);
477 CASE_ON(BP_ON_NEW_TYPE, new_type);
483 /* unregister the hook on demand */
484 switch (bp->reason) {
485 CASE_OFF(BP_ON_NEW_NODE, new_node);
486 CASE_OFF(BP_ON_REPLACE, replace);
487 CASE_OFF(BP_ON_LOWER, lower);
488 CASE_OFF(BP_ON_REMIRG, free_graph);
489 CASE_OFF(BP_ON_NEW_ENT, new_entity);
490 CASE_OFF(BP_ON_NEW_TYPE, new_type);
500 * Break if nr is reached.
502 static void break_on_nr(long nr, bp_reasons_t reason)
509 key.bp.reason = reason;
512 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
514 if (elem->bp.bpnr == 0) {
515 /* new break point */
516 elem->bp.bpnr = ++bp_num;
517 elem->bp.next = bp_list;
520 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
522 update_hooks(&elem->bp);
527 * Break if ident name is reached.
529 static void break_on_ident(const char *name, bp_reasons_t reason) {
530 bp_ident_t key, *elem;
532 key.bp.kind = BP_IDENT;
535 key.bp.reason = reason;
536 key.id = new_id_from_str(name);
538 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
540 if (elem->bp.bpnr == 0) {
541 /* new break point */
542 elem->bp.bpnr = ++bp_num;
543 elem->bp.next = bp_list;
546 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
548 update_hooks(&elem->bp);
550 } /* break_on_ident */
553 * Sets/resets the active flag of breakpoint bp.
555 static void bp_activate(unsigned bp, int active)
559 for (p = bp_list; p; p = p->next) {
561 if (p->active != active) {
566 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
570 dbg_printf("Error: Firm BP %u not exists.\n", bp);
575 * Show a list of supported commands
577 static void show_commands(void) {
578 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
579 ".init break after initialization\n"
580 ".create nr break if node nr was created\n"
581 ".replace nr break if node nr is replaced by another node\n"
582 ".lower nr break before node nr is lowered\n"
583 ".remirg nr|name break if the irg of nr or entity name is deleted\n"
584 ".newent nr|name break if the entity nr or name was created\n"
585 ".newtype nr|name break if the type nr or name was created\n"
586 ".bp show all breakpoints\n"
587 ".enable nr enable breakpoint nr\n"
588 ".disable nr disable breakpoint nr\n"
589 ".showtype nr|name show content of the type nr or name\n"
590 ".showent nr|name show content of the entity nr or name\n"
591 ".setmask name msk sets the debug module name to mask msk\n"
592 ".setlvl name lvl sets the debug module name to level lvl\n"
593 ".setoutfile name file redirects debug output of module name to file\n"
594 ".irgname name prints address and graph number of a method given by its name\n"
595 ".irgldname ldname prints address and graph number of a method given by its ldname\n"
596 ".help list all commands\n"
598 } /* show_commands */
601 * Shows all Firm breakpoints.
603 static void show_bp(void) {
609 dbg_printf("Firm Breakpoints:");
610 for (p = bp_list; p; p = p->next) {
612 dbg_printf("+\n BP %u: ", p->bpnr);
616 node_p = (bp_nr_t *)p;
617 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
621 ident_p = (bp_ident_t *)p;
622 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
626 dbg_printf(p->active ? "+enabled" : "+disabled");
628 dbg_printf(have_one ? "+\n" : "+ NONE\n");
632 * firm_dbg_register() expects that the name is stored persistent.
633 * So we need this little helper function
635 static firm_dbg_module_t *dbg_register(const char *name) {
636 ident *id = new_id_from_str(name);
638 return firm_dbg_register(get_id_str(id));
642 * Sets the debug mask of module name to lvl
644 static void set_dbg_level(const char *name, unsigned lvl)
646 firm_dbg_module_t *module = dbg_register(name);
648 if (firm_dbg_get_mask(module) != lvl) {
649 firm_dbg_set_mask(module, lvl);
651 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
653 } /* set_dbg_level */
656 * Redirects the debug output of module name to fname
658 static void set_dbg_outfile(const char *name, const char *fname)
660 firm_dbg_module_t *module = dbg_register(name);
661 FILE *f = fopen(fname, "w");
668 firm_dbg_set_file(module, f);
669 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
670 } /* set_dbg_outfile */
673 * Show info about a firm thing.
675 static void show_firm_object(void *firm_thing) {
678 if (firm_thing == NULL) {
679 fprintf(f, "<NULL>\n");
682 switch (get_kind(firm_thing)) {
684 fprintf(f, "BAD: (%p)\n", firm_thing);
687 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
690 dump_type_to_file(f, firm_thing, dump_verbosity_max);
698 case k_ir_compound_graph_path:
704 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
706 } /* show_firm_object */
709 * Find a firm type by its number.
711 static ir_type *find_type_nr(long nr) {
712 int i, n = get_irp_n_types();
715 for (i = 0; i < n; ++i) {
716 tp = get_irp_type(i);
717 if (get_type_nr(tp) == nr)
720 tp = get_glob_type();
721 if (get_type_nr(tp) == nr)
727 * Find a firm type by its name.
729 static ir_type *find_type_name(const char *name) {
730 int i, n = get_irp_n_types();
733 for (i = 0; i < n; ++i) {
734 tp = get_irp_type(i);
735 if (strcmp(get_type_name(tp), name) == 0)
738 tp = get_glob_type();
739 if (strcmp(get_type_name(tp), name) == 0)
742 } /* find_type_name */
744 /** The environment for the entity search functions. */
745 typedef struct find_env {
747 long nr; /**< the number that is searched for */
748 const char *name; /**< the name that is searched for */
750 ir_entity *res; /**< the result */
754 * Type-walker: Find an entity with given number.
756 static void check_ent_nr(type_or_ent *tore, void *ctx) {
757 ir_entity *ent = (ir_entity *)tore;
758 find_env_t *env = ctx;
761 if (get_entity_nr(ent) == env->u.nr) {
767 * Type-walker: Find an entity with given name.
769 static void check_ent_name(type_or_ent *tore, void *ctx) {
770 ir_entity *ent = (ir_entity *)tore;
771 find_env_t *env = ctx;
774 if (strcmp(get_entity_name(ent), env->u.name) == 0) {
777 } /* check_ent_name */
780 * Find a firm entity by its number.
782 static ir_entity *find_entity_nr(long nr) {
787 type_walk(check_ent_nr, NULL, &env);
789 } /* find_entity_nr */
792 * Find a firm entity by its name.
794 static ir_entity *find_entity_name(const char *name) {
799 type_walk(check_ent_name, NULL, &env);
801 } /* find_entity_name */
804 * Search methods for a name.
806 static void show_by_name(type_or_ent *tore, void *env) {
807 ident *id = (ident *)env;
809 if (is_entity(tore)) {
810 ir_entity *ent = (ir_entity *)tore;
812 if (is_method_entity(ent)) {
813 if (get_entity_ident(ent) == id) {
814 ir_type *owner = get_entity_owner(ent);
815 ir_graph *irg = get_entity_irg(ent);
817 if (owner != get_glob_type()) {
818 printf("%s::%s", get_type_name(owner), get_id_str(id));
820 printf("%s", get_id_str(id));
823 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
832 * Search methods for a ldname.
834 static void show_by_ldname(type_or_ent *tore, void *env) {
835 ident *id = (ident *)env;
837 if (is_entity(tore)) {
838 ir_entity *ent = (ir_entity *)tore;
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_type_name(owner), get_id_str(id));
848 printf("%s", get_id_str(id));
851 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
857 } /* show_by_ldname */
860 * prints the address and graph number of all irgs with given name
862 static void irg_name(const char *name) {
863 ident *id = new_id_from_str(name);
865 type_walk(show_by_name, NULL, (void *)id);
869 * prints the address and graph number of all irgs with given ld_name
871 static void irg_ld_name(const char *name) {
872 ident *id = new_id_from_str(name);
874 type_walk(show_by_ldname, NULL, (void *)id);
902 static const char *reserved[] = {
926 static struct lexer {
927 int has_token; /**< set if a token is cached. */
928 unsigned cur_token; /**< current token. */
929 unsigned number; /**< current token attribute. */
930 const char *s; /**< current token attribute. */
931 unsigned len; /**< current token attribute. */
933 const char *curr_pos;
935 const char *tok_start;
939 * Initialize the lexer.
941 static void init_lexer(const char *input) {
943 lexer.curr_pos = input;
944 lexer.end_pos = input + strlen(input);
949 * Get the next char from the input.
951 static char next_char(void) {
952 if (lexer.curr_pos >= lexer.end_pos)
954 return *lexer.curr_pos++;
957 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
960 #define MIN(a, b) (a) < (b) ? (a) : (b)
965 static unsigned get_token(void) {
969 /* skip white space */
972 } while (c != '\0' && isspace(c));
974 lexer.tok_start = lexer.curr_pos - 1;
976 /* command begins here */
982 } while (isalpha(c));
986 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
987 if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0')
993 } else if (isalpha(c)) {
995 lexer.s = lexer.curr_pos - 1;
999 } while (isgraph(c));
1001 lexer.len = lexer.curr_pos - lexer.s;
1002 return tok_identifier;
1003 } else if (isdigit(c) || c == '-') {
1004 unsigned number = 0;
1007 /* we support negative numbers as well, so one can easily set all bits with -1 */
1016 if (c == 'x' || c == 'X') {
1023 number = (number << 4) | (c - '0');
1025 number = (number << 4) | (toupper(c) - 'A' + 10);
1028 lexer.number = number;
1035 number = number * 10 + (c - '0');
1039 lexer.number = sign ? 0 - number : number;
1048 * High level function to use from debugger interface
1050 * Supported commands:
1051 * .create nr break if node nr was created
1052 * .help list all commands
1054 void firm_debug(const char *cmd) {
1055 char name[1024], fname[1024];
1063 token = get_token();
1070 token = get_token();
1071 if (token != tok_number)
1073 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1077 token = get_token();
1078 if (token != tok_number)
1080 break_on_nr(lexer.number, BP_ON_REPLACE);
1084 token = get_token();
1085 if (token != tok_number)
1087 break_on_nr(lexer.number, BP_ON_LOWER);
1091 token = get_token();
1093 if (token == tok_number)
1094 break_on_nr(lexer.number, BP_ON_REMIRG);
1095 else if (token == tok_identifier) {
1096 len = MIN(lexer.len, 1023);
1097 strncpy(name, lexer.s, len);
1099 break_on_ident(name, BP_ON_REMIRG);
1105 token = get_token();
1107 if (token == tok_number)
1108 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1109 else if (token == tok_identifier) {
1110 len = MIN(lexer.len, 1023);
1111 strncpy(name, lexer.s, len);
1113 break_on_ident(name, BP_ON_NEW_ENT);
1119 token = get_token();
1121 if (token == tok_number)
1122 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1123 else if (token == tok_identifier) {
1124 len = MIN(lexer.len, 1023);
1125 strncpy(name, lexer.s, len);
1127 break_on_ident(name, BP_ON_NEW_TYPE);
1133 token = get_token();
1135 if (token == tok_number)
1136 show_firm_object(find_type_nr(lexer.number));
1137 else if (token == tok_identifier) {
1138 len = MIN(lexer.len, 1023);
1139 strncpy(name, lexer.s, len);
1141 show_firm_object(find_type_name(name));
1147 token = get_token();
1149 if (token == tok_number)
1150 show_firm_object(find_entity_nr(lexer.number));
1151 else if (token == tok_identifier) {
1152 len = MIN(lexer.len, 1023);
1153 strncpy(name, lexer.s, len);
1155 show_firm_object(find_entity_name(name));
1169 token = get_token();
1170 if (token != tok_number)
1172 bp_activate(lexer.number, 1);
1176 token = get_token();
1177 if (token != tok_number)
1179 bp_activate(lexer.number, 0);
1183 token = get_token();
1184 if (token != tok_identifier)
1186 len = MIN(lexer.len, 1023);
1187 strncpy(name, lexer.s, len);
1190 token = get_token();
1191 if (token != tok_number)
1193 set_dbg_level(name, lexer.number);
1197 token = get_token();
1198 if (token != tok_identifier)
1200 len = MIN(lexer.len, 1023);
1201 strncpy(name, lexer.s, len);
1204 token = get_token();
1205 if (token != tok_number)
1207 set_dbg_level(name, (1 << lexer.number) - 1);
1210 case tok_setoutfile:
1211 token = get_token();
1212 if (token != tok_identifier)
1214 len = MIN(lexer.len, 1023);
1215 strncpy(name, lexer.s, len);
1218 token = get_token();
1219 if (token != tok_identifier)
1221 len = MIN(lexer.len, 1023);
1222 strncpy(fname, lexer.s, len);
1224 set_dbg_outfile(name, fname);
1227 token = get_token();
1228 if (token != tok_identifier)
1230 len = MIN(lexer.len, 1023);
1231 strncpy(name, lexer.s, len);
1236 token = get_token();
1237 if (token != tok_identifier)
1239 len = MIN(lexer.len, 1023);
1240 strncpy(name, lexer.s, len);
1252 printf("Error: before %s\n", lexer.tok_start);
1257 token = get_token();
1258 if (token == tok_eof)
1267 /* creates the debugger tables */
1268 void firm_init_debugger(void)
1272 bp_numbers = new_set(cmp_nr_bp, 8);
1273 bp_idents = new_set(cmp_ident_bp, 8);
1275 env = getenv("FIRMDBG");
1284 } /* firm_init_debugger */
1288 /* some picky compiler do not allow empty files */
1289 static int _firm_only_that_you_can_compile_with_NDEBUG_defined;
1294 * @page debugger The Firm debugger extension
1296 * Firm contains a debugger extension. This allows to set debugger breakpoints
1297 * an various events.
1298 * The extension uses a text interface which can be accessed from most debuggers.
1299 * More than one command can be given separated by ';'.
1301 * @section sec_cmd Supported commands
1303 * The following commands are currently supported:
1307 * Break immediately after the debugger extension was initialized.
1308 * Typically this command is used in the environment to stop the execution
1309 * of a Firm compiler right after the initialization, like this:
1311 * $export FIRMDBG=".init"
1315 * Break if a new IR-node with node number nr was created.
1316 * Typically used to find the place where wrong nodes are created.
1320 * Break before IR-node with node number nr is replaced by another node.
1324 * Break before IR-node with node number nr is lowered.
1328 * Break if the irg with graph number nr is deleted.
1332 * Break if the irg of entity name is deleted.
1336 * Break if the entity with number nr was created.
1340 * Break if the entity name was created.
1344 * Break if the type with number nr was created.
1348 * Break if the type name was created.
1352 * Show all Firm internal breakpoints.
1356 * Enables breakpoint nr.
1360 * Disables breakpoint nr.
1364 * Show the content of entity nr.
1368 * Show the content of entity name.
1372 * Show the content of type nr.
1376 * Show the content of type name.
1378 * @b .setmask name msk
1380 * Sets the debug module name to mask msk.
1382 * @b .setlvl name lvl
1384 * Sets the debug module name to level lvl.
1386 * @b .setoutfile name file
1388 * Redirects debug output of module name to file.
1392 * Prints address and graph number of a method given by its name.
1394 * @b .irgldname name
1396 * Prints address and graph number of a method given by its linker name.
1400 * List all commands.
1403 * The Firm debugger extension can be accessed using the function firm_debug().
1404 * The following example shows how to set a creation breakpoint in GDB when
1405 * node 2101 is created.
1407 * -# set FIRMDBG=".init"
1408 * -# start gdb with your compiler
1409 * -# after gdb breaks, issue
1411 * call firm_debug(".create 2101")
1413 * On the console the following text should be issued:
1415 * Firm BP 1: creation of Node 2101
1418 * @section gdb_macro GDB macro
1420 * Add the following to your .gdbinit file:
1423 # define firm "cmd" Firm debugger extension
1426 call firm_debug($arg0)
1430 * Then, all Firm debugger extension commands can be accessed in the gdb
1431 * console using the firm prefix, eg.:
1433 * firm ".create 2101"