2 * Copyright (C) 1995-2010 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 #define WIN32_LEAN_AND_MEAN
48 #include "irgraph_t.h"
52 #include "iredges_t.h"
58 /* Break into the debugger. The Win32 way. */
59 void firm_debug_break(void)
63 #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64))
64 /* Break into the debugger. The ia32/x86_64 way under GCC. */
65 void firm_debug_break(void)
67 __asm__ __volatile__("int3");
70 /* Break into the debugger. Poor Unix way. */
71 void firm_debug_break(void)
77 /** supported breakpoint kinds */
79 BP_NR = 'n', /**< break on node number. */
80 BP_IDENT = 'i' /**< break on ident. */
84 * Reasons for node number breakpoints.
86 typedef enum bp_reasons_t {
87 BP_ON_NEW_THING, /**< break if node, entity or type with number is created */
88 BP_ON_REPLACE, /**< break if node with number is replaced */
89 BP_ON_LOWER, /**< break if node with number is lowered */
90 BP_ON_REMIRG, /**< break if an IRG is removed */
91 BP_ON_NEW_ENT, /**< break if a new entity is created */
96 typedef struct breakpoint {
97 bp_kind kind; /**< the kind of this break point */
98 unsigned bpnr; /**< break point number */
99 int active; /**< non-zero, if this break point is active */
100 bp_reasons_t reason; /**< reason for the breakpoint */
101 struct breakpoint *next; /**< link to the next one */
104 /** A number breakpoint. */
106 breakpoint bp; /**< the breakpoint data */
107 long nr; /**< the node number */
110 /** Calculate the hash value for a node breakpoint. */
111 #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason)
113 /** An ident breakpoint. */
115 breakpoint bp; /**< the breakpoint data */
116 ident *id; /**< the ident */
119 /** Calculate the hash value for an ident breakpoint. */
120 #define HASH_IDENT_BP(key) (hash_ptr((key).id) ^ (key).bp.reason)
122 /** The set containing the breakpoints on node numbers. */
123 static set *bp_numbers;
125 /** The set containing the breakpoints on idents. */
126 static set *bp_idents;
128 /**< the list of all breakpoints */
129 static breakpoint *bp_list;
131 /** number of the current break point */
132 static unsigned bp_num = 0;
134 /** set if break on init command was issued. */
135 static int break_on_init = 0;
137 /** the hook entries for the Firm debugger module. */
138 static hook_entry_t debugger_hooks[hook_last];
140 /** number of active breakpoints to maintain hooks. */
141 static unsigned num_active_bp[BP_MAX_REASON];
144 * The debug message buffer
146 static char firm_dbg_msg_buf[2048];
149 * If set, the debug extension writes all output to the
150 * firm_dbg_msg_buf buffer
152 static int redir_output = 0;
155 * Is set to one, if the debug extension is active
157 static int is_active = 0;
159 /** hook the hook h with function fkt. */
160 #define HOOK(h, fkt) \
162 debugger_hooks[h].hook._##h = fkt; \
163 register_hook(h, &debugger_hooks[h]); \
166 /** unhook the hook h */
169 unregister_hook(h, &debugger_hooks[h]); \
170 debugger_hooks[h].hook._##h = NULL; \
173 /** returns non-zero if a entry hook h is used */
174 #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL)
176 /* some macros needed to create the info string */
177 #define _DBG_VERSION(major, minor) #major "." #minor
178 #define DBG_VERSION(major, minor) _DBG_VERSION(major, minor)
179 #define API_VERSION(major, minor) "API:" DBG_VERSION(major, minor)
181 /* the API version: change if needed */
182 #define FIRM_DBG_MAJOR 1
183 #define FIRM_DBG_MINOR 0
185 /** for automatic detection of the debug extension */
186 static const char __attribute__((used)) firm_debug_info_string[] =
187 API_VERSION(FIRM_DBG_MAJOR, FIRM_DBG_MINOR);
189 int firm_debug_active(void)
195 * Reset the debug text buffer.
197 static void reset_dbg_buf(void)
199 firm_dbg_msg_buf[0] = '\0';
202 static void add_to_dbg_buf(const char *buf)
204 strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
207 const char *firm_debug_text(void)
209 firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
210 return firm_dbg_msg_buf;
216 static void dbg_printf(const char *fmt, ...)
228 ir_vsnprintf(buf, sizeof(buf), fmt, args);
238 * A new node is created.
240 * @param ctx the hook context
241 * @param irg the IR graph on which the node is created
242 * @param node the new IR node that was created
244 static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node)
250 key.nr = get_irn_node_nr(node);
251 key.bp.reason = BP_ON_NEW_THING;
253 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
254 if (elem && elem->bp.active) {
255 dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
261 * A node is replaced.
263 * @param ctx the hook context
264 * @param old the IR node the is replaced
265 * @param nw the new IR node that will replace old
267 static void dbg_replace(void *ctx, ir_node *old, ir_node *nw)
272 key.nr = get_irn_node_nr(old);
273 key.bp.reason = BP_ON_REPLACE;
275 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
276 if (elem && elem->bp.active) {
277 dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
283 * A new node is lowered.
285 * @param ctx the hook context
286 * @param node the new IR node that will be lowered
288 static void dbg_lower(void *ctx, ir_node *node)
293 key.nr = get_irn_node_nr(node);
294 key.bp.reason = BP_ON_LOWER;
296 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
297 if (elem && elem->bp.active) {
298 dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
304 * A graph will be deleted.
306 * @param ctx the hook context
307 * @param irg the IR graph that will be deleted
309 static void dbg_free_graph(void *ctx, ir_graph *irg)
314 key.nr = get_irg_graph_nr(irg);
315 key.bp.reason = BP_ON_REMIRG;
317 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
318 if (elem && elem->bp.active) {
319 ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
324 bp_ident_t key, *elem;
325 ir_entity *ent = get_irg_entity(irg);
330 key.id = get_entity_ident(ent);
331 key.bp.reason = BP_ON_REMIRG;
333 elem = (bp_ident_t*)set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
334 if (elem && elem->bp.active) {
335 dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
342 * An entity was created.
344 * @param ctx the hook context
345 * @param ent the newly created entity
347 static void dbg_new_entity(void *ctx, ir_entity *ent)
351 bp_ident_t key, *elem;
353 key.id = get_entity_ident(ent);
354 key.bp.reason = BP_ON_NEW_ENT;
356 elem = (bp_ident_t*)set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
357 if (elem && elem->bp.active) {
358 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
365 key.nr = get_entity_nr(ent);
366 key.bp.reason = BP_ON_NEW_THING;
368 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
369 if (elem && elem->bp.active) {
370 dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
377 * A type was created.
379 * @param ctx the hook context
380 * @param tp the newly created type
382 static void dbg_new_type(void *ctx, ir_type *tp)
388 key.nr = get_type_nr(tp);
389 key.bp.reason = BP_ON_NEW_THING;
391 elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
392 if (elem && elem->bp.active) {
393 ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
400 * Return the reason string.
402 static const char *reason_str(bp_reasons_t reason)
405 case BP_ON_NEW_THING: return "node, entity or type creation";
406 case BP_ON_REPLACE: return "node replace";
407 case BP_ON_LOWER: return "node lowering";
408 case BP_ON_REMIRG: return "removing IRG";
409 case BP_ON_NEW_ENT: return "entity creation";
410 case BP_MAX_REASON: break;
412 panic("unsupported reason");
416 * Compare two number breakpoints.
418 static int cmp_nr_bp(const void *elt, const void *key, size_t size)
420 const bp_nr_t *e1 = (const bp_nr_t*)elt;
421 const bp_nr_t *e2 = (const bp_nr_t*)key;
424 return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason);
428 * Compare two ident breakpoints.
430 static int cmp_ident_bp(const void *elt, const void *key, size_t size)
432 const bp_ident_t *e1 = (const bp_ident_t*)elt;
433 const bp_ident_t *e2 = (const bp_ident_t*)key;
436 return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason);
442 static void update_hooks(breakpoint *bp)
444 #define CASE_ON(a, hook, handler) case a: if (! IS_HOOKED(hook)) HOOK(hook, handler); break
445 #define CASE_OFF(a, hook) case a: if (IS_HOOKED(hook)) UNHOOK(hook); break
448 ++num_active_bp[bp->reason];
450 --num_active_bp[bp->reason];
452 if (num_active_bp[bp->reason] > 0) {
453 /* register the hooks on demand */
454 switch (bp->reason) {
455 CASE_ON(BP_ON_REPLACE, hook_replace, dbg_replace);
456 CASE_ON(BP_ON_LOWER, hook_lower, dbg_lower);
457 CASE_ON(BP_ON_REMIRG, hook_free_graph, dbg_free_graph);
458 CASE_ON(BP_ON_NEW_ENT, hook_new_entity, dbg_new_entity);
459 case BP_ON_NEW_THING:
460 if (!IS_HOOKED(hook_new_node))
461 HOOK(hook_new_node, dbg_new_node);
462 if (!IS_HOOKED(hook_new_type))
463 HOOK(hook_new_type, dbg_new_type);
464 if (!IS_HOOKED(hook_new_entity))
465 HOOK(hook_new_entity, dbg_new_entity);
472 /* unregister the hook on demand */
473 switch (bp->reason) {
474 CASE_OFF(BP_ON_REPLACE, hook_replace);
475 CASE_OFF(BP_ON_LOWER, hook_lower);
476 CASE_OFF(BP_ON_REMIRG, hook_free_graph);
477 CASE_OFF(BP_ON_NEW_ENT, hook_new_entity);
478 case BP_ON_NEW_THING:
479 if (IS_HOOKED(hook_new_node))
480 UNHOOK(hook_new_node);
481 if (IS_HOOKED(hook_new_type))
482 UNHOOK(hook_new_type);
483 if (IS_HOOKED(hook_new_entity))
484 UNHOOK(hook_new_entity);
495 * Break if nr is reached.
497 static void break_on_nr(long nr, bp_reasons_t reason)
504 key.bp.reason = reason;
507 elem = (bp_nr_t*)set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
509 if (elem->bp.bpnr == 0) {
510 /* new break point */
511 elem->bp.bpnr = ++bp_num;
512 elem->bp.next = bp_list;
515 dbg_printf("Firm BP %u: %s of Nr %ld\n", elem->bp.bpnr, reason_str(reason), nr);
517 update_hooks(&elem->bp);
522 * Break if ident name is reached.
524 static void break_on_ident(const char *name, bp_reasons_t reason)
526 bp_ident_t key, *elem;
528 key.bp.kind = BP_IDENT;
531 key.bp.reason = reason;
532 key.id = new_id_from_str(name);
534 elem = (bp_ident_t*)set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
536 if (elem->bp.bpnr == 0) {
537 /* new break point */
538 elem->bp.bpnr = ++bp_num;
539 elem->bp.next = bp_list;
542 dbg_printf("Firm BP %u: %s of ident \"%s\"\n", elem->bp.bpnr, reason_str(reason), name);
544 update_hooks(&elem->bp);
549 * Sets/resets the active flag of breakpoint bp.
551 static void bp_activate(unsigned bp, int active)
555 for (p = bp_list; p; p = p->next) {
557 if (p->active != active) {
562 dbg_printf("Firm BP %u is now %s\n", bp, active ? "enabled" : "disabled");
566 dbg_printf("Error: Firm BP %u not exists.\n", bp);
571 * Show a list of supported commands
573 static void show_commands(void)
575 dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
576 "init break after initialization\n"
577 "create nr break if node nr was created\n"
578 "replace nr break if node nr is replaced by another node\n"
579 "lower nr break before node nr is lowered\n"
580 "remirg nr|name break if the irg of nr or entity name is deleted\n"
581 "newent nr|name break if the entity nr or name was created\n"
582 "newtype nr|name break if the type nr or name was created\n"
583 "bp show all breakpoints\n"
584 "enable nr enable breakpoint nr\n"
585 "disable nr disable breakpoint nr\n"
586 "showtype nr|name show content of the type nr or name\n"
587 "showent nr|name show content of the entity nr or name\n"
588 "setmask name msk sets the debug module name to mask msk\n"
589 "setlvl name lvl sets the debug module name to level lvl\n"
590 "setoutfile name file redirects debug output of module name to file\n"
591 "irgname name prints address and graph number of a method given by its name\n"
592 "irgldname ldname prints address and graph number of a method given by its ldname\n"
593 "help list all commands\n"
598 * Shows all Firm breakpoints.
600 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)
635 ident *id = new_id_from_str(name);
637 return firm_dbg_register(get_id_str(id));
641 * Sets the debug mask of module name to lvl
643 static void set_dbg_level(const char *name, unsigned lvl)
645 firm_dbg_module_t *module = dbg_register(name);
647 if (firm_dbg_get_mask(module) != lvl) {
648 firm_dbg_set_mask(module, lvl);
650 dbg_printf("Setting debug mask of module %s to %u\n", name, lvl);
655 * Redirects the debug output of module name to fname
657 static void set_dbg_outfile(const char *name, const char *fname)
659 firm_dbg_module_t *module = dbg_register(name);
660 FILE *f = fopen(fname, "w");
667 firm_dbg_set_file(module, f);
668 dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname);
672 * Show info about a firm thing.
674 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, (ir_entity*)firm_thing);
690 dump_type_to_file(f, (ir_type*)firm_thing);
698 case k_ir_compound_graph_path:
704 fprintf(f, "Cannot identify thing at (%p).\n", firm_thing);
709 * Find a firm type by its number.
711 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)
732 int i, n = get_irp_n_types();
735 for (i = 0; i < n; ++i) {
736 tp = get_irp_type(i);
737 if (!is_compound_type(tp))
740 if (strcmp(get_compound_name(tp), name) == 0)
743 tp = get_glob_type();
744 if (strcmp(get_compound_name(tp), name) == 0)
749 /** The environment for the entity search functions. */
750 typedef struct find_env {
752 long nr; /**< the number that is searched for */
753 const char *name; /**< the name that is searched for */
755 ir_entity *res; /**< the result */
759 * Type-walker: Find an entity with given number.
761 static void check_ent_nr(type_or_ent tore, void *ctx)
763 find_env_t *env = (find_env_t*)ctx;
765 if (is_entity(tore.ent)) {
766 if (get_entity_nr(tore.ent) == env->u.nr) {
773 * Type-walker: Find an entity with given name.
775 static void check_ent_name(type_or_ent tore, void *ctx)
777 find_env_t *env = (find_env_t*)ctx;
779 if (is_entity(tore.ent))
780 if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) {
786 * Find a firm entity by its number.
788 static ir_entity *find_entity_nr(long nr)
794 type_walk(check_ent_nr, NULL, &env);
799 * Find a firm entity by its name.
801 static ir_entity *find_entity_name(const char *name)
807 type_walk(check_ent_name, NULL, &env);
812 * Search methods for a name.
814 static void show_by_name(type_or_ent tore, void *env)
816 ident *id = (ident *)env;
818 if (is_entity(tore.ent)) {
819 ir_entity *ent = tore.ent;
821 if (is_method_entity(ent)) {
822 if (get_entity_ident(ent) == id) {
823 ir_type *owner = get_entity_owner(ent);
824 ir_graph *irg = get_entity_irg(ent);
826 if (owner != get_glob_type()) {
827 printf("%s::%s", get_compound_name(owner), get_id_str(id));
829 printf("%s", get_id_str(id));
832 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
841 * Search methods for a ldname.
843 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_compound_name(owner), get_id_str(id));
858 printf("%s", get_id_str(id));
861 printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg);
870 * prints the address and graph number of all irgs with given name
872 static void irg_name(const char *name)
874 ident *id = new_id_from_str(name);
876 type_walk(show_by_name, NULL, (void *)id);
880 * prints the address and graph number of all irgs with given ld_name
882 static void irg_ld_name(const char *name)
884 ident *id = new_id_from_str(name);
886 type_walk(show_by_ldname, NULL, (void *)id);
891 tok_bp = first_token,
915 static const char *reserved[] = {
939 static struct lexer {
940 int has_token; /**< set if a token is cached. */
941 unsigned cur_token; /**< current token. */
942 unsigned number; /**< current token attribute. */
943 const char *s; /**< current token attribute. */
944 size_t len; /**< current token attribute. */
946 const char *curr_pos;
948 const char *tok_start;
952 * Initialize the lexer.
954 static void init_lexer(const char *input)
957 lexer.curr_pos = input;
958 lexer.end_pos = input + strlen(input);
963 * Get the next char from the input.
965 static char next_char(void)
967 if (lexer.curr_pos >= lexer.end_pos)
969 return *lexer.curr_pos++;
972 #define unput() if (lexer.curr_pos < lexer.end_pos) --lexer.curr_pos
975 #define MIN(a, b) (a) < (b) ? (a) : (b)
980 static unsigned get_token(void)
985 /* skip white space */
988 } while (c != '\0' && isspace((unsigned char)c));
990 lexer.tok_start = lexer.curr_pos - 1;
991 if (c == '.' || isalpha((unsigned char)c)) {
992 /* command begins here */
994 const char* tok_start;
999 } while (isgraph((unsigned char)c));
1002 tok_start = lexer.tok_start;
1003 if (*tok_start == '.') {
1007 for (i = ARRAY_SIZE(reserved); i-- != 0;) {
1008 if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
1009 return first_token + i;
1013 lexer.s = lexer.tok_start;
1014 lexer.len = lexer.curr_pos - lexer.s;
1015 return tok_identifier;
1016 } else if (isdigit((unsigned char)c) || c == '-') {
1017 unsigned number = 0;
1020 /* we support negative numbers as well, so one can easily set all bits with -1 */
1029 if (c == 'x' || c == 'X') {
1033 if (! isxdigit((unsigned char)c))
1035 if (isdigit((unsigned char)c))
1036 number = (number << 4) | (c - '0');
1038 number = (number << 4) | (toupper((unsigned char)c) - 'A' + 10);
1041 lexer.number = number;
1046 if (! isdigit((unsigned char)c))
1048 number = number * 10 + (c - '0');
1052 lexer.number = sign ? 0 - number : number;
1060 void firm_debug(const char *cmd)
1062 char name[1024], fname[1024];
1070 token = get_token();
1077 token = get_token();
1078 if (token != tok_number)
1080 break_on_nr(lexer.number, BP_ON_NEW_THING);
1084 token = get_token();
1085 if (token != tok_number)
1087 break_on_nr(lexer.number, BP_ON_REPLACE);
1091 token = get_token();
1092 if (token != tok_number)
1094 break_on_nr(lexer.number, BP_ON_LOWER);
1098 token = get_token();
1100 if (token == tok_number)
1101 break_on_nr(lexer.number, BP_ON_REMIRG);
1102 else if (token == tok_identifier) {
1103 len = MIN(lexer.len, 1023);
1104 strncpy(name, lexer.s, len);
1106 break_on_ident(name, BP_ON_REMIRG);
1112 token = get_token();
1114 if (token == tok_number)
1115 break_on_nr(lexer.number, BP_ON_NEW_THING);
1116 else if (token == tok_identifier) {
1117 len = MIN(lexer.len, 1023);
1118 strncpy(name, lexer.s, len);
1120 break_on_ident(name, BP_ON_NEW_ENT);
1126 token = get_token();
1128 if (token == tok_number)
1129 show_firm_object(find_type_nr(lexer.number));
1130 else if (token == tok_identifier) {
1131 len = MIN(lexer.len, 1023);
1132 strncpy(name, lexer.s, len);
1134 show_firm_object(find_type_name(name));
1140 token = get_token();
1142 if (token == tok_number)
1143 show_firm_object(find_entity_nr(lexer.number));
1144 else if (token == tok_identifier) {
1145 len = MIN(lexer.len, 1023);
1146 strncpy(name, lexer.s, len);
1148 show_firm_object(find_entity_name(name));
1162 token = get_token();
1163 if (token != tok_number)
1165 bp_activate(lexer.number, 1);
1169 token = get_token();
1170 if (token != tok_number)
1172 bp_activate(lexer.number, 0);
1176 token = get_token();
1177 if (token != tok_identifier)
1179 len = MIN(lexer.len, 1023);
1180 strncpy(name, lexer.s, len);
1183 token = get_token();
1184 if (token != tok_number)
1186 set_dbg_level(name, lexer.number);
1190 token = get_token();
1191 if (token != tok_identifier)
1193 len = MIN(lexer.len, 1023);
1194 strncpy(name, lexer.s, len);
1197 token = get_token();
1198 if (token != tok_number)
1200 set_dbg_level(name, (1 << lexer.number) - 1);
1203 case tok_setoutfile:
1204 token = get_token();
1205 if (token != tok_identifier)
1207 len = MIN(lexer.len, 1023);
1208 strncpy(name, lexer.s, len);
1211 token = get_token();
1212 if (token != tok_identifier)
1214 len = MIN(lexer.len, 1023);
1215 strncpy(fname, lexer.s, len);
1217 set_dbg_outfile(name, fname);
1221 token = get_token();
1222 if (token != tok_identifier)
1224 len = MIN(lexer.len, 1023);
1225 strncpy(name, lexer.s, len);
1231 token = get_token();
1232 if (token != tok_identifier)
1234 len = MIN(lexer.len, 1023);
1235 strncpy(name, lexer.s, len);
1240 case tok_dumpfilter:
1241 token = get_token();
1242 if (token != tok_identifier)
1244 len = MIN(lexer.len, 1023);
1245 strncpy(name, lexer.s, len);
1247 ir_set_dump_filter(name);
1257 printf("Error: before %s\n", lexer.tok_start);
1262 token = get_token();
1263 if (token == tok_eof)
1272 void firm_init_debugger(void)
1276 bp_numbers = new_set(cmp_nr_bp, 8);
1277 bp_idents = new_set(cmp_ident_bp, 8);
1279 env = getenv("FIRMDBG");
1290 void firm_finish_debugger(void)
1292 del_set(bp_numbers);
1297 * A gdb helper function to print firm objects.
1299 const char *gdb_node_helper(void *firm_object)
1301 static char buf[1024];
1302 ir_snprintf(buf, sizeof(buf), "%+F", firm_object);
1306 const char *gdb_tarval_helper(void *tv_object)
1308 static char buf[1024];
1309 ir_snprintf(buf, sizeof(buf), "%+T", tv_object);
1313 const char *gdb_out_edge_helper(const ir_node *node)
1315 static char buf[4*1024];
1318 size_t len = sizeof(buf);
1319 const ir_edge_t *edge;
1320 foreach_out_edge(node, edge) {
1321 ir_node *n = get_edge_src_irn(edge);
1323 ir_snprintf(b, len, "%+F ", n);
1334 /* some picky compiler do not allow empty files */
1335 static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined;
1340 * @page debugger The Firm debugger extension
1342 * Firm contains a debugger extension. This allows to set debugger breakpoints
1343 * an various events.
1344 * The extension uses a text interface which can be accessed from most debuggers.
1345 * More than one command can be given separated by ';'.
1347 * @section sec_cmd Supported commands
1349 * Historically all debugger commands start with a dot. This isn't needed in newer
1350 * versions, but still supported, ie the commands ".init" and "init" are equal.
1351 * The following commands are currently supported:
1355 * Break immediately after the debugger extension was initialized.
1356 * Typically this command is used in the environment to stop the execution
1357 * of a Firm compiler right after the initialization, like this:
1359 * $export FIRMDBG=".init"
1363 * Break if a new IR-node with node number nr was created.
1364 * Typically used to find the place where wrong nodes are created.
1368 * Break before IR-node with node number nr is replaced by another node.
1372 * Break before IR-node with node number nr is lowered.
1376 * Break if the irg with graph number nr is deleted.
1380 * Break if the irg of entity name is deleted.
1384 * Break if the entity with number nr was created.
1388 * Break if the entity name was created.
1392 * Break if the type with number nr was created.
1396 * Break if the type name was created.
1400 * Show all Firm internal breakpoints.
1404 * Enables breakpoint nr.
1408 * Disables breakpoint nr.
1412 * Show the content of entity nr.
1416 * Show the content of entity name.
1420 * Show the content of type nr.
1424 * Show the content of type name.
1426 * @b setmask name msk
1428 * Sets the debug module name to mask msk.
1430 * @b setlvl name lvl
1432 * Sets the debug module name to level lvl.
1434 * @b setoutfile name file
1436 * Redirects debug output of module name to file.
1440 * Prints address and graph number of a method given by its name.
1444 * Prints address and graph number of a method given by its linker name.
1448 * List all commands.
1451 * The Firm debugger extension can be accessed using the function firm_debug().
1452 * The following example shows how to set a creation breakpoint in GDB when
1453 * node 2101 is created.
1455 * -# set FIRMDBG="init"
1456 * -# start gdb with your compiler
1457 * -# after gdb breaks, issue
1459 * call firm_debug("create 2101")
1461 * On the console the following text should be issued:
1463 * Firm BP 1: creation of Node 2101
1466 * @section gdb_macro GDB macro
1468 * Add the following to your .gdbinit file:
1471 # define firm "cmd" Firm debugger extension
1474 call firm_debug($arg0)
1478 * Then, all Firm debugger extension commands can be accessed in the gdb
1479 * console using the firm prefix, eg.:
1481 * firm "create 2101"