X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fdebug%2Fdebugger.c;h=0ac3ad6e1f133dd07bdea0d3fc4d9dd20c47b05a;hb=40f56bdee6900292d63f0d3edd8ab020e99750d5;hp=ac75ab4b542635a4c0c63c0f735bde9195f62609;hpb=50b3b4c7c433292a0d1416886796a3392da63395;p=libfirm diff --git a/ir/debug/debugger.c b/ir/debug/debugger.c index ac75ab4b5..0ac3ad6e1 100644 --- a/ir/debug/debugger.c +++ b/ir/debug/debugger.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 1995-2007 University of Karlsruhe. All right reserved. + * Copyright (C) 1995-2008 University of Karlsruhe. All right reserved. * * This file is part of libFirm. * @@ -24,31 +24,20 @@ * @date 2005 * @version $Id$ */ -#ifdef HAVE_CONFIG_H #include "config.h" -#endif - -#include "firm_config.h" #ifdef DEBUG_libfirm #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include - -#define strncasecmp strnicmp #endif -#ifdef HAVE_STDLIB_H #include -#endif - #include #include - -#ifdef HAVE_STRING_H #include -#endif + #ifdef HAVE_STRINGS_H #include #endif @@ -62,21 +51,26 @@ #include "entity_t.h" #include "irprintf.h" #include "irdump.h" +#include "iredges_t.h" #include "debug.h" +#include "error.h" #ifdef _WIN32 /* Break into the debugger. The Win32 way. */ -void firm_debug_break(void) { +void firm_debug_break(void) +{ DebugBreak(); } #elif defined(__GNUC__) && (defined(__i386__) || defined(__x86_64)) /* Break into the debugger. The ia32/x86_64 way under GCC. */ -void firm_debug_break(void) { +void firm_debug_break(void) +{ __asm__ __volatile__("int3"); } #else /* Break into the debugger. Poor Unix way. */ -void firm_debug_break(void) { +void firm_debug_break(void) +{ raise(SIGINT); } #endif /* _WIN32 */ @@ -169,14 +163,14 @@ static int is_active = 0; do { \ debugger_hooks[h].hook._##h = fkt; \ register_hook(h, &debugger_hooks[h]); \ -} while(0) +} while (0) /** unhook the hook h */ #define UNHOOK(h) \ do { \ unregister_hook(h, &debugger_hooks[h]); \ debugger_hooks[h].hook._##h = NULL; \ -} while(0) +} while (0) /** returns non-zero if a entry hook h is used */ #define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL) @@ -197,21 +191,24 @@ static const char firm_debug_info_string[] = /** * Returns non-zero, if the debug extension is active */ -int firm_debug_active(void) { +int firm_debug_active(void) +{ return is_active; } /* firm_debug_active */ /** * Reset the debug text buffer. */ -static void reset_dbg_buf(void) { +static void reset_dbg_buf(void) +{ firm_dbg_msg_buf[0] = '\0'; } /* reset_dbg_buf */ /** * Add text to the debug text buffer. */ -static void add_to_dbg_buf(const char *buf) { +static void add_to_dbg_buf(const char *buf) +{ strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf)); } /* add_to_dbg_buf */ @@ -220,7 +217,8 @@ static void add_to_dbg_buf(const char *buf) { * * To be called from the debugger. */ -const char *firm_debug_text(void) { +const char *firm_debug_text(void) +{ firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0'; return firm_dbg_msg_buf; } /* firm_debug_text */ @@ -409,18 +407,6 @@ static void dbg_new_type(void *ctx, ir_type *tp) firm_debug_break(); } } - { - bp_ident_t key, *elem; - - key.id = get_type_ident(tp); - key.bp.reason = BP_ON_NEW_TYPE; - - elem = set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key)); - if (elem && elem->bp.active) { - dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp); - firm_debug_break(); - } - } } /* dbg_new_type */ /** @@ -435,9 +421,9 @@ static const char *reason_str(bp_reasons_t reason) case BP_ON_REMIRG: return "removing IRG"; case BP_ON_NEW_ENT: return "entity creation"; case BP_ON_NEW_TYPE: return "type creation"; - default: assert(0); + case BP_MAX_REASON: break; } - return "unknown"; + panic("unsupported reason"); } /* reason_str */ /** @@ -537,7 +523,8 @@ static void break_on_nr(long nr, bp_reasons_t reason) /** * Break if ident name is reached. */ -static void break_on_ident(const char *name, bp_reasons_t reason) { +static void break_on_ident(const char *name, bp_reasons_t reason) +{ bp_ident_t key, *elem; key.bp.kind = BP_IDENT; @@ -585,33 +572,35 @@ static void bp_activate(unsigned bp, int active) /** * Show a list of supported commands */ -static void show_commands(void) { +static void show_commands(void) +{ dbg_printf("Internal Firm debugger extension $Revision$ commands:\n" - ".init break after initialization\n" - ".create nr break if node nr was created\n" - ".replace nr break if node nr is replaced by another node\n" - ".lower nr break before node nr is lowered\n" - ".remirg nr|name break if the irg of nr or entity name is deleted\n" - ".newent nr|name break if the entity nr or name was created\n" - ".newtype nr|name break if the type nr or name was created\n" - ".bp show all breakpoints\n" - ".enable nr enable breakpoint nr\n" - ".disable nr disable breakpoint nr\n" - ".showtype nr|name show content of the type nr or name\n" - ".showent nr|name show content of the entity nr or name\n" - ".setmask name msk sets the debug module name to mask msk\n" - ".setlvl name lvl sets the debug module name to level lvl\n" - ".setoutfile name file redirects debug output of module name to file\n" - ".irgname name prints address and graph number of a method given by its name\n" - ".irgldname ldname prints address and graph number of a method given by its ldname\n" - ".help list all commands\n" + "init break after initialization\n" + "create nr break if node nr was created\n" + "replace nr break if node nr is replaced by another node\n" + "lower nr break before node nr is lowered\n" + "remirg nr|name break if the irg of nr or entity name is deleted\n" + "newent nr|name break if the entity nr or name was created\n" + "newtype nr|name break if the type nr or name was created\n" + "bp show all breakpoints\n" + "enable nr enable breakpoint nr\n" + "disable nr disable breakpoint nr\n" + "showtype nr|name show content of the type nr or name\n" + "showent nr|name show content of the entity nr or name\n" + "setmask name msk sets the debug module name to mask msk\n" + "setlvl name lvl sets the debug module name to level lvl\n" + "setoutfile name file redirects debug output of module name to file\n" + "irgname name prints address and graph number of a method given by its name\n" + "irgldname ldname prints address and graph number of a method given by its ldname\n" + "help list all commands\n" ); } /* show_commands */ /** * Shows all Firm breakpoints. */ -static void show_bp(void) { +static void show_bp(void) +{ breakpoint *p; bp_nr_t *node_p; bp_ident_t *ident_p; @@ -643,7 +632,8 @@ static void show_bp(void) { * firm_dbg_register() expects that the name is stored persistent. * So we need this little helper function */ -static firm_dbg_module_t *dbg_register(const char *name) { +static firm_dbg_module_t *dbg_register(const char *name) +{ ident *id = new_id_from_str(name); return firm_dbg_register(get_id_str(id)); @@ -683,7 +673,8 @@ static void set_dbg_outfile(const char *name, const char *fname) /** * Show info about a firm thing. */ -static void show_firm_object(void *firm_thing) { +static void show_firm_object(void *firm_thing) +{ FILE *f = stdout; if (firm_thing == NULL) { @@ -719,7 +710,8 @@ static void show_firm_object(void *firm_thing) { /** * Find a firm type by its number. */ -static ir_type *find_type_nr(long nr) { +static ir_type *find_type_nr(long nr) +{ int i, n = get_irp_n_types(); ir_type *tp; @@ -737,17 +729,21 @@ static ir_type *find_type_nr(long nr) { /** * Find a firm type by its name. */ -static ir_type *find_type_name(const char *name) { +static ir_type *find_type_name(const char *name) +{ int i, n = get_irp_n_types(); ir_type *tp; for (i = 0; i < n; ++i) { tp = get_irp_type(i); - if (strcmp(get_type_name(tp), name) == 0) + if (!is_compound_type(tp)) + continue; + + if (strcmp(get_compound_name(tp), name) == 0) return tp; } tp = get_glob_type(); - if (strcmp(get_type_name(tp), name) == 0) + if (strcmp(get_compound_name(tp), name) == 0) return tp; return NULL; } /* find_type_name */ @@ -764,33 +760,35 @@ typedef struct find_env { /** * Type-walker: Find an entity with given number. */ -static void check_ent_nr(type_or_ent *tore, void *ctx) { - ir_entity *ent = (ir_entity *)tore; +static void check_ent_nr(type_or_ent tore, void *ctx) +{ find_env_t *env = ctx; - if (is_entity(ent)) - if (get_entity_nr(ent) == env->u.nr) { - env->res = ent; + if (is_entity(tore.ent)) { + if (get_entity_nr(tore.ent) == env->u.nr) { + env->res = tore.ent; } + } } /* check_ent_nr */ /** * Type-walker: Find an entity with given name. */ -static void check_ent_name(type_or_ent *tore, void *ctx) { - ir_entity *ent = (ir_entity *)tore; +static void check_ent_name(type_or_ent tore, void *ctx) +{ find_env_t *env = ctx; - if (is_entity(ent)) - if (strcmp(get_entity_name(ent), env->u.name) == 0) { - env->res = ent; + if (is_entity(tore.ent)) + if (strcmp(get_entity_name(tore.ent), env->u.name) == 0) { + env->res = tore.ent; } } /* check_ent_name */ /** * Find a firm entity by its number. */ -static ir_entity *find_entity_nr(long nr) { +static ir_entity *find_entity_nr(long nr) +{ find_env_t env; env.u.nr = nr; @@ -802,7 +800,8 @@ static ir_entity *find_entity_nr(long nr) { /** * Find a firm entity by its name. */ -static ir_entity *find_entity_name(const char *name) { +static ir_entity *find_entity_name(const char *name) +{ find_env_t env; env.u.name = name; @@ -814,11 +813,12 @@ static ir_entity *find_entity_name(const char *name) { /** * Search methods for a name. */ -static void show_by_name(type_or_ent *tore, void *env) { +static void show_by_name(type_or_ent tore, void *env) +{ ident *id = (ident *)env; - if (is_entity(tore)) { - ir_entity *ent = (ir_entity *)tore; + if (is_entity(tore.ent)) { + ir_entity *ent = tore.ent; if (is_method_entity(ent)) { if (get_entity_ident(ent) == id) { @@ -826,7 +826,7 @@ static void show_by_name(type_or_ent *tore, void *env) { ir_graph *irg = get_entity_irg(ent); if (owner != get_glob_type()) { - printf("%s::%s", get_type_name(owner), get_id_str(id)); + printf("%s::%s", get_compound_name(owner), get_id_str(id)); } else { printf("%s", get_id_str(id)); } @@ -842,11 +842,12 @@ static void show_by_name(type_or_ent *tore, void *env) { /** * Search methods for a ldname. */ -static void show_by_ldname(type_or_ent *tore, void *env) { +static void show_by_ldname(type_or_ent tore, void *env) +{ ident *id = (ident *)env; - if (is_entity(tore)) { - ir_entity *ent = (ir_entity *)tore; + if (is_entity(tore.ent)) { + ir_entity *ent = tore.ent; if (is_method_entity(ent)) { if (get_entity_ld_ident(ent) == id) { @@ -854,7 +855,7 @@ static void show_by_ldname(type_or_ent *tore, void *env) { ir_graph *irg = get_entity_irg(ent); if (owner != get_glob_type()) { - printf("%s::%s", get_type_name(owner), get_id_str(id)); + printf("%s::%s", get_compound_name(owner), get_id_str(id)); } else { printf("%s", get_id_str(id)); } @@ -870,7 +871,8 @@ static void show_by_ldname(type_or_ent *tore, void *env) { /** * prints the address and graph number of all irgs with given name */ -static void irg_name(const char *name) { +static void irg_name(const char *name) +{ ident *id = new_id_from_str(name); type_walk(show_by_name, NULL, (void *)id); @@ -879,7 +881,8 @@ static void irg_name(const char *name) { /** * prints the address and graph number of all irgs with given ld_name */ -static void irg_ld_name(const char *name) { +static void irg_ld_name(const char *name) +{ ident *id = new_id_from_str(name); type_walk(show_by_ldname, NULL, (void *)id); @@ -949,7 +952,8 @@ static struct lexer { /** * Initialize the lexer. */ -static void init_lexer(const char *input) { +static void init_lexer(const char *input) +{ lexer.has_token = 0; lexer.curr_pos = input; lexer.end_pos = input + strlen(input); @@ -959,7 +963,8 @@ static void init_lexer(const char *input) { /** * Get the next char from the input. */ -static char next_char(void) { +static char next_char(void) +{ if (lexer.curr_pos >= lexer.end_pos) return '\0'; return *lexer.curr_pos++; @@ -973,7 +978,8 @@ static char next_char(void) { /** * The lexer. */ -static unsigned get_token(void) { +static unsigned get_token(void) +{ char c; int i; @@ -983,32 +989,29 @@ static unsigned get_token(void) { } while (c != '\0' && isspace(c)); lexer.tok_start = lexer.curr_pos - 1; - if (c == '.') { + if (c == '.' || isalpha(c)) { /* command begins here */ - int len = 0; + int len = 0; + const char* tok_start; do { c = next_char(); ++len; - } while (isalpha(c)); + } while (isgraph(c)); unput(); - --len; + tok_start = lexer.tok_start; + if (*tok_start == '.') { + ++tok_start; + --len; + } for (i = sizeof(reserved)/sizeof(reserved[0]) - 1; i >= 0; --i) { - if (strncasecmp(lexer.tok_start + 1, reserved[i], len) == 0 && reserved[i][len] == '\0') - break; + if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0') + return 256 + i; } - if (i >= 0) - return 256 + i; - return tok_error; - } else if (isalpha(c)) { - /* identifier */ - lexer.s = lexer.curr_pos - 1; - do { - c = next_char(); - } while (isgraph(c)); - unput(); + /* identifier */ + lexer.s = lexer.tok_start; lexer.len = lexer.curr_pos - lexer.s; return tok_identifier; } else if (isdigit(c) || c == '-') { @@ -1058,11 +1061,10 @@ static unsigned get_token(void) { /** * High level function to use from debugger interface * - * Supported commands: - * .create nr break if node nr was created - * .help list all commands + * See show_commands() for supported commands. */ -void firm_debug(const char *cmd) { +void firm_debug(const char *cmd) +{ char name[1024], fname[1024]; int len; @@ -1297,7 +1299,8 @@ void firm_init_debugger(void) /** * A gdb helper function to print firm objects. */ -const char *gdb_node_helper(void *firm_object) { +const char *gdb_node_helper(void *firm_object) +{ static char buf[1024]; ir_snprintf(buf, sizeof(buf), "%+F", firm_object); return buf; @@ -1306,16 +1309,36 @@ const char *gdb_node_helper(void *firm_object) { /** * A gdb helper function to print tarvals. */ -const char *gdb_tarval_helper(void *tv_object) { +const char *gdb_tarval_helper(void *tv_object) +{ static char buf[1024]; ir_snprintf(buf, sizeof(buf), "%+T", tv_object); return buf; } +const char *gdb_out_edge_helper(const ir_node *node) +{ + static char buf[4*1024]; + char *b = buf; + size_t l; + size_t len = sizeof(buf); + const ir_edge_t *edge; + foreach_out_edge(node, edge) { + ir_node *n = get_edge_src_irn(edge); + + ir_snprintf(b, len, "%+F ", n); + l = strlen(b); + len -= l; + b += l; + } + + return buf; +} + #else /* some picky compiler do not allow empty files */ -static int _firm_only_that_you_can_compile_with_NDEBUG_defined; +static int __attribute__((unused)) _firm_only_that_you_can_compile_with_NDEBUG_defined; #endif /* NDEBUG */ @@ -1329,9 +1352,11 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * * @section sec_cmd Supported commands * + * Historically all debugger commands start with a dot. This isn't needed in newer + * versions, but still supported, ie the commands ".init" and "init" are equal. * The following commands are currently supported: * - * @b .init + * @b init * * Break immediately after the debugger extension was initialized. * Typically this command is used in the environment to stop the execution @@ -1339,92 +1364,92 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * * $export FIRMDBG=".init" * - * @b .create nr + * @b create nr * * Break if a new IR-node with node number nr was created. * Typically used to find the place where wrong nodes are created. * - * @b .replace nr + * @b replace nr * * Break before IR-node with node number nr is replaced by another node. * - * @b .lower nr + * @b lower nr * * Break before IR-node with node number nr is lowered. * - * @b .remirg nr + * @b remirg nr * * Break if the irg with graph number nr is deleted. * - * @b .remirg name + * @b remirg name * * Break if the irg of entity name is deleted. * - * @b .newent nr + * @b newent nr * * Break if the entity with number nr was created. * - * @b .newent name + * @b newent name * * Break if the entity name was created. * - * @b .newtype nr + * @b newtype nr * * Break if the type with number nr was created. * - * @b .newtype name + * @b newtype name * * Break if the type name was created. * - * @b .bp + * @b bp * * Show all Firm internal breakpoints. * - * @b .enable nr + * @b enable nr * * Enables breakpoint nr. * - * @b .disable nr + * @b disable nr * * Disables breakpoint nr. * - * @b .showent nr + * @b showent nr * * Show the content of entity nr. * - * @b .showent name + * @b showent name * * Show the content of entity name. * - * @b .showtype nr + * @b showtype nr * * Show the content of type nr. * - * @b .showtype name + * @b showtype name * * Show the content of type name. * - * @b .setmask name msk + * @b setmask name msk * * Sets the debug module name to mask msk. * - * @b .setlvl name lvl + * @b setlvl name lvl * * Sets the debug module name to level lvl. * - * @b .setoutfile name file + * @b setoutfile name file * * Redirects debug output of module name to file. * - * @b .irgname name + * @b irgname name * * Prints address and graph number of a method given by its name. * - * @b .irgldname name + * @b irgldname name * * Prints address and graph number of a method given by its linker name. * - * @b .help + * @b help * * List all commands. * @@ -1433,11 +1458,11 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * The following example shows how to set a creation breakpoint in GDB when * node 2101 is created. * - * -# set FIRMDBG=".init" + * -# set FIRMDBG="init" * -# start gdb with your compiler * -# after gdb breaks, issue * - * call firm_debug(".create 2101") + * call firm_debug("create 2101") * * On the console the following text should be issued: * @@ -1459,7 +1484,7 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * Then, all Firm debugger extension commands can be accessed in the gdb * console using the firm prefix, eg.: * - * firm ".create 2101" + * firm "create 2101" * - * firm ".help" + * firm "help" */