X-Git-Url: http://nsz.repo.hu/git/?a=blobdiff_plain;f=ir%2Fdebug%2Fdebugger.c;h=00cfe05b68c4f7846f74720cf8d7fd20d8e2aeea;hb=bc772df6ffc43cc8d73b0fb3d8d43a1c8ebf1c25;hp=4732879eade330503fafee58d8cf1888b235f942;hpb=dc56e312f47df43430ee1587c67aed80adfdace5;p=libfirm diff --git a/ir/debug/debugger.c b/ir/debug/debugger.c index 4732879ea..00cfe05b6 100644 --- a/ir/debug/debugger.c +++ b/ir/debug/debugger.c @@ -6,14 +6,14 @@ * Modified by: * Created: 2005 * CVS-ID: $Id$ - * Copyright: (c) 2001-2005 Universität Karlsruhe + * Copyright: (c) 2001-2006 Universität Karlsruhe * Licence: This file protected by GPL - GNU GENERAL PUBLIC LICENSE. */ #ifdef HAVE_CONFIG_H #include "config.h" #endif -#ifndef NDEBUG +#ifdef DEBUG_libfirm #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -39,28 +39,30 @@ #include "irgraph_t.h" #include "entity_t.h" #include "irprintf.h" +#include "typewalk.h" +#include "irdump.h" #include "debug.h" #ifdef _WIN32 -/** Break into the debugger. The Win32 way. */ -static void firm_debug_break(void) { +/* Break into the debugger. The Win32 way. */ +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. */ -static void firm_debug_break(void) { +/* Break into the debugger. The ia32/x86_64 way under GCC. */ +void firm_debug_break(void) { __asm__ __volatile__("int3"); } #else -/** Break into the debugger. Poor Unix way. */ -static void firm_debug_break(void) { +/* Break into the debugger. Poor Unix way. */ +void firm_debug_break(void) { raise(SIGINT); } #endif /* _WIN32 */ /** supported breakpoint kinds */ typedef enum { - BP_NR = 'n', /**< break on node number. */ + BP_NR = 'n', /**< break on node number. */ BP_IDENT = 'i' /**< break on ident. */ } bp_kind; @@ -92,16 +94,16 @@ typedef struct { long nr; /**< the node number */ } bp_nr_t; -/** calculate the hash value for a node breakpoint */ +/** Calculate the hash value for a node breakpoint. */ #define HASH_NR_BP(key) (((key).nr << 2) ^ (key).bp.reason) -/** A ident breakpoint. */ +/** An ident breakpoint. */ typedef struct { breakpoint bp; /**< the breakpoint data */ ident *id; /**< the ident */ } bp_ident_t; -/** calculate the hash value for an ident breakpoint */ +/** Calculate the hash value for an ident breakpoint. */ #define HASH_IDENT_BP(key) (HASH_PTR((key).id) ^ (key).bp.reason) /** The set containing the breakpoints on node numbers. */ @@ -143,13 +145,20 @@ static int is_active = 0; /** hook the hook h with function fkt. */ #define HOOK(h, fkt) \ - debugger_hooks[h].hook._##h = fkt; register_hook(h, &debugger_hooks[h]) +do { \ + debugger_hooks[h].hook._##h = fkt; \ + register_hook(h, &debugger_hooks[h]); \ +} while(0) /** unhook the hook h */ -#define UNHOOK(h) unregister_hook(h, &debugger_hooks[h]) +#define UNHOOK(h) \ +do { \ + unregister_hook(h, &debugger_hooks[h]); \ + debugger_hooks[h].hook._##h = NULL; \ +} while(0) /** returns non-zero if a entry hook h is used */ -#define IS_HOOKED(h) (debugger_hooks[h].next != NULL) +#define IS_HOOKED(h) (debugger_hooks[h].hook._##h != NULL) /* some macros needed to create the info string */ #define _DBG_VERSION(major, minor) #major "." #minor @@ -170,21 +179,21 @@ static const char *firm_debug_info_string = */ int firm_debug_active(void) { return is_active; -} +} /* firm_debug_active */ /** - * reset the debug text buffer + * Reset the debug text buffer. */ static void reset_dbg_buf(void) { firm_dbg_msg_buf[0] = '\0'; -} +} /* reset_dbg_buf */ /** - * Add text to the debug text buffer + * Add text to the debug text buffer. */ static void add_to_dbg_buf(const char *buf) { strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf)); -} +} /* add_to_dbg_buf */ /** * Return the content of the debug text buffer. @@ -192,8 +201,9 @@ static void add_to_dbg_buf(const char *buf) { * To be called from the debugger. */ 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 */ /** * debug output @@ -217,7 +227,7 @@ static void dbg_printf(const char *fmt, ...) add_to_dbg_buf(buf); else puts(buf); -} +} /* dbg_printf */ /** * A new node is created. @@ -238,7 +248,7 @@ static void dbg_new_node(void *ctx, ir_graph *irg, ir_node *node) dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node); firm_debug_break(); } -} +} /* dbg_new_node */ /** * A node is replaced. @@ -259,7 +269,7 @@ static void dbg_replace(void *ctx, ir_node *old, ir_node *nw) dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw); firm_debug_break(); } -} +} /* dbg_replace */ /** * A new node is lowered. @@ -279,7 +289,7 @@ static void dbg_lower(void *ctx, ir_node *node) dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node); firm_debug_break(); } -} +} /* dbg_lower */ /** * A graph will be deleted. @@ -316,7 +326,7 @@ static void dbg_free_graph(void *ctx, ir_graph *irg) firm_debug_break(); } } -} +} /* dbg_free_graph */ /** * An entity was created. @@ -350,7 +360,7 @@ static void dbg_new_entity(void *ctx, entity *ent) firm_debug_break(); } } -} +} /* dbg_new_entity */ /** * A type was created. @@ -358,7 +368,7 @@ static void dbg_new_entity(void *ctx, entity *ent) * @param ctx the hook context * @param tp the newly created type */ -static void dbg_new_type(void *ctx, type *tp) +static void dbg_new_type(void *ctx, ir_type *tp) { { bp_nr_t key, *elem; @@ -384,10 +394,10 @@ static void dbg_new_type(void *ctx, type *tp) firm_debug_break(); } } -} +} /* dbg_new_type */ /** - * return the reason string. + * Return the reason string. */ static const char *reason_str(bp_reasons_t reason) { @@ -401,10 +411,10 @@ static const char *reason_str(bp_reasons_t reason) default: assert(0); } return "unknown"; -} +} /* reason_str */ /** - * Compare two number breakpoints + * Compare two number breakpoints. */ static int cmp_nr_bp(const void *elt, const void *key, size_t size) { @@ -412,10 +422,10 @@ static int cmp_nr_bp(const void *elt, const void *key, size_t size) const bp_nr_t *e2 = key; return (e1->nr - e2->nr) | (e1->bp.reason - e2->bp.reason); -} +} /* cmp_nr_bp */ /** - * Compare two ident breakpoints + * Compare two ident breakpoints. */ static int cmp_ident_bp(const void *elt, const void *key, size_t size) { @@ -423,10 +433,10 @@ static int cmp_ident_bp(const void *elt, const void *key, size_t size) const bp_ident_t *e2 = key; return (e1->id != e2->id) | (e1->bp.reason - e2->bp.reason); -} +} /* cmp_ident_bp */ /** - * update the hooks + * Update the hooks. */ static void update_hooks(breakpoint *bp) { @@ -466,7 +476,7 @@ static void update_hooks(breakpoint *bp) } #undef CASE_ON #undef CASE_OFF -} +} /* update_hooks */ /** * Break if nr is reached. @@ -493,7 +503,7 @@ static void break_on_nr(long nr, bp_reasons_t reason) update_hooks(&elem->bp); } -} +} /* break_on_nr */ /** * Break if ident name is reached. @@ -519,7 +529,7 @@ static void break_on_ident(const char *name, bp_reasons_t reason) { update_hooks(&elem->bp); } -} +} /* break_on_ident */ /** * Sets/resets the active flag of breakpoint bp. @@ -540,7 +550,7 @@ static void bp_activate(unsigned bp, int active) } } dbg_printf("Error: Firm BP %u not exists.\n", bp); -} +} /* bp_activate */ /** @@ -558,11 +568,16 @@ static void show_commands(void) { ".bp show all breakpoints\n" ".enable nr enable breakpoint nr\n" ".disable nr disable breakpoint nr\n" - ".setmask name lvl sets the debug module name to level lvl\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. @@ -593,7 +608,7 @@ static void show_bp(void) { dbg_printf(p->active ? "+enabled" : "+disabled"); } dbg_printf(have_one ? "+\n" : "+ NONE\n"); -} +} /* show_bp */ /** * firm_dbg_register() expects that the name is stored persistent. @@ -603,7 +618,7 @@ 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)); -} +} /* dbg_register */ /** * Sets the debug mask of module name to lvl @@ -612,10 +627,12 @@ static void set_dbg_level(const char *name, unsigned lvl) { firm_dbg_module_t *module = dbg_register(name); - firm_dbg_set_mask(module, lvl); + if (firm_dbg_get_mask(module) != lvl) { + firm_dbg_set_mask(module, lvl); - dbg_printf("Setting debug mask of module %s to %u\n", name, lvl); -} + dbg_printf("Setting debug mask of module %s to %u\n", name, lvl); + } +} /* set_dbg_level */ /** * Redirects the debug output of module name to fname @@ -632,7 +649,212 @@ static void set_dbg_outfile(const char *name, const char *fname) firm_dbg_set_file(module, f); dbg_printf("Redirecting debug output of module %s to file %s\n", name, fname); -} +} /* set_dbg_outfile */ + +/** + * Show info about a firm thing. + */ +static void show_firm_object(void *firm_thing) { + FILE *f = stdout; + + if (firm_thing == NULL) { + fprintf(f, "\n"); + return; + } + switch (get_kind(firm_thing)) { + case k_BAD: + fprintf(f, "BAD: (%p)\n", firm_thing); + break; + case k_entity: + dump_entity_to_file(f, firm_thing, dump_verbosity_max); + break; + case k_type: + dump_type_to_file(f, firm_thing, dump_verbosity_max); + break; + case k_ir_graph: + case k_ir_node: + case k_ir_mode: + case k_ir_op: + case k_tarval: + case k_ir_loop: + case k_ir_compound_graph_path: + case k_ir_extblk: + case k_ir_prog: + fprintf(f, "NIY\n"); + break; + default: + fprintf(f, "Cannot identify thing at (%p).\n", firm_thing); + } +} /* show_firm_object */ + +/** + * Find a firm type by its number. + */ +static ir_type *find_type_nr(long nr) { + int i, n = get_irp_n_types(); + ir_type *tp; + + for (i = 0; i < n; ++i) { + tp = get_irp_type(i); + if (get_type_nr(tp) == nr) + return tp; + } + tp = get_glob_type(); + if (get_type_nr(tp) == nr) + return tp; + return NULL; +} /* find_type_nr */ + +/** + * Find a firm type by its 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) + return tp; + } + tp = get_glob_type(); + if (strcmp(get_type_name(tp), name) == 0) + return tp; + return NULL; +} /* find_type_name */ + +/** The environment for the entity search functions. */ +typedef struct find_env { + union { + long nr; /**< the number that is searched for */ + const char *name; /**< the name that is searched for */ + } u; + entity *res; /**< the result */ +} find_env_t; + +/** + * Type-walker: Find an entity with given number. + */ +static void check_ent_nr(type_or_ent *tore, void *ctx) { + entity *ent = (entity *)tore; + find_env_t *env = ctx; + + if (is_entity(ent)) + if (get_entity_nr(ent) == env->u.nr) { + env->res = ent; + } +} /* check_ent_nr */ + +/** + * Type-walker: Find an entity with given name. + */ +static void check_ent_name(type_or_ent *tore, void *ctx) { + entity *ent = (entity *)tore; + find_env_t *env = ctx; + + if (is_entity(ent)) + if (strcmp(get_entity_name(ent), env->u.name) == 0) { + env->res = ent; + } +} /* check_ent_name */ + +/** + * Find a firm entity by its number. + */ +static entity *find_entity_nr(long nr) { + find_env_t env; + + env.u.nr = nr; + env.res = NULL; + type_walk(check_ent_nr, NULL, &env); + return env.res; +} /* find_entity_nr */ + +/** + * Find a firm entity by its name. + */ +static entity *find_entity_name(const char *name) { + find_env_t env; + + env.u.name = name; + env.res = NULL; + type_walk(check_ent_name, NULL, &env); + return env.res; +} /* find_entity_name */ + +/** + * Search methods for a name. + */ +static void show_by_name(type_or_ent *tore, void *env) { + ident *id = (ident *)env; + + if (is_entity(tore)) { + entity *ent = (entity *)tore; + + if (is_method_entity(ent)) { + if (get_entity_ident(ent) == id) { + ir_type *owner = get_entity_owner(ent); + ir_graph *irg = get_entity_irg(ent); + + if (owner != get_glob_type()) { + printf("%s::%s", get_type_name(owner), get_id_str(id)); + } else { + printf("%s", get_id_str(id)); + } + if (irg) + printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg); + else + printf(" NULL\n"); + } + } + } +} /* show_by_name */ + +/** + * Search methods for a ldname. + */ +static void show_by_ldname(type_or_ent *tore, void *env) { + ident *id = (ident *)env; + + if (is_entity(tore)) { + entity *ent = (entity *)tore; + + if (is_method_entity(ent)) { + if (get_entity_ld_ident(ent) == id) { + ir_type *owner = get_entity_owner(ent); + ir_graph *irg = get_entity_irg(ent); + + if (owner != get_glob_type()) { + printf("%s::%s", get_type_name(owner), get_id_str(id)); + } else { + printf("%s", get_id_str(id)); + } + if (irg) + printf("[%ld] (%p)\n", get_irg_graph_nr(irg), irg); + else + printf(" NULL\n"); + } + } + } +} /* show_by_ldname */ + +/** + * prints the address and graph number of all irgs with given name + */ +static void irg_name(const char *name) { + ident *id = new_id_from_str(name); + + type_walk(show_by_name, NULL, (void *)id); +} /* irg_name */ + +/** + * prints the address and graph number of all irgs with given ld_name + */ +static void irg_ld_name(const char *name) { + ident *id = new_id_from_str(name); + + type_walk(show_by_ldname, NULL, (void *)id); +} /* irg_ld_name */ /** * High level function to use from debugger interface @@ -676,6 +898,18 @@ void firm_debug(const char *cmd) { else if (sscanf(cmd, ".newtype %s\n", name) == 1) { break_on_ident(name, BP_ON_NEW_TYPE); } + else if (sscanf(cmd, ".showtype %ld\n", &nr) == 1) { + show_firm_object(find_type_nr(nr)); + } + else if (sscanf(cmd, ".showtype %s\n", name) == 1) { + show_firm_object(find_type_name(name)); + } + else if (sscanf(cmd, ".showent %ld\n", &nr) == 1) { + show_firm_object(find_entity_nr(nr)); + } + else if (sscanf(cmd, ".showent %s\n", name) == 1) { + show_firm_object(find_entity_name(name)); + } else if (strcmp(cmd, ".init") == 0) break_on_init = 1; else if (strcmp(cmd, ".bp") == 0) @@ -686,12 +920,18 @@ void firm_debug(const char *cmd) { bp_activate(bp, 0); else if (sscanf(cmd, ".setmask %s %u\n", name, &lvl) == 2) set_dbg_level(name, lvl); + else if (sscanf(cmd, ".setlvl %s %u\n", name, &lvl) == 2) + set_dbg_level(name, (1 << lvl) - 1); else if (sscanf(cmd, ".setoutfile %s %s\n", name, fname) == 2) set_dbg_outfile(name, fname); + else if (sscanf(cmd, ".irgname %s\n", name) == 1) + irg_name(name); + else if (sscanf(cmd, ".irgldname %s\n", name) == 1) + irg_ld_name(name); else { show_commands(); } -} +} /* firm_debug */ /* creates the debugger tables */ void firm_init_debugger(void) @@ -699,7 +939,7 @@ void firm_init_debugger(void) char *env; bp_numbers = new_set(cmp_nr_bp, 8); - bp_idents = new_set(cmp_ident_bp, 8); + bp_idents = new_set(cmp_ident_bp, 8); env = getenv("FIRMDBG"); @@ -710,7 +950,7 @@ void firm_init_debugger(void) if (break_on_init) firm_debug_break(); -} +} /* firm_init_debugger */ #else @@ -729,6 +969,7 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * @section sec_cmd Supported commands * * The following commands are currently supported: + * * @b .init * * Break immediately after the debugger extension was initialized. @@ -737,7 +978,6 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * * $export FIRMDBG=".init" * - * * @b .create nr * * Break if a new IR-node with node number nr was created. @@ -787,7 +1027,27 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * * Disables breakpoint nr. * - * @b .setmask name lvl + * @b .showent nr + * + * Show the content of entity nr. + * + * @b .showent name + * + * Show the content of entity name. + * + * @b .showtype nr + * + * Show the content of type nr. + * + * @b .showtype name + * + * Show the content of type name. + * + * @b .setmask name msk + * + * Sets the debug module name to mask msk. + * + * @b .setlvl name lvl * * Sets the debug module name to level lvl. * @@ -795,6 +1055,14 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * * Redirects debug output of module name to file. * + * @b .irgname name + * + * Prints address and graph number of a method given by its name. + * + * @b .irgldname name + * + * Prints address and graph number of a method given by its linker name. + * * @b .help * * List all commands. @@ -808,7 +1076,7 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; * -# start gdb with your compiler * -# after gdb breaks, issue * - * p firm_debug(".create 2101") + * call firm_debug(".create 2101") * * On the console the following text should be issued: * @@ -823,21 +1091,14 @@ static int _firm_only_that_you_can_compile_with_NDEBUG_defined; # define firm "cmd" Firm debugger extension # define firm - p firm_debug($arg0) + call firm_debug($arg0) end * @endcode * - * Then, all Firm debugger extension commands can be access in the gdb + * Then, all Firm debugger extension commands can be accessed in the gdb * console using the firm prefix, eg.: * * firm ".create 2101" + * * firm ".help" */ - -#ifdef __GNUC__ -static void _firm_only_that_you_can_compile_with_NDEBUG_defined(void) __attribute__((unused)); -#endif - -static void _firm_only_that_you_can_compile_with_NDEBUG_defined(void) -{ -}