/*
- * Copyright (C) 1995-2010 University of Karlsruhe. All right reserved.
- *
* This file is part of libFirm.
- *
- * This file may be distributed and/or modified under the terms of the
- * GNU General Public License version 2 as published by the Free Software
- * Foundation and appearing in the file LICENSE.GPL included in the
- * packaging of this file.
- *
- * Licensees holding valid libFirm Professional Edition licenses may use
- * this file in accordance with the libFirm Commercial License.
- * Agreement provided with the Software.
- *
- * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
- * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE.
+ * Copyright (C) 2012 University of Karlsruhe.
*/
/**
#include <signal.h>
#include <string.h>
#include <strings.h>
+#include <time.h>
#include <ctype.h>
* Reasons for node number breakpoints.
*/
typedef enum bp_reasons_t {
- BP_ON_NEW_NODE, /**< break if node with number is created */
+ BP_ON_NEW_THING, /**< break if node, entity or type with number is created */
BP_ON_REPLACE, /**< break if node with number is replaced */
BP_ON_LOWER, /**< break if node with number is lowered */
BP_ON_REMIRG, /**< break if an IRG is removed */
BP_ON_NEW_ENT, /**< break if a new entity is created */
- BP_ON_NEW_TYPE, /**< break if a new type is created */
BP_MAX_REASON
} bp_reasons_t;
firm_dbg_msg_buf[0] = '\0';
}
-static void add_to_dbg_buf(const char *buf)
-{
- strncat(firm_dbg_msg_buf, buf, sizeof(firm_dbg_msg_buf));
-}
-
const char *firm_debug_text(void)
{
firm_dbg_msg_buf[sizeof(firm_dbg_msg_buf) - 1] = '\0';
*/
static void dbg_printf(const char *fmt, ...)
{
- char buf[1024];
-
- va_list args;
- va_start(args, fmt);
-
if (fmt[0] != '+')
reset_dbg_buf();
else
++fmt;
- ir_vsnprintf(buf, sizeof(buf), fmt, args);
+ va_list args;
+ va_start(args, fmt);
+ if (redir_output) {
+ size_t const cur = strlen(firm_dbg_msg_buf);
+ ir_vsnprintf(firm_dbg_msg_buf + cur, sizeof(firm_dbg_msg_buf) - cur, fmt, args);
+ } else {
+ ir_vprintf(fmt, args);
+ }
va_end(args);
-
- if (redir_output)
- add_to_dbg_buf(buf);
- else
- puts(buf);
}
/**
(void) irg;
key.nr = get_irn_node_nr(node);
- key.bp.reason = BP_ON_NEW_NODE;
+ key.bp.reason = BP_ON_NEW_THING;
- elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F created\n", elem->bp.bpnr, node);
firm_debug_break();
key.nr = get_irn_node_nr(old);
key.bp.reason = BP_ON_REPLACE;
- elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F will be replaced by %+F\n", elem->bp.bpnr, old, nw);
firm_debug_break();
key.nr = get_irn_node_nr(node);
key.bp.reason = BP_ON_LOWER;
- elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F will be lowered\n", elem->bp.bpnr, node);
firm_debug_break();
key.nr = get_irg_graph_nr(irg);
key.bp.reason = BP_ON_REMIRG;
- elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
ir_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, irg);
firm_debug_break();
key.id = get_entity_ident(ent);
key.bp.reason = BP_ON_REMIRG;
- elem = (bp_ident_t*)set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
+ elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F will be deleted\n", elem->bp.bpnr, ent);
firm_debug_break();
key.id = get_entity_ident(ent);
key.bp.reason = BP_ON_NEW_ENT;
- elem = (bp_ident_t*)set_find(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
+ elem = set_find(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
if (elem && elem->bp.active) {
ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
firm_debug_break();
bp_nr_t key, *elem;
key.nr = get_entity_nr(ent);
- key.bp.reason = BP_ON_NEW_ENT;
+ key.bp.reason = BP_ON_NEW_THING;
- elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
dbg_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, ent);
firm_debug_break();
bp_nr_t key, *elem;
key.nr = get_type_nr(tp);
- key.bp.reason = BP_ON_NEW_TYPE;
+ key.bp.reason = BP_ON_NEW_THING;
- elem = (bp_nr_t*)set_find(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_find(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem && elem->bp.active) {
ir_printf("Firm BP %u reached, %+F was created\n", elem->bp.bpnr, tp);
firm_debug_break();
static const char *reason_str(bp_reasons_t reason)
{
switch (reason) {
- case BP_ON_NEW_NODE: return "node creation";
- case BP_ON_REPLACE: return "node replace";
- case BP_ON_LOWER: return "node lowering";
- case BP_ON_REMIRG: return "removing IRG";
- case BP_ON_NEW_ENT: return "entity creation";
- case BP_ON_NEW_TYPE: return "type creation";
- case BP_MAX_REASON: break;
+ case BP_ON_NEW_THING: return "node, entity or type creation";
+ case BP_ON_REPLACE: return "node replace";
+ case BP_ON_LOWER: return "node lowering";
+ case BP_ON_REMIRG: return "removing IRG";
+ case BP_ON_NEW_ENT: return "entity creation";
+ case BP_MAX_REASON: break;
}
panic("unsupported reason");
}
*/
static void update_hooks(breakpoint *bp)
{
-#define CASE_ON(a, b) case a: if (! IS_HOOKED(hook_##b)) HOOK(hook_##b, dbg_##b); break
-#define CASE_OFF(a, b) case a: if (IS_HOOKED(hook_##b)) UNHOOK(hook_##b); break
+#define CASE_ON(a, hook, handler) case a: if (! IS_HOOKED(hook)) HOOK(hook, handler); break
+#define CASE_OFF(a, hook) case a: if (IS_HOOKED(hook)) UNHOOK(hook); break
if (bp->active)
++num_active_bp[bp->reason];
if (num_active_bp[bp->reason] > 0) {
/* register the hooks on demand */
switch (bp->reason) {
- CASE_ON(BP_ON_NEW_NODE, new_node);
- CASE_ON(BP_ON_REPLACE, replace);
- CASE_ON(BP_ON_LOWER, lower);
- CASE_ON(BP_ON_REMIRG, free_graph);
- CASE_ON(BP_ON_NEW_ENT, new_entity);
- CASE_ON(BP_ON_NEW_TYPE, new_type);
+ CASE_ON(BP_ON_REPLACE, hook_replace, dbg_replace);
+ CASE_ON(BP_ON_LOWER, hook_lower, dbg_lower);
+ CASE_ON(BP_ON_REMIRG, hook_free_graph, dbg_free_graph);
+ CASE_ON(BP_ON_NEW_ENT, hook_new_entity, dbg_new_entity);
+ case BP_ON_NEW_THING:
+ if (!IS_HOOKED(hook_new_node))
+ HOOK(hook_new_node, dbg_new_node);
+ if (!IS_HOOKED(hook_new_type))
+ HOOK(hook_new_type, dbg_new_type);
+ if (!IS_HOOKED(hook_new_entity))
+ HOOK(hook_new_entity, dbg_new_entity);
+ break;
default:
break;
}
else {
/* unregister the hook on demand */
switch (bp->reason) {
- CASE_OFF(BP_ON_NEW_NODE, new_node);
- CASE_OFF(BP_ON_REPLACE, replace);
- CASE_OFF(BP_ON_LOWER, lower);
- CASE_OFF(BP_ON_REMIRG, free_graph);
- CASE_OFF(BP_ON_NEW_ENT, new_entity);
- CASE_OFF(BP_ON_NEW_TYPE, new_type);
+ CASE_OFF(BP_ON_REPLACE, hook_replace);
+ CASE_OFF(BP_ON_LOWER, hook_lower);
+ CASE_OFF(BP_ON_REMIRG, hook_free_graph);
+ CASE_OFF(BP_ON_NEW_ENT, hook_new_entity);
+ case BP_ON_NEW_THING:
+ if (IS_HOOKED(hook_new_node))
+ UNHOOK(hook_new_node);
+ if (IS_HOOKED(hook_new_type))
+ UNHOOK(hook_new_type);
+ if (IS_HOOKED(hook_new_entity))
+ UNHOOK(hook_new_entity);
+ break;
default:
break;
}
key.bp.reason = reason;
key.nr = nr;
- elem = (bp_nr_t*)set_insert(bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
+ elem = set_insert(bp_nr_t, bp_numbers, &key, sizeof(key), HASH_NR_BP(key));
if (elem->bp.bpnr == 0) {
/* new break point */
key.bp.reason = reason;
key.id = new_id_from_str(name);
- elem = (bp_ident_t*)set_insert(bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
+ elem = set_insert(bp_ident_t, bp_idents, &key, sizeof(key), HASH_IDENT_BP(key));
if (elem->bp.bpnr == 0) {
/* new break point */
*/
static void show_commands(void)
{
- dbg_printf("Internal Firm debugger extension $Revision$ commands:\n"
+ dbg_printf("Internal Firm debugger extension 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"
"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"
+ "initialnodenr n|rand set initial node number to n or random number\n"
"help list all commands\n"
);
}
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;
}
enum tokens {
- tok_create = 256,
- tok_replace,
+ first_token = 256,
+ tok_bp = first_token,
+ tok_create,
+ tok_disable,
+ tok_dumpfilter,
+ tok_enable,
+ tok_help,
+ tok_init,
+ tok_irgldname,
+ tok_irgname,
tok_lower,
- tok_remirg,
tok_newent,
- tok_newtype,
- tok_showtype,
- tok_showent,
- tok_init,
- tok_bp,
- tok_enable,
- tok_disable,
- tok_setmask,
+ tok_remirg,
+ tok_replace,
tok_setlvl,
+ tok_setmask,
tok_setoutfile,
- tok_irgname,
- tok_irgldname,
- tok_help,
+ tok_showent,
+ tok_showtype,
+ tok_initialnodenr,
tok_identifier,
tok_number,
tok_eof,
};
static const char *reserved[] = {
+ "bp",
"create",
- "replace",
+ "disable",
+ "dumpfilter",
+ "enable",
+ "help",
+ "init",
+ "irgldname",
+ "irgname",
"lower",
- "remirg",
"newent",
- "newtype",
- "showtype",
- "showent",
- "init",
- "bp",
- "enable",
- "disable",
- "setmask",
+ "remirg",
+ "replace",
"setlvl",
+ "setmask",
"setoutfile",
- "irgname",
- "irgldname",
- "help"
+ "showent",
+ "showtype",
+ "initialnodenr",
};
/**
}
for (i = ARRAY_SIZE(reserved); i-- != 0;) {
if (strncasecmp(tok_start, reserved[i], len) == 0 && reserved[i][len] == '\0')
- return 256 + i;
+ return first_token + i;
}
/* identifier */
token = get_token();
if (token != tok_number)
goto error;
- break_on_nr(lexer.number, BP_ON_NEW_NODE);
+ break_on_nr(lexer.number, BP_ON_NEW_THING);
break;
case tok_replace:
token = get_token();
if (token == tok_number)
- break_on_nr(lexer.number, BP_ON_NEW_ENT);
+ break_on_nr(lexer.number, BP_ON_NEW_THING);
else if (token == tok_identifier) {
len = MIN(lexer.len, 1023);
strncpy(name, lexer.s, len);
goto error;
break;
- case tok_newtype:
- token = get_token();
-
- if (token == tok_number)
- break_on_nr(lexer.number, BP_ON_NEW_TYPE);
- else if (token == tok_identifier) {
- len = MIN(lexer.len, 1023);
- strncpy(name, lexer.s, len);
- name[len] = '\0';
- break_on_ident(name, BP_ON_NEW_TYPE);
- } else
- goto error;
- break;
-
case tok_showtype:
token = get_token();
irg_name(name);
break;
+ case tok_initialnodenr:
+ token = get_token();
+ if (token == tok_number) {
+ dbg_printf("Setting initial node number to %u\n", lexer.number);
+ irp->max_node_nr = lexer.number;
+ } else if (token == tok_identifier && !strcmp(lexer.s, "rand")) {
+ dbg_printf("Randomizing initial node number\n");
+ srand(time(0));
+ irp->max_node_nr += rand() % 6666;
+ } else
+ goto error;
+ break;
+
case tok_irgldname:
token = get_token();
if (token != tok_identifier)
irg_ld_name(name);
break;
+ case tok_dumpfilter:
+ token = get_token();
+ if (token != tok_identifier)
+ goto error;
+ len = MIN(lexer.len, 1023);
+ strncpy(name, lexer.s, len);
+ name[len] = '\0';
+ ir_set_dump_filter(name);
+ break;
+
case tok_help:
show_commands();
break;
firm_debug_break();
}
+void firm_finish_debugger(void)
+{
+ del_set(bp_numbers);
+ del_set(bp_idents);
+}
+
/**
* A gdb helper function to print firm objects.
*/
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);