2 * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved.
4 * This file is part of libFirm.
6 * This file may be distributed and/or modified under the terms of the
7 * GNU General Public License version 2 as published by the Free Software
8 * Foundation and appearing in the file LICENSE.GPL included in the
9 * packaging of this file.
11 * Licensees holding valid libFirm Professional Edition licenses may use
12 * this file in accordance with the libFirm Commercial License.
13 * Agreement provided with the Software.
15 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
16 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * @brief Helper function for integrated debug support
23 * @author Michael Beck
31 #include "firm_config.h"
36 #define WIN32_LEAN_AND_MEAN
60 #include "irgraph_t.h"
64 #include "iredges_t.h"
68 /* Break into the debugger. The Win32 way. */
69 void firm_debug_break(void) {
72 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
73 /* Break into the debugger. The ia32/x86_64 way under GCC. */
74 void firm_debug_break(void) {
75 __asm__ __volatile__("int3");
78 /* Break into the debugger. Poor Unix way. */
79 void firm_debug_break(void) {
84 /** supported breakpoint kinds */
86 BP_NR = 'n', /**< break on node number. */
87 BP_IDENT = 'i' /**< break on ident. */
91 * Reasons for node number breakpoints.
93 typedef enum _bp_reasons_t {
94 BP_ON_NEW_NODE, /**< break if node with number is created */
95 BP_ON_REPLACE, /**< break if node with number is replaced */
96 BP_ON_LOWER, /**< break if node with number is lowered */
97 BP_ON_REMIRG, /**< break if an IRG is removed */
98 BP_ON_NEW_ENT, /**< break if a new entity is created */
99 BP_ON_NEW_TYPE, /**< break if a new type is created */
104 typedef struct _breakpoint {
105 bp_kind kind; /**< the kind of this break point */
106 unsigned bpnr; /**< break point number */
107 int active; /**< non-zero, if this break point is active */
108 bp_reasons_t reason; /**< reason for the breakpoint */
109 struct _breakpoint *next; /**< link to the next one */
112 /** A number breakpoint. */
114 breakpoint bp; /**< the breakpoint data */
115 long nr; /**< the node number */
118 /** Calculate the hash value for a node breakpoint. */
119 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
121 /** An ident breakpoint. */
123 breakpoint bp; /**< the breakpoint data */
124 ident *id; /**< the ident */
127 /** Calculate the hash value for an ident breakpoint. */
128 #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason)
130 /** The set containing the breakpoints on node numbers. */
131 static set *bp_numbers;
133 /** The set containing the breakpoints on idents. */
134 static set *bp_idents;
136 /**< the list of all breakpoints */
137 static breakpoint *bp_list;
139 /** number of the current break point */
140 static unsigned bp_num = 0;
142 /** set if break on init command was issued. */
143 static int break_on_init = 0;
145 /** the hook entries for the Firm debugger module. */
146 static hook_entry_t debugger_hooks[hook_last];
148 /** number of active breakpoints to maintain hooks. */
149 static unsigned num_active_bp[BP_MAX_REASON];
152 * The debug message buffer
154 static char firm_dbg_msg_buf[2048];
157 * If set, the debug extension writes all output to the
158 * firm_dbg_msg_buf buffer
160 static int redir_output = 0;
163 * Is set to one, if the debug extension is active
165 static int is_active = 0;
167 /** hook the hook h with function fkt. */
168 #define HOOK(h, fkt) \
170 debugger_hooks[h].hook._##h = fkt; \
171 register_hook(h, &debugger_hooks[h]); \
174 /** unhook the hook h */
177 unregister_hook(h, &debugger_hooks[h]); \
178 debugger_hooks[h].hook._##h = NULL; \
181 /** returns non-zero if a entry hook h is used */
182 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
184 /* some macros needed to create the info string */
185 #define _DBG_VERSION(major, minor) #major "." #minor
186 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
187 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
189 /* the API version: change if needed */
190 #define FIRM_DBG_MAJOR 1
191 #define FIRM_DBG_MINOR 0
193 /** for automatic detection of the debug extension */
194 static const char firm_debug_info_string[] =
195 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
198 * Returns non-zero, if the debug extension is active
200 int firm_debug_active(void) {
202 } /* firm_debug_active */
205 * Reset the debug text buffer.
207 static void reset_dbg_buf(void) {
208 firm_dbg_msg_buf[0] = '\0';
209 } /* reset_dbg_buf */
212 * Add text to the debug text buffer.
214 static void add_to_dbg_buf(const char *buf) {
215 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
216 } /* add_to_dbg_buf */
219 * Return the content of the debug text buffer.
221 * To be called from the debugger.
223 const char *firm_debug_text(void) {
224 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
225 return firm_dbg_msg_buf;
226 } /* firm_debug_text */
231 static void dbg_printf(const char *fmt, ...)
243 ir_vsnprintf(buf, sizeof(buf), fmt, args);
253 * A new node is created.
255 * @param ctx the hook context
256 * @param irg the IR graph on which the node is created
257 * @param node the new IR node that was created
259 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
265 key.nr = get_irn_node_nr(node);
266 key.bp.reason = BP_ON_NEW_NODE;
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 created\n", elem->bp.bpnr, node);
276 * A node is replaced.
278 * @param ctx the hook context
279 * @param old the IR node the is replaced
280 * @param nw the new IR node that will replace old
282 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
287 key.nr = get_irn_node_nr(old);
288 key.bp.reason = BP_ON_REPLACE;
290 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
291 if (elem && elem->bp.active) {
292 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
298 * A new node is lowered.
300 * @param ctx the hook context
301 * @param node the new IR node that will be lowered
303 static void dbg_lower(void *ctx, ir_node *node)
308 key.nr = get_irn_node_nr(node);
309 key.bp.reason = BP_ON_LOWER;
311 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
312 if (elem && elem->bp.active) {
313 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
319 * A graph will be deleted.
321 * @param ctx the hook context
322 * @param irg the IR graph that will be deleted
324 static void dbg_free_graph(void *ctx, ir_graph *irg)
329 key.nr = get_irg_graph_nr(irg);
330 key.bp.reason = BP_ON_REMIRG;
332 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
333 if (elem && elem->bp.active) {
334 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
339 bp_ident_t key, *elem;
340 ir_entity *ent = get_irg_entity(irg);
345 key.id = get_entity_ident(ent);
346 key.bp.reason = BP_ON_REMIRG;
348 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
349 if (elem && elem->bp.active) {
350 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
354 } /* dbg_free_graph */
357 * An entity was created.
359 * @param ctx the hook context
360 * @param ent the newly created entity
362 static void dbg_new_entity(void *ctx, ir_entity *ent)
366 bp_ident_t key, *elem;
368 key.id = get_entity_ident(ent);
369 key.bp.reason = BP_ON_NEW_ENT;
371 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
372 if (elem && elem->bp.active) {
373 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
380 key.nr = get_entity_nr(ent);
381 key.bp.reason = BP_ON_NEW_ENT;
383 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
384 if (elem && elem->bp.active) {
385 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
389 } /* dbg_new_entity */
392 * A type was created.
394 * @param ctx the hook context
395 * @param tp the newly created type
397 static void dbg_new_type(void *ctx, ir_type *tp)
403 key.nr = get_type_nr(tp);
404 key.bp.reason = BP_ON_NEW_TYPE;
406 elem = set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
407 if (elem && elem->bp.active) {
408 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
413 bp_ident_t key, *elem;
415 key.id = get_type_ident(tp);
416 key.bp.reason = BP_ON_NEW_TYPE;
418 elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
419 if (elem && elem->bp.active) {
420 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
427 * Return the reason string.
429 static const char *reason_str(bp_reasons_t reason)
432 case BP_ON_NEW_NODE: return "node creation";
433 case BP_ON_REPLACE: return "node replace";
434 case BP_ON_LOWER: return "node lowering";
435 case BP_ON_REMIRG: return "removing IRG";
436 case BP_ON_NEW_ENT: return "entity creation";
437 case BP_ON_NEW_TYPE: return "type creation";
444 * Compare two number breakpoints.
446 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
448 const bp_nr_t *e1 = elt;
449 const bp_nr_t *e2 = key;
452 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
456 * Compare two ident breakpoints.
458 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
460 const bp_ident_t *e1 = elt;
461 const bp_ident_t *e2 = key;
464 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
470 static void update_hooks(breakpoint *bp)
472 #define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
473 #define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
476 ++num_active_bp[bp->reason];
478 --num_active_bp[bp->reason];
480 if (num_active_bp[bp->reason] > 0) {
481 /* register the hooks on demand */
482 switch (bp->reason) {
483 CASE_ON(BP_ON_NEW_NODE, new_node);
484 CASE_ON(BP_ON_REPLACE, replace);
485 CASE_ON(BP_ON_LOWER, lower);
486 CASE_ON(BP_ON_REMIRG, free_graph);
487 CASE_ON(BP_ON_NEW_ENT, new_entity);
488 CASE_ON(BP_ON_NEW_TYPE, new_type);
494 /* unregister the hook on demand */
495 switch (bp->reason) {
496 CASE_OFF(BP_ON_NEW_NODE, new_node);
497 CASE_OFF(BP_ON_REPLACE, replace);
498 CASE_OFF(BP_ON_LOWER, lower);
499 CASE_OFF(BP_ON_REMIRG, free_graph);
500 CASE_OFF(BP_ON_NEW_ENT, new_entity);
501 CASE_OFF(BP_ON_NEW_TYPE, new_type);
511 * Break if nr is reached.
513 static void break_on_nr(long nr, bp_reasons_t reason)
520 key.bp.reason = reason;
523 elem = set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
525 if (elem->bp.bpnr == 0) {
526 /* new break point */
527 elem->bp.bpnr = ++bp_num;
528 elem->bp.next = bp_list;
531 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
533 update_hooks(&elem->bp);
538 * Break if ident name is reached.
540 static void break_on_ident(const char *name, bp_reasons_t reason) {
541 bp_ident_t key, *elem;
543 key.bp.kind = BP_IDENT;
546 key.bp.reason = reason;
547 key.id = new_id_from_str(name);
549 elem = set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
551 if (elem->bp.bpnr == 0) {
552 /* new break point */
553 elem->bp.bpnr = ++bp_num;
554 elem->bp.next = bp_list;
557 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
559 update_hooks(&elem->bp);
561 } /* break_on_ident */
564 * Sets/resets the active flag of breakpoint bp.
566 static void bp_activate(unsigned bp, int active)
570 for (p = bp_list; p; p = p->next) {
572 if (p->active != active) {
577 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
581 dbg_printf("Error: Firm BP %u not exists.\n", bp);
586 * Show a list of supported commands
588 static void show_commands(void) {
589 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
590 "init break after initialization\n"
591 "create nr break if node nr was created\n"
592 "replace nr break if node nr is replaced by another node\n"
593 "lower nr break before node nr is lowered\n"
594 "remirg nr|name break if the irg of nr or entity name is deleted\n"
595 "newent nr|name break if the entity nr or name was created\n"
596 "newtype nr|name break if the type nr or name was created\n"
597 "bp show all breakpoints\n"
598 "enable nr enable breakpoint nr\n"
599 "disable nr disable breakpoint nr\n"
600 "showtype nr|name show content of the type nr or name\n"
601 "showent nr|name show content of the entity nr or name\n"
602 "setmask name msk sets the debug module name to mask msk\n"
603 "setlvl name lvl sets the debug module name to level lvl\n"
604 "setoutfile name file redirects debug output of module name to file\n"
605 "irgname name prints address and graph number of a method given by its name\n"
606 "irgldname ldname prints address and graph number of a method given by its ldname\n"
607 "help list all commands\n"
609 } /* show_commands */
612 * Shows all Firm breakpoints.
614 static void show_bp(void) {
620 dbg_printf("Firm Breakpoints:");
621 for (p = bp_list; p; p = p->next) {
623 dbg_printf("+\n BP %u: ", p->bpnr);
627 node_p = (bp_nr_t *)p;
628 dbg_printf("%s of Nr %ld ", reason_str(p->reason), node_p->nr);
632 ident_p = (bp_ident_t *)p;
633 dbg_printf("+%s of ident \"%s\" ", reason_str(p->reason), get_id_str(ident_p->id));
637 dbg_printf(p->active ? "+enabled" : "+disabled");
639 dbg_printf(have_one ? "+\n" : "+ NONE\n");
643 * firm_dbg_register() expects that the name is stored persistent.
644 * So we need this little helper function
646 static firm_dbg_module_t *dbg_register(const char *name) {
647 ident *id = new_id_from_str(name);
649 return firm_dbg_register(get_id_str(id));
653 * Sets the debug mask of module name to lvl
655 static void set_dbg_level(const char *name, unsigned lvl)
657 firm_dbg_module_t *module = dbg_register(name);
659 if (firm_dbg_get_mask(module) != lvl) {
660 firm_dbg_set_mask(module, lvl);
662 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
664 } /* set_dbg_level */
667 * Redirects the debug output of module name to fname
669 static void set_dbg_outfile(const char *name, const char *fname)
671 firm_dbg_module_t *module = dbg_register(name);
672 FILE *f = fopen(fname, "w");
679 firm_dbg_set_file(module, f);
680 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
681 } /* set_dbg_outfile */
684 * Show info about a firm thing.
686 static void show_firm_object(void *firm_thing) {
689 if (firm_thing == NULL) {
690 fprintf(f, "<NULL>\n");
693 switch (get_kind(firm_thing)) {
695 fprintf(f, "BAD: (%p)\n", firm_thing);
698 dump_entity_to_file(f, firm_thing, dump_verbosity_max);
701 dump_type_to_file(f, firm_thing, dump_verbosity_max);
709 case k_ir_compound_graph_path:
715 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
717 } /* show_firm_object */
720 * Find a firm type by its number.
722 static ir_type *find_type_nr(long nr) {
723 int i, n = get_irp_n_types();
726 for (i = 0; i < n; ++i) {
727 tp = get_irp_type(i);
728 if (get_type_nr(tp) == nr)
731 tp = get_glob_type();
732 if (get_type_nr(tp) == nr)
738 * Find a firm type by its name.
740 static ir_type *find_type_name(const char *name) {
741 int i, n = get_irp_n_types();
744 for (i = 0; i < n; ++i) {
745 tp = get_irp_type(i);
746 if (strcmp(get_type_name(tp), name) == 0)
749 tp = get_glob_type();
750 if (strcmp(get_type_name(tp), name) == 0)
753 } /* find_type_name */
755 /** The environment for the entity search functions. */
756 typedef struct find_env {
758 long nr; /**< the number that is searched for */
759 const char *name; /**< the name that is searched for */
761 ir_entity *res; /**< the result */
765 * Type-walker: Find an entity with given number.
767 static void check_ent_nr(type_or_ent tore, void *ctx) {
768 find_env_t *env = ctx;
770 if (is_entity(tore.ent)) {
771 if (get_entity_nr(tore.ent) == env->u.nr) {
778 * Type-walker: Find an entity with given name.
780 static void check_ent_name(type_or_ent tore, void *ctx) {
781 find_env_t *env = ctx;
783 if (is_entity(tore.ent))
784 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
787 } /* check_ent_name */
790 * Find a firm entity by its number.
792 static ir_entity *find_entity_nr(long nr) {
797 type_walk(check_ent_nr, NULL, &env);
799 } /* find_entity_nr */
802 * Find a firm entity by its name.
804 static ir_entity *find_entity_name(const char *name) {
809 type_walk(check_ent_name, NULL, &env);
811 } /* find_entity_name */
814 * Search methods for a name.
816 static void show_by_name(type_or_ent tore, void *env) {
817 ident *id = (ident *)env;
819 if (is_entity(tore.ent)) {
820 ir_entity *ent = tore.ent;
822 if (is_method_entity(ent)) {
823 if (get_entity_ident(ent) == id) {
824 ir_type *owner = get_entity_owner(ent);
825 ir_graph *irg = get_entity_irg(ent);
827 if (owner != get_glob_type()) {
828 printf("%s::%s", get_type_name(owner), get_id_str(id));
830 printf("%s", get_id_str(id));
833 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
842 * Search methods for a ldname.
844 static void show_by_ldname(type_or_ent tore, void *env) {
845 ident *id = (ident *)env;
847 if (is_entity(tore.ent)) {
848 ir_entity *ent = tore.ent;
850 if (is_method_entity(ent)) {
851 if (get_entity_ld_ident(ent) == id) {
852 ir_type *owner = get_entity_owner(ent);
853 ir_graph *irg = get_entity_irg(ent);
855 if (owner != get_glob_type()) {
856 printf("%s::%s", get_type_name(owner), get_id_str(id));
858 printf("%s", get_id_str(id));
861 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
867 } /* show_by_ldname */
870 * prints the address and graph number of all irgs with given name
872 static void irg_name(const char *name) {
873 ident *id = new_id_from_str(name);
875 type_walk(show_by_name, NULL, (void *)id);
879 * prints the address and graph number of all irgs with given ld_name
881 static void irg_ld_name(const char *name) {
882 ident *id = new_id_from_str(name);
884 type_walk(show_by_ldname, NULL, (void *)id);
912 static const char *reserved[] = {
936 static struct lexer {
937 int has_token; /**< set if a token is cached. */
938 unsigned cur_token; /**< current token. */
939 unsigned number; /**< current token attribute. */
940 const char *s; /**< current token attribute. */
941 unsigned len; /**< current token attribute. */
943 const char *curr_pos;
945 const char *tok_start;
949 * Initialize the lexer.
951 static void init_lexer(const char *input) {
953 lexer.curr_pos = input;
954 lexer.end_pos = input + strlen(input);
959 * Get the next char from the input.
961 static char next_char(void) {
962 if (lexer.curr_pos >= lexer.end_pos)
964 return *lexer.curr_pos++;
967 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
970 #define MIN(a, b) (a) < (b) ? (a) : (b)
975 static unsigned get_token(void) {
979 /* skip white space */
982 } while (c != '\0' && isspace(c));
984 lexer.tok_start = lexer.curr_pos - 1;
985 if (c == '.' || isalpha(c)) {
986 /* command begins here */
988 const char* tok_start;
993 } while (isgraph(c));
996 tok_start = lexer.tok_start;
997 if (*tok_start == '.') {
1001 for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) {
1002 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
1007 lexer.s = lexer.tok_start;
1008 lexer.len = lexer.curr_pos - lexer.s;
1009 return tok_identifier;
1010 } else if (isdigit(c) || c == '-') {
1011 unsigned number = 0;
1014 /* we support negative numbers as well, so one can easily set all bits with -1 */
1023 if (c == 'x' || c == 'X') {
1030 number = (number << 4) | (c - '0');
1032 number = (number << 4) | (toupper(c) - 'A' + 10);
1035 lexer.number = number;
1042 number = number * 10 + (c - '0');
1046 lexer.number = sign ? 0 - number : number;
1055 * High level function to use from debugger interface
1057 * See show_commands() for supported commands.
1059 void firm_debug(const char *cmd) {
1060 char name[1024], fname[1024];
1068 token = get_token();
1075 token = get_token();
1076 if (token != tok_number)
1078 break_on_nr(lexer.number, BP_ON_NEW_NODE);
1082 token = get_token();
1083 if (token != tok_number)
1085 break_on_nr(lexer.number, BP_ON_REPLACE);
1089 token = get_token();
1090 if (token != tok_number)
1092 break_on_nr(lexer.number, BP_ON_LOWER);
1096 token = get_token();
1098 if (token == tok_number)
1099 break_on_nr(lexer.number, BP_ON_REMIRG);
1100 else if (token == tok_identifier) {
1101 len = MIN(lexer.len, 1023);
1102 strncpy(name, lexer.s, len);
1104 break_on_ident(name, BP_ON_REMIRG);
1110 token = get_token();
1112 if (token == tok_number)
1113 break_on_nr(lexer.number, BP_ON_NEW_ENT);
1114 else if (token == tok_identifier) {
1115 len = MIN(lexer.len, 1023);
1116 strncpy(name, lexer.s, len);
1118 break_on_ident(name, BP_ON_NEW_ENT);
1124 token = get_token();
1126 if (token == tok_number)
1127 break_on_nr(lexer.number, BP_ON_NEW_TYPE);
1128 else if (token == tok_identifier) {
1129 len = MIN(lexer.len, 1023);
1130 strncpy(name, lexer.s, len);
1132 break_on_ident(name, BP_ON_NEW_TYPE);
1138 token = get_token();
1140 if (token == tok_number)
1141 show_firm_object(find_type_nr(lexer.number));
1142 else if (token == tok_identifier) {
1143 len = MIN(lexer.len, 1023);
1144 strncpy(name, lexer.s, len);
1146 show_firm_object(find_type_name(name));
1152 token = get_token();
1154 if (token == tok_number)
1155 show_firm_object(find_entity_nr(lexer.number));
1156 else if (token == tok_identifier) {
1157 len = MIN(lexer.len, 1023);
1158 strncpy(name, lexer.s, len);
1160 show_firm_object(find_entity_name(name));
1174 token = get_token();
1175 if (token != tok_number)
1177 bp_activate(lexer.number, 1);
1181 token = get_token();
1182 if (token != tok_number)
1184 bp_activate(lexer.number, 0);
1188 token = get_token();
1189 if (token != tok_identifier)
1191 len = MIN(lexer.len, 1023);
1192 strncpy(name, lexer.s, len);
1195 token = get_token();
1196 if (token != tok_number)
1198 set_dbg_level(name, lexer.number);
1202 token = get_token();
1203 if (token != tok_identifier)
1205 len = MIN(lexer.len, 1023);
1206 strncpy(name, lexer.s, len);
1209 token = get_token();
1210 if (token != tok_number)
1212 set_dbg_level(name, (1 << lexer.number) - 1);
1215 case tok_setoutfile:
1216 token = get_token();
1217 if (token != tok_identifier)
1219 len = MIN(lexer.len, 1023);
1220 strncpy(name, lexer.s, len);
1223 token = get_token();
1224 if (token != tok_identifier)
1226 len = MIN(lexer.len, 1023);
1227 strncpy(fname, lexer.s, len);
1229 set_dbg_outfile(name, fname);
1232 token = get_token();
1233 if (token != tok_identifier)
1235 len = MIN(lexer.len, 1023);
1236 strncpy(name, lexer.s, len);
1241 token = get_token();
1242 if (token != tok_identifier)
1244 len = MIN(lexer.len, 1023);
1245 strncpy(name, lexer.s, len);
1257 printf("Error: before %s\n", lexer.tok_start);
1262 token = get_token();
1263 if (token == tok_eof)
1272 /* creates the debugger tables */
1273 void firm_init_debugger(void)
1277 bp_numbers = new_set(cmp_nr_bp, 8);
1278 bp_idents = new_set(cmp_ident_bp, 8);
1280 env = getenv("FIRMDBG");
1289 } /* firm_init_debugger */
1292 * A gdb helper function to print firm objects.
1294 const char *gdb_node_helper(void *firm_object) {
1295 static char buf[1024];
1296 ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
1301 * A gdb helper function to print tarvals.
1303 const char *gdb_tarval_helper(void *tv_object) {
1304 static char buf[1024];
1305 ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
1309 const char *gdb_out_edge_helper(const ir_node *node) {
1310 static char buf[4*1024];
1313 size_t len = sizeof(buf);
1314 const ir_edge_t *edge;
1315 foreach_out_edge(node, edge) {
1316 ir_node *n = get_edge_src_irn(edge);
1318 ir_snprintf(b, len, "%+F ", n);
1329 /* some picky compiler do not allow empty files */
1330 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1335 * @page debugger The Firm debugger extension
1337 * Firm contains a debugger extension. This allows to set debugger breakpoints
1338 * an various events.
1339 * The extension uses a text interface which can be accessed from most debuggers.
1340 * More than one command can be given separated by ';'.
1342 * @section sec_cmd Supported commands
1344 * Historically all debugger commands start with a dot. This isn't needed in newer
1345 * versions, but still supported, ie the commands ".init" and "init" are equal.
1346 * The following commands are currently supported:
1350 * Break immediately after the debugger extension was initialized.
1351 * Typically this command is used in the environment to stop the execution
1352 * of a Firm compiler right after the initialization, like this:
1354 * $export FIRMDBG=".init"
1358 * Break if a new IR-node with node number nr was created.
1359 * Typically used to find the place where wrong nodes are created.
1363 * Break before IR-node with node number nr is replaced by another node.
1367 * Break before IR-node with node number nr is lowered.
1371 * Break if the irg with graph number nr is deleted.
1375 * Break if the irg of entity name is deleted.
1379 * Break if the entity with number nr was created.
1383 * Break if the entity name was created.
1387 * Break if the type with number nr was created.
1391 * Break if the type name was created.
1395 * Show all Firm internal breakpoints.
1399 * Enables breakpoint nr.
1403 * Disables breakpoint nr.
1407 * Show the content of entity nr.
1411 * Show the content of entity name.
1415 * Show the content of type nr.
1419 * Show the content of type name.
1421 * @b setmask name msk
1423 * Sets the debug module name to mask msk.
1425 * @b setlvl name lvl
1427 * Sets the debug module name to level lvl.
1429 * @b setoutfile name file
1431 * Redirects debug output of module name to file.
1435 * Prints address and graph number of a method given by its name.
1439 * Prints address and graph number of a method given by its linker name.
1443 * List all commands.
1446 * The Firm debugger extension can be accessed using the function firm_debug().
1447 * The following example shows how to set a creation breakpoint in GDB when
1448 * node 2101 is created.
1450 * -# set FIRMDBG="init"
1451 * -# start gdb with your compiler
1452 * -# after gdb breaks, issue
1454 * call firm_debug("create 2101")
1456 * On the console the following text should be issued:
1458 * Firm BP 1: creation of Node 2101
1461 * @section gdb_macro GDB macro
1463 * Add the following to your .gdbinit file:
1466 # define firm "cmd" Firm debugger extension
1469 call firm_debug($arg0)
1473 * Then, all Firm debugger extension commands can be accessed in the gdb
1474 * console using the firm prefix, eg.:
1476 * firm "create 2101"