2012-05-14 Stan Shebs <stan@codesourcery.com>
Add dynamic printf. * breakpoint.h (enum bptype): New type bp_dprintf. (struct breakpoint): New field extra_string. (struct breakpoint_ops): Add arg to create_breakpoints_sal. (create_breakpoint): Add extra_string arg. * breakpoint.c (dprintf_breakpoint_ops): New. (is_breakpoint): Add bp_dprintf. (bpstat_what): Add dprintf case. (bptype_string): Ditto. (print_one_breakpoint_location): Ditto. (init_bp_location): Ditto. (bkpt_print_mention): Ditto. (dprintf_style_enums): New array. (dprintf_style): New global. (dprintf_function): New global. (dprintf_channel): New global. (update_dprintf_command_list): New function. (update_dprintf_commands): New function. (init_breakpoint_sal): Add extra_string argument, handle it. (create_breakpoint_sal): Add extra_string argument. (create_breakpoints_sal): Add extra_string argument, update callers. (find_condition_and_thread): Add extra argument. (create_breakpoint): Add extra_string argument, record it. (dprintf_command): New function. (break_command_1): Add arg to create_breakpoint call. (handle_gnu_v3_exceptions): Ditto. (trace_command): Ditto. (ftrace_command): Ditto. (strace_command): Ditto. (bkpt_print_mention): Add dprintf case. (create_breakpoint_sal_default): Add extra_string argument. (_initialize_breakpoint): Add new commands. * mi/mi-cmd-break.c (mi_cmd_break_insert): Add arg to call. * python/py-breakpoint.c (bppy_init): Ditto. * python/py-finishbreakpoint.c (bpfinishpy_init): Ditto. * gdb.texinfo (Dynamic Printf): New subsection. * gdb.base/dprintf.c: New file. * gdb.base/dprintf.exp: New file.
This commit is contained in:
parent
27d799802a
commit
e7e0cddfb0
12 changed files with 572 additions and 24 deletions
|
@ -1,3 +1,41 @@
|
||||||
|
2012-05-14 Stan Shebs <stan@codesourcery.com>
|
||||||
|
|
||||||
|
Add dynamic printf.
|
||||||
|
* breakpoint.h (enum bptype): New type bp_dprintf.
|
||||||
|
(struct breakpoint): New field extra_string.
|
||||||
|
(struct breakpoint_ops): Add arg to create_breakpoints_sal.
|
||||||
|
(create_breakpoint): Add extra_string arg.
|
||||||
|
* breakpoint.c (dprintf_breakpoint_ops): New.
|
||||||
|
(is_breakpoint): Add bp_dprintf.
|
||||||
|
(bpstat_what): Add dprintf case.
|
||||||
|
(bptype_string): Ditto.
|
||||||
|
(print_one_breakpoint_location): Ditto.
|
||||||
|
(init_bp_location): Ditto.
|
||||||
|
(bkpt_print_mention): Ditto.
|
||||||
|
(dprintf_style_enums): New array.
|
||||||
|
(dprintf_style): New global.
|
||||||
|
(dprintf_function): New global.
|
||||||
|
(dprintf_channel): New global.
|
||||||
|
(update_dprintf_command_list): New function.
|
||||||
|
(update_dprintf_commands): New function.
|
||||||
|
(init_breakpoint_sal): Add extra_string argument, handle it.
|
||||||
|
(create_breakpoint_sal): Add extra_string argument.
|
||||||
|
(create_breakpoints_sal): Add extra_string argument, update callers.
|
||||||
|
(find_condition_and_thread): Add extra argument.
|
||||||
|
(create_breakpoint): Add extra_string argument, record it.
|
||||||
|
(dprintf_command): New function.
|
||||||
|
(break_command_1): Add arg to create_breakpoint call.
|
||||||
|
(handle_gnu_v3_exceptions): Ditto.
|
||||||
|
(trace_command): Ditto.
|
||||||
|
(ftrace_command): Ditto.
|
||||||
|
(strace_command): Ditto.
|
||||||
|
(bkpt_print_mention): Add dprintf case.
|
||||||
|
(create_breakpoint_sal_default): Add extra_string argument.
|
||||||
|
(_initialize_breakpoint): Add new commands.
|
||||||
|
* mi/mi-cmd-break.c (mi_cmd_break_insert): Add arg to call.
|
||||||
|
* python/py-breakpoint.c (bppy_init): Ditto.
|
||||||
|
* python/py-finishbreakpoint.c (bpfinishpy_init): Ditto.
|
||||||
|
|
||||||
2012-05-14 Maciej W. Rozycki <macro@codesourcery.com>
|
2012-05-14 Maciej W. Rozycki <macro@codesourcery.com>
|
||||||
|
|
||||||
* mips-tdep.c (mips_push_dummy_code): Correct description typo.
|
* mips-tdep.c (mips_push_dummy_code): Correct description typo.
|
||||||
|
|
18
gdb/NEWS
18
gdb/NEWS
|
@ -142,6 +142,11 @@
|
||||||
"info auto-load python-scripts", "set auto-load python-scripts on|off"
|
"info auto-load python-scripts", "set auto-load python-scripts on|off"
|
||||||
and "show auto-load python-scripts" counterparts instead.
|
and "show auto-load python-scripts" counterparts instead.
|
||||||
|
|
||||||
|
** "dprintf location,format,args..." creates a dynamic printf, which
|
||||||
|
is basically a breakpoint that does a printf and immediately
|
||||||
|
resumes your program's execution, so it is like a printf that you
|
||||||
|
can insert dynamically at runtime instead of at compiletime.
|
||||||
|
|
||||||
* New targets
|
* New targets
|
||||||
|
|
||||||
Renesas RL78 rl78-*-elf
|
Renesas RL78 rl78-*-elf
|
||||||
|
@ -200,6 +205,19 @@ set debug auto-load on|off
|
||||||
show debug auto-load
|
show debug auto-load
|
||||||
Control display of debugging info for auto-loading the files above.
|
Control display of debugging info for auto-loading the files above.
|
||||||
|
|
||||||
|
set dprintf-style gdb|call
|
||||||
|
show dprintf-style
|
||||||
|
Control the way in which a dynamic printf is performed; "gdb" requests
|
||||||
|
a GDB printf command, while "call" causes dprintf to call a function
|
||||||
|
in the inferior.
|
||||||
|
|
||||||
|
set dprintf-function <expr>
|
||||||
|
show dprintf-function
|
||||||
|
set dprintf-channel <expr>
|
||||||
|
show dprintf-channel
|
||||||
|
Set the function and optional first argument to the call when using
|
||||||
|
the "call" style of dynamic printf.
|
||||||
|
|
||||||
* New configure options
|
* New configure options
|
||||||
|
|
||||||
--with-auto-load-dir
|
--with-auto-load-dir
|
||||||
|
|
293
gdb/breakpoint.c
293
gdb/breakpoint.c
|
@ -109,7 +109,7 @@ static void create_sals_from_address_default (char **,
|
||||||
static void create_breakpoints_sal_default (struct gdbarch *,
|
static void create_breakpoints_sal_default (struct gdbarch *,
|
||||||
struct linespec_result *,
|
struct linespec_result *,
|
||||||
struct linespec_sals *,
|
struct linespec_sals *,
|
||||||
char *, enum bptype,
|
char *, char *, enum bptype,
|
||||||
enum bpdisp, int, int,
|
enum bpdisp, int, int,
|
||||||
int,
|
int,
|
||||||
const struct breakpoint_ops *,
|
const struct breakpoint_ops *,
|
||||||
|
@ -294,6 +294,9 @@ struct breakpoint_ops bkpt_breakpoint_ops;
|
||||||
/* Breakpoints set on probes. */
|
/* Breakpoints set on probes. */
|
||||||
static struct breakpoint_ops bkpt_probe_breakpoint_ops;
|
static struct breakpoint_ops bkpt_probe_breakpoint_ops;
|
||||||
|
|
||||||
|
/* Dynamic printf class type. */
|
||||||
|
static struct breakpoint_ops dprintf_breakpoint_ops;
|
||||||
|
|
||||||
/* A reference-counted struct command_line. This lets multiple
|
/* A reference-counted struct command_line. This lets multiple
|
||||||
breakpoints share a single command list. */
|
breakpoints share a single command list. */
|
||||||
struct counted_command_line
|
struct counted_command_line
|
||||||
|
@ -1494,7 +1497,8 @@ int
|
||||||
is_breakpoint (const struct breakpoint *bpt)
|
is_breakpoint (const struct breakpoint *bpt)
|
||||||
{
|
{
|
||||||
return (bpt->type == bp_breakpoint
|
return (bpt->type == bp_breakpoint
|
||||||
|| bpt->type == bp_hardware_breakpoint);
|
|| bpt->type == bp_hardware_breakpoint
|
||||||
|
|| bpt->type == bp_dprintf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Return true if BPT is of any hardware watchpoint kind. */
|
/* Return true if BPT is of any hardware watchpoint kind. */
|
||||||
|
@ -5178,6 +5182,11 @@ bpstat_what (bpstat bs_head)
|
||||||
PC of the former breakpoint. */
|
PC of the former breakpoint. */
|
||||||
this_action = BPSTAT_WHAT_KEEP_CHECKING;
|
this_action = BPSTAT_WHAT_KEEP_CHECKING;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case bp_dprintf:
|
||||||
|
this_action = BPSTAT_WHAT_STOP_SILENT;
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
internal_error (__FILE__, __LINE__,
|
internal_error (__FILE__, __LINE__,
|
||||||
_("bpstat_what: unhandled bptype %d"), (int) bptype);
|
_("bpstat_what: unhandled bptype %d"), (int) bptype);
|
||||||
|
@ -5442,6 +5451,7 @@ bptype_string (enum bptype type)
|
||||||
{bp_tracepoint, "tracepoint"},
|
{bp_tracepoint, "tracepoint"},
|
||||||
{bp_fast_tracepoint, "fast tracepoint"},
|
{bp_fast_tracepoint, "fast tracepoint"},
|
||||||
{bp_static_tracepoint, "static tracepoint"},
|
{bp_static_tracepoint, "static tracepoint"},
|
||||||
|
{bp_dprintf, "dprintf"},
|
||||||
{bp_jit_event, "jit events"},
|
{bp_jit_event, "jit events"},
|
||||||
{bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"},
|
{bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"},
|
||||||
{bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"},
|
{bp_gnu_ifunc_resolver_return, "STT_GNU_IFUNC resolver return"},
|
||||||
|
@ -5582,6 +5592,7 @@ print_one_breakpoint_location (struct breakpoint *b,
|
||||||
case bp_tracepoint:
|
case bp_tracepoint:
|
||||||
case bp_fast_tracepoint:
|
case bp_fast_tracepoint:
|
||||||
case bp_static_tracepoint:
|
case bp_static_tracepoint:
|
||||||
|
case bp_dprintf:
|
||||||
case bp_jit_event:
|
case bp_jit_event:
|
||||||
case bp_gnu_ifunc_resolver:
|
case bp_gnu_ifunc_resolver:
|
||||||
case bp_gnu_ifunc_resolver_return:
|
case bp_gnu_ifunc_resolver_return:
|
||||||
|
@ -6444,6 +6455,7 @@ init_bp_location (struct bp_location *loc, const struct bp_location_ops *ops,
|
||||||
case bp_exception_master:
|
case bp_exception_master:
|
||||||
case bp_gnu_ifunc_resolver:
|
case bp_gnu_ifunc_resolver:
|
||||||
case bp_gnu_ifunc_resolver_return:
|
case bp_gnu_ifunc_resolver_return:
|
||||||
|
case bp_dprintf:
|
||||||
loc->loc_type = bp_loc_software_breakpoint;
|
loc->loc_type = bp_loc_software_breakpoint;
|
||||||
mark_breakpoint_location_modified (loc);
|
mark_breakpoint_location_modified (loc);
|
||||||
break;
|
break;
|
||||||
|
@ -8382,7 +8394,122 @@ bp_loc_is_permanent (struct bp_location *loc)
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* The style in which to perform a dynamic printf. This is a user
|
||||||
|
option because different output options have different tradeoffs;
|
||||||
|
if GDB does the printing, there is better error handling if there
|
||||||
|
is a problem with any of the arguments, but using an inferior
|
||||||
|
function lets you have special-purpose printers and sending of
|
||||||
|
output to the same place as compiled-in print functions. (Future
|
||||||
|
styles may include the ability to do a target-side printf.) */
|
||||||
|
|
||||||
|
static const char dprintf_style_gdb[] = "gdb";
|
||||||
|
static const char dprintf_style_call[] = "call";
|
||||||
|
static const char *const dprintf_style_enums[] = {
|
||||||
|
dprintf_style_gdb,
|
||||||
|
dprintf_style_call,
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
static const char *dprintf_style = dprintf_style_gdb;
|
||||||
|
|
||||||
|
/* The function to use for dynamic printf if the preferred style is to
|
||||||
|
call into the inferior. The value is simply a string that is
|
||||||
|
copied into the command, so it can be anything that GDB can
|
||||||
|
evaluate to a callable address, not necessarily a function name. */
|
||||||
|
|
||||||
|
static char *dprintf_function = "";
|
||||||
|
|
||||||
|
/* The channel to use for dynamic printf if the preferred style is to
|
||||||
|
call into the inferior; if a nonempty string, it will be passed to
|
||||||
|
the call as the first argument, with the format string as the
|
||||||
|
second. As with the dprintf function, this can be anything that
|
||||||
|
GDB knows how to evaluate, so in addition to common choices like
|
||||||
|
"stderr", this could be an app-specific expression like
|
||||||
|
"mystreams[curlogger]". */
|
||||||
|
|
||||||
|
static char *dprintf_channel = "";
|
||||||
|
|
||||||
|
/* Build a command list for the dprintf corresponding to the current
|
||||||
|
settings of the dprintf style options. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_dprintf_command_list (struct breakpoint *b)
|
||||||
|
{
|
||||||
|
char *dprintf_args = b->extra_string;
|
||||||
|
char *printf_line = NULL;
|
||||||
|
|
||||||
|
if (!dprintf_args)
|
||||||
|
return;
|
||||||
|
|
||||||
|
dprintf_args = skip_spaces (dprintf_args);
|
||||||
|
|
||||||
|
/* Allow a comma, as it may have terminated a location, but don't
|
||||||
|
insist on it. */
|
||||||
|
if (*dprintf_args == ',')
|
||||||
|
++dprintf_args;
|
||||||
|
dprintf_args = skip_spaces (dprintf_args);
|
||||||
|
|
||||||
|
if (*dprintf_args != '"')
|
||||||
|
error (_("Bad format string, missing '\"'."));
|
||||||
|
|
||||||
|
if (strcmp (dprintf_style, "gdb") == 0)
|
||||||
|
printf_line = xstrprintf ("printf %s", dprintf_args);
|
||||||
|
else if (strcmp (dprintf_style, "call") == 0)
|
||||||
|
{
|
||||||
|
if (!dprintf_function)
|
||||||
|
error (_("No function supplied for dprintf call"));
|
||||||
|
|
||||||
|
if (dprintf_channel && strlen (dprintf_channel) > 0)
|
||||||
|
printf_line = xstrprintf ("call (void) %s (%s,%s)",
|
||||||
|
dprintf_function,
|
||||||
|
dprintf_channel,
|
||||||
|
dprintf_args);
|
||||||
|
else
|
||||||
|
printf_line = xstrprintf ("call (void) %s (%s)",
|
||||||
|
dprintf_function,
|
||||||
|
dprintf_args);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
internal_error (__FILE__, __LINE__,
|
||||||
|
_("Invalid dprintf style."));
|
||||||
|
|
||||||
|
/* Manufacture a printf/continue sequence. */
|
||||||
|
if (printf_line)
|
||||||
|
{
|
||||||
|
struct command_line *printf_cmd_line, *cont_cmd_line = NULL;
|
||||||
|
|
||||||
|
cont_cmd_line = xmalloc (sizeof (struct command_line));
|
||||||
|
cont_cmd_line->control_type = simple_control;
|
||||||
|
cont_cmd_line->body_count = 0;
|
||||||
|
cont_cmd_line->body_list = NULL;
|
||||||
|
cont_cmd_line->next = NULL;
|
||||||
|
cont_cmd_line->line = xstrdup ("continue");
|
||||||
|
|
||||||
|
printf_cmd_line = xmalloc (sizeof (struct command_line));
|
||||||
|
printf_cmd_line->control_type = simple_control;
|
||||||
|
printf_cmd_line->body_count = 0;
|
||||||
|
printf_cmd_line->body_list = NULL;
|
||||||
|
printf_cmd_line->next = cont_cmd_line;
|
||||||
|
printf_cmd_line->line = printf_line;
|
||||||
|
|
||||||
|
breakpoint_set_commands (b, printf_cmd_line);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Update all dprintf commands, making their command lists reflect
|
||||||
|
current style settings. */
|
||||||
|
|
||||||
|
static void
|
||||||
|
update_dprintf_commands (char *args, int from_tty,
|
||||||
|
struct cmd_list_element *c)
|
||||||
|
{
|
||||||
|
struct breakpoint *b;
|
||||||
|
|
||||||
|
ALL_BREAKPOINTS (b)
|
||||||
|
{
|
||||||
|
if (b->type == bp_dprintf)
|
||||||
|
update_dprintf_command_list (b);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Create a breakpoint with SAL as location. Use ADDR_STRING
|
/* Create a breakpoint with SAL as location. Use ADDR_STRING
|
||||||
as textual description of the location, and COND_STRING
|
as textual description of the location, and COND_STRING
|
||||||
|
@ -8392,6 +8519,7 @@ static void
|
||||||
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
|
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
|
||||||
struct symtabs_and_lines sals, char *addr_string,
|
struct symtabs_and_lines sals, char *addr_string,
|
||||||
char *filter, char *cond_string,
|
char *filter, char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type, enum bpdisp disposition,
|
enum bptype type, enum bpdisp disposition,
|
||||||
int thread, int task, int ignore_count,
|
int thread, int task, int ignore_count,
|
||||||
const struct breakpoint_ops *ops, int from_tty,
|
const struct breakpoint_ops *ops, int from_tty,
|
||||||
|
@ -8438,6 +8566,7 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
|
||||||
b->task = task;
|
b->task = task;
|
||||||
|
|
||||||
b->cond_string = cond_string;
|
b->cond_string = cond_string;
|
||||||
|
b->extra_string = extra_string;
|
||||||
b->ignore_count = ignore_count;
|
b->ignore_count = ignore_count;
|
||||||
b->enable_state = enabled ? bp_enabled : bp_disabled;
|
b->enable_state = enabled ? bp_enabled : bp_disabled;
|
||||||
b->disposition = disposition;
|
b->disposition = disposition;
|
||||||
|
@ -8502,6 +8631,18 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
|
||||||
if (*arg)
|
if (*arg)
|
||||||
error (_("Garbage %s follows condition"), arg);
|
error (_("Garbage %s follows condition"), arg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Dynamic printf requires and uses additional arguments on the
|
||||||
|
command line, otherwise it's an error. */
|
||||||
|
if (type == bp_dprintf)
|
||||||
|
{
|
||||||
|
if (b->extra_string)
|
||||||
|
update_dprintf_command_list (b);
|
||||||
|
else
|
||||||
|
error (_("Format string required"));
|
||||||
|
}
|
||||||
|
else if (b->extra_string)
|
||||||
|
error (_("Garbage %s at end of command"), b->extra_string);
|
||||||
}
|
}
|
||||||
|
|
||||||
b->display_canonical = display_canonical;
|
b->display_canonical = display_canonical;
|
||||||
|
@ -8519,6 +8660,7 @@ static void
|
||||||
create_breakpoint_sal (struct gdbarch *gdbarch,
|
create_breakpoint_sal (struct gdbarch *gdbarch,
|
||||||
struct symtabs_and_lines sals, char *addr_string,
|
struct symtabs_and_lines sals, char *addr_string,
|
||||||
char *filter, char *cond_string,
|
char *filter, char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type, enum bpdisp disposition,
|
enum bptype type, enum bpdisp disposition,
|
||||||
int thread, int task, int ignore_count,
|
int thread, int task, int ignore_count,
|
||||||
const struct breakpoint_ops *ops, int from_tty,
|
const struct breakpoint_ops *ops, int from_tty,
|
||||||
|
@ -8542,7 +8684,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
|
||||||
|
|
||||||
init_breakpoint_sal (b, gdbarch,
|
init_breakpoint_sal (b, gdbarch,
|
||||||
sals, addr_string,
|
sals, addr_string,
|
||||||
filter, cond_string,
|
filter, cond_string, extra_string,
|
||||||
type, disposition,
|
type, disposition,
|
||||||
thread, task, ignore_count,
|
thread, task, ignore_count,
|
||||||
ops, from_tty,
|
ops, from_tty,
|
||||||
|
@ -8571,7 +8713,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
|
||||||
static void
|
static void
|
||||||
create_breakpoints_sal (struct gdbarch *gdbarch,
|
create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
struct linespec_result *canonical,
|
struct linespec_result *canonical,
|
||||||
char *cond_string,
|
char *cond_string, char *extra_string,
|
||||||
enum bptype type, enum bpdisp disposition,
|
enum bptype type, enum bpdisp disposition,
|
||||||
int thread, int task, int ignore_count,
|
int thread, int task, int ignore_count,
|
||||||
const struct breakpoint_ops *ops, int from_tty,
|
const struct breakpoint_ops *ops, int from_tty,
|
||||||
|
@ -8597,7 +8739,8 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
create_breakpoint_sal (gdbarch, lsal->sals,
|
create_breakpoint_sal (gdbarch, lsal->sals,
|
||||||
addr_string,
|
addr_string,
|
||||||
filter_string,
|
filter_string,
|
||||||
cond_string, type, disposition,
|
cond_string, extra_string,
|
||||||
|
type, disposition,
|
||||||
thread, task, ignore_count, ops,
|
thread, task, ignore_count, ops,
|
||||||
from_tty, enabled, internal, flags,
|
from_tty, enabled, internal, flags,
|
||||||
canonical->special_display);
|
canonical->special_display);
|
||||||
|
@ -8734,7 +8877,8 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
|
||||||
If no thread is found, *THREAD is set to -1. */
|
If no thread is found, *THREAD is set to -1. */
|
||||||
static void
|
static void
|
||||||
find_condition_and_thread (char *tok, CORE_ADDR pc,
|
find_condition_and_thread (char *tok, CORE_ADDR pc,
|
||||||
char **cond_string, int *thread, int *task)
|
char **cond_string, int *thread, int *task,
|
||||||
|
char **rest)
|
||||||
{
|
{
|
||||||
*cond_string = NULL;
|
*cond_string = NULL;
|
||||||
*thread = -1;
|
*thread = -1;
|
||||||
|
@ -8747,6 +8891,12 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
|
||||||
|
|
||||||
tok = skip_spaces (tok);
|
tok = skip_spaces (tok);
|
||||||
|
|
||||||
|
if ((*tok == '"' || *tok == ',') && rest)
|
||||||
|
{
|
||||||
|
*rest = savestring (tok, strlen (tok));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
end_tok = skip_to_space (tok);
|
end_tok = skip_to_space (tok);
|
||||||
|
|
||||||
toklen = end_tok - tok;
|
toklen = end_tok - tok;
|
||||||
|
@ -8786,6 +8936,11 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
|
||||||
if (!valid_task_id (*task))
|
if (!valid_task_id (*task))
|
||||||
error (_("Unknown task %d."), *task);
|
error (_("Unknown task %d."), *task);
|
||||||
}
|
}
|
||||||
|
else if (rest)
|
||||||
|
{
|
||||||
|
*rest = savestring (tok, strlen (tok));
|
||||||
|
tok += toklen;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
error (_("Junk at end of arguments."));
|
error (_("Junk at end of arguments."));
|
||||||
}
|
}
|
||||||
|
@ -8853,7 +9008,8 @@ decode_static_tracepoint_spec (char **arg_p)
|
||||||
|
|
||||||
int
|
int
|
||||||
create_breakpoint (struct gdbarch *gdbarch,
|
create_breakpoint (struct gdbarch *gdbarch,
|
||||||
char *arg, char *cond_string, int thread,
|
char *arg, char *cond_string,
|
||||||
|
int thread, char *extra_string,
|
||||||
int parse_condition_and_thread,
|
int parse_condition_and_thread,
|
||||||
int tempflag, enum bptype type_wanted,
|
int tempflag, enum bptype type_wanted,
|
||||||
int ignore_count,
|
int ignore_count,
|
||||||
|
@ -8975,16 +9131,22 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||||
|
|
||||||
if (parse_condition_and_thread)
|
if (parse_condition_and_thread)
|
||||||
{
|
{
|
||||||
|
char *rest;
|
||||||
/* Here we only parse 'arg' to separate condition
|
/* Here we only parse 'arg' to separate condition
|
||||||
from thread number, so parsing in context of first
|
from thread number, so parsing in context of first
|
||||||
sal is OK. When setting the breakpoint we'll
|
sal is OK. When setting the breakpoint we'll
|
||||||
re-parse it in context of each sal. */
|
re-parse it in context of each sal. */
|
||||||
cond_string = NULL;
|
cond_string = NULL;
|
||||||
thread = -1;
|
thread = -1;
|
||||||
|
rest = NULL;
|
||||||
find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
|
find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
|
||||||
&thread, &task);
|
&thread, &task, &rest);
|
||||||
if (cond_string)
|
if (cond_string)
|
||||||
make_cleanup (xfree, cond_string);
|
make_cleanup (xfree, cond_string);
|
||||||
|
if (rest)
|
||||||
|
make_cleanup (xfree, rest);
|
||||||
|
if (rest)
|
||||||
|
extra_string = rest;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -8994,10 +9156,16 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||||
cond_string = xstrdup (cond_string);
|
cond_string = xstrdup (cond_string);
|
||||||
make_cleanup (xfree, cond_string);
|
make_cleanup (xfree, cond_string);
|
||||||
}
|
}
|
||||||
|
/* Create a private copy of any extra string. */
|
||||||
|
if (extra_string)
|
||||||
|
{
|
||||||
|
extra_string = xstrdup (extra_string);
|
||||||
|
make_cleanup (xfree, extra_string);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ops->create_breakpoints_sal (gdbarch, &canonical, lsal,
|
ops->create_breakpoints_sal (gdbarch, &canonical, lsal,
|
||||||
cond_string, type_wanted,
|
cond_string, extra_string, type_wanted,
|
||||||
tempflag ? disp_del : disp_donttouch,
|
tempflag ? disp_del : disp_donttouch,
|
||||||
thread, task, ignore_count, ops,
|
thread, task, ignore_count, ops,
|
||||||
from_tty, enabled, internal, flags);
|
from_tty, enabled, internal, flags);
|
||||||
|
@ -9022,6 +9190,7 @@ create_breakpoint (struct gdbarch *gdbarch,
|
||||||
|
|
||||||
b->addr_string = copy_arg;
|
b->addr_string = copy_arg;
|
||||||
b->cond_string = NULL;
|
b->cond_string = NULL;
|
||||||
|
b->extra_string = NULL;
|
||||||
b->ignore_count = ignore_count;
|
b->ignore_count = ignore_count;
|
||||||
b->disposition = tempflag ? disp_del : disp_donttouch;
|
b->disposition = tempflag ? disp_del : disp_donttouch;
|
||||||
b->condition_not_parsed = 1;
|
b->condition_not_parsed = 1;
|
||||||
|
@ -9077,7 +9246,7 @@ break_command_1 (char *arg, int flag, int from_tty)
|
||||||
|
|
||||||
create_breakpoint (get_current_arch (),
|
create_breakpoint (get_current_arch (),
|
||||||
arg,
|
arg,
|
||||||
NULL, 0, 1 /* parse arg */,
|
NULL, 0, NULL, 1 /* parse arg */,
|
||||||
tempflag, type_wanted,
|
tempflag, type_wanted,
|
||||||
0 /* Ignore count */,
|
0 /* Ignore count */,
|
||||||
pending_break_support,
|
pending_break_support,
|
||||||
|
@ -9242,6 +9411,29 @@ stopat_command (char *arg, int from_tty)
|
||||||
break_command_1 (arg, 0, from_tty);
|
break_command_1 (arg, 0, from_tty);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dprintf_command (char *arg, int from_tty);
|
||||||
|
|
||||||
|
/* The dynamic printf command is mostly like a regular breakpoint, but
|
||||||
|
with a prewired command list consisting of a single output command,
|
||||||
|
built from extra arguments supplied on the dprintf command
|
||||||
|
line. */
|
||||||
|
|
||||||
|
void
|
||||||
|
dprintf_command (char *arg, int from_tty)
|
||||||
|
{
|
||||||
|
create_breakpoint (get_current_arch (),
|
||||||
|
arg,
|
||||||
|
NULL, 0, NULL, 1 /* parse arg */,
|
||||||
|
0, bp_dprintf,
|
||||||
|
0 /* Ignore count */,
|
||||||
|
pending_break_support,
|
||||||
|
&dprintf_breakpoint_ops,
|
||||||
|
from_tty,
|
||||||
|
1 /* enabled */,
|
||||||
|
0 /* internal */,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
/* Implement the "breakpoint_hit" breakpoint_ops method for
|
/* Implement the "breakpoint_hit" breakpoint_ops method for
|
||||||
ranged breakpoints. */
|
ranged breakpoints. */
|
||||||
|
|
||||||
|
@ -10953,7 +11145,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
|
||||||
trigger_func_name = "__cxa_throw";
|
trigger_func_name = "__cxa_throw";
|
||||||
|
|
||||||
create_breakpoint (get_current_arch (),
|
create_breakpoint (get_current_arch (),
|
||||||
trigger_func_name, cond_string, -1,
|
trigger_func_name, cond_string, -1, NULL,
|
||||||
0 /* condition and thread are valid. */,
|
0 /* condition and thread are valid. */,
|
||||||
tempflag, bp_breakpoint,
|
tempflag, bp_breakpoint,
|
||||||
0,
|
0,
|
||||||
|
@ -12182,6 +12374,7 @@ base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
struct linespec_result *c,
|
struct linespec_result *c,
|
||||||
struct linespec_sals *lsal,
|
struct linespec_sals *lsal,
|
||||||
char *cond_string,
|
char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type_wanted,
|
enum bptype type_wanted,
|
||||||
enum bpdisp disposition,
|
enum bpdisp disposition,
|
||||||
int thread,
|
int thread,
|
||||||
|
@ -12344,6 +12537,9 @@ bkpt_print_mention (struct breakpoint *b)
|
||||||
case bp_hardware_breakpoint:
|
case bp_hardware_breakpoint:
|
||||||
printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
|
printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
|
||||||
break;
|
break;
|
||||||
|
case bp_dprintf:
|
||||||
|
printf_filtered (_("Dprintf %d"), b->number);
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
say_where (b);
|
say_where (b);
|
||||||
|
@ -12384,6 +12580,7 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
struct linespec_result *canonical,
|
struct linespec_result *canonical,
|
||||||
struct linespec_sals *lsal,
|
struct linespec_sals *lsal,
|
||||||
char *cond_string,
|
char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type_wanted,
|
enum bptype type_wanted,
|
||||||
enum bpdisp disposition,
|
enum bpdisp disposition,
|
||||||
int thread,
|
int thread,
|
||||||
|
@ -12393,7 +12590,8 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
int internal, unsigned flags)
|
int internal, unsigned flags)
|
||||||
{
|
{
|
||||||
create_breakpoints_sal_default (gdbarch, canonical, lsal,
|
create_breakpoints_sal_default (gdbarch, canonical, lsal,
|
||||||
cond_string, type_wanted,
|
cond_string, extra_string,
|
||||||
|
type_wanted,
|
||||||
disposition, thread, task,
|
disposition, thread, task,
|
||||||
ignore_count, ops, from_tty,
|
ignore_count, ops, from_tty,
|
||||||
enabled, internal, flags);
|
enabled, internal, flags);
|
||||||
|
@ -12705,6 +12903,7 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
struct linespec_result *canonical,
|
struct linespec_result *canonical,
|
||||||
struct linespec_sals *lsal,
|
struct linespec_sals *lsal,
|
||||||
char *cond_string,
|
char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type_wanted,
|
enum bptype type_wanted,
|
||||||
enum bpdisp disposition,
|
enum bpdisp disposition,
|
||||||
int thread,
|
int thread,
|
||||||
|
@ -12714,7 +12913,8 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
int internal, unsigned flags)
|
int internal, unsigned flags)
|
||||||
{
|
{
|
||||||
create_breakpoints_sal_default (gdbarch, canonical, lsal,
|
create_breakpoints_sal_default (gdbarch, canonical, lsal,
|
||||||
cond_string, type_wanted,
|
cond_string, extra_string,
|
||||||
|
type_wanted,
|
||||||
disposition, thread, task,
|
disposition, thread, task,
|
||||||
ignore_count, ops, from_tty,
|
ignore_count, ops, from_tty,
|
||||||
enabled, internal, flags);
|
enabled, internal, flags);
|
||||||
|
@ -12778,6 +12978,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
struct linespec_result *canonical,
|
struct linespec_result *canonical,
|
||||||
struct linespec_sals *lsal,
|
struct linespec_sals *lsal,
|
||||||
char *cond_string,
|
char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type_wanted,
|
enum bptype type_wanted,
|
||||||
enum bpdisp disposition,
|
enum bpdisp disposition,
|
||||||
int thread,
|
int thread,
|
||||||
|
@ -12811,7 +13012,8 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
|
||||||
tp = XCNEW (struct tracepoint);
|
tp = XCNEW (struct tracepoint);
|
||||||
init_breakpoint_sal (&tp->base, gdbarch, expanded,
|
init_breakpoint_sal (&tp->base, gdbarch, expanded,
|
||||||
addr_string, NULL,
|
addr_string, NULL,
|
||||||
cond_string, type_wanted, disposition,
|
cond_string, extra_string,
|
||||||
|
type_wanted, disposition,
|
||||||
thread, task, ignore_count, ops,
|
thread, task, ignore_count, ops,
|
||||||
from_tty, enabled, internal, flags,
|
from_tty, enabled, internal, flags,
|
||||||
canonical->special_display);
|
canonical->special_display);
|
||||||
|
@ -13438,13 +13640,17 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
|
||||||
char *cond_string = 0;
|
char *cond_string = 0;
|
||||||
int thread = -1;
|
int thread = -1;
|
||||||
int task = 0;
|
int task = 0;
|
||||||
|
char *extra_string = NULL;
|
||||||
|
|
||||||
find_condition_and_thread (s, sals.sals[0].pc,
|
find_condition_and_thread (s, sals.sals[0].pc,
|
||||||
&cond_string, &thread, &task);
|
&cond_string, &thread, &task,
|
||||||
|
&extra_string);
|
||||||
if (cond_string)
|
if (cond_string)
|
||||||
b->cond_string = cond_string;
|
b->cond_string = cond_string;
|
||||||
b->thread = thread;
|
b->thread = thread;
|
||||||
b->task = task;
|
b->task = task;
|
||||||
|
if (extra_string)
|
||||||
|
b->extra_string = extra_string;
|
||||||
b->condition_not_parsed = 0;
|
b->condition_not_parsed = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13512,6 +13718,7 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch,
|
||||||
struct linespec_result *canonical,
|
struct linespec_result *canonical,
|
||||||
struct linespec_sals *lsal,
|
struct linespec_sals *lsal,
|
||||||
char *cond_string,
|
char *cond_string,
|
||||||
|
char *extra_string,
|
||||||
enum bptype type_wanted,
|
enum bptype type_wanted,
|
||||||
enum bpdisp disposition,
|
enum bpdisp disposition,
|
||||||
int thread,
|
int thread,
|
||||||
|
@ -13521,6 +13728,7 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch,
|
||||||
int internal, unsigned flags)
|
int internal, unsigned flags)
|
||||||
{
|
{
|
||||||
create_breakpoints_sal (gdbarch, canonical, cond_string,
|
create_breakpoints_sal (gdbarch, canonical, cond_string,
|
||||||
|
extra_string,
|
||||||
type_wanted, disposition,
|
type_wanted, disposition,
|
||||||
thread, task, ignore_count, ops, from_tty,
|
thread, task, ignore_count, ops, from_tty,
|
||||||
enabled, internal, flags);
|
enabled, internal, flags);
|
||||||
|
@ -14394,7 +14602,7 @@ trace_command (char *arg, int from_tty)
|
||||||
|
|
||||||
if (create_breakpoint (get_current_arch (),
|
if (create_breakpoint (get_current_arch (),
|
||||||
arg,
|
arg,
|
||||||
NULL, 0, 1 /* parse arg */,
|
NULL, 0, NULL, 1 /* parse arg */,
|
||||||
0 /* tempflag */,
|
0 /* tempflag */,
|
||||||
bp_tracepoint /* type_wanted */,
|
bp_tracepoint /* type_wanted */,
|
||||||
0 /* Ignore count */,
|
0 /* Ignore count */,
|
||||||
|
@ -14411,7 +14619,7 @@ ftrace_command (char *arg, int from_tty)
|
||||||
{
|
{
|
||||||
if (create_breakpoint (get_current_arch (),
|
if (create_breakpoint (get_current_arch (),
|
||||||
arg,
|
arg,
|
||||||
NULL, 0, 1 /* parse arg */,
|
NULL, 0, NULL, 1 /* parse arg */,
|
||||||
0 /* tempflag */,
|
0 /* tempflag */,
|
||||||
bp_fast_tracepoint /* type_wanted */,
|
bp_fast_tracepoint /* type_wanted */,
|
||||||
0 /* Ignore count */,
|
0 /* Ignore count */,
|
||||||
|
@ -14439,7 +14647,7 @@ strace_command (char *arg, int from_tty)
|
||||||
|
|
||||||
if (create_breakpoint (get_current_arch (),
|
if (create_breakpoint (get_current_arch (),
|
||||||
arg,
|
arg,
|
||||||
NULL, 0, 1 /* parse arg */,
|
NULL, 0, NULL, 1 /* parse arg */,
|
||||||
0 /* tempflag */,
|
0 /* tempflag */,
|
||||||
bp_static_tracepoint /* type_wanted */,
|
bp_static_tracepoint /* type_wanted */,
|
||||||
0 /* Ignore count */,
|
0 /* Ignore count */,
|
||||||
|
@ -14504,7 +14712,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
|
||||||
|
|
||||||
if (!create_breakpoint (get_current_arch (),
|
if (!create_breakpoint (get_current_arch (),
|
||||||
addr_str,
|
addr_str,
|
||||||
utp->cond_string, -1, 0 /* parse cond/thread */,
|
utp->cond_string, -1, NULL,
|
||||||
|
0 /* parse cond/thread */,
|
||||||
0 /* tempflag */,
|
0 /* tempflag */,
|
||||||
utp->type /* type_wanted */,
|
utp->type /* type_wanted */,
|
||||||
0 /* Ignore count */,
|
0 /* Ignore count */,
|
||||||
|
@ -15260,6 +15469,14 @@ initialize_breakpoint_ops (void)
|
||||||
ops->print_one = print_one_catch_solib;
|
ops->print_one = print_one_catch_solib;
|
||||||
ops->print_mention = print_mention_catch_solib;
|
ops->print_mention = print_mention_catch_solib;
|
||||||
ops->print_recreate = print_recreate_catch_solib;
|
ops->print_recreate = print_recreate_catch_solib;
|
||||||
|
|
||||||
|
ops = &dprintf_breakpoint_ops;
|
||||||
|
*ops = bkpt_base_breakpoint_ops;
|
||||||
|
ops->re_set = bkpt_re_set;
|
||||||
|
ops->resources_needed = bkpt_resources_needed;
|
||||||
|
ops->print_it = bkpt_print_it;
|
||||||
|
ops->print_mention = bkpt_print_mention;
|
||||||
|
ops->print_recreate = bkpt_print_recreate;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -15842,6 +16059,44 @@ The breakpoint will stop execution of the inferior whenever it executes\n\
|
||||||
an instruction at any address within the [START-LOCATION, END-LOCATION]\n\
|
an instruction at any address within the [START-LOCATION, END-LOCATION]\n\
|
||||||
range (including START-LOCATION and END-LOCATION)."));
|
range (including START-LOCATION and END-LOCATION)."));
|
||||||
|
|
||||||
|
c = add_com ("dprintf", class_breakpoint, dprintf_command, _("\
|
||||||
|
Set a dynamic printf at specified line or function.\n\
|
||||||
|
dprintf location,format string,arg1,arg2,...\n\
|
||||||
|
location may be a line number, function name, or \"*\" and an address.\n\
|
||||||
|
If a line number is specified, break at start of code for that line.\n\
|
||||||
|
If a function is specified, break at start of code for that function.\n\
|
||||||
|
"));
|
||||||
|
set_cmd_completer (c, location_completer);
|
||||||
|
|
||||||
|
add_setshow_enum_cmd ("dprintf-style", class_support,
|
||||||
|
dprintf_style_enums, &dprintf_style, _("\
|
||||||
|
Set the style of usage for dynamic printf."), _("\
|
||||||
|
Show the style of usage for dynamic printf."), _("\
|
||||||
|
This setting chooses how GDB will do a dynamic printf.\n\
|
||||||
|
If the value is \"gdb\", then the printing is done by GDB to its own\n\
|
||||||
|
console, as with the \"printf\" command.\n\
|
||||||
|
If the value is \"call\", the print is done by calling a function in your\n\
|
||||||
|
program; by default printf(), but you can choose a different function or\n\
|
||||||
|
output stream by setting dprintf-function and dprintf-channel."),
|
||||||
|
update_dprintf_commands, NULL,
|
||||||
|
&setlist, &showlist);
|
||||||
|
|
||||||
|
dprintf_function = xstrdup ("printf");
|
||||||
|
add_setshow_string_cmd ("dprintf-function", class_support,
|
||||||
|
&dprintf_function, _("\
|
||||||
|
Set the function to use for dynamic printf"), _("\
|
||||||
|
Show the function to use for dynamic printf"), NULL,
|
||||||
|
update_dprintf_commands, NULL,
|
||||||
|
&setlist, &showlist);
|
||||||
|
|
||||||
|
dprintf_channel = xstrdup ("");
|
||||||
|
add_setshow_string_cmd ("dprintf-channel", class_support,
|
||||||
|
&dprintf_channel, _("\
|
||||||
|
Set the channel to use for dynamic printf"), _("\
|
||||||
|
Show the channel to use for dynamic printf"), NULL,
|
||||||
|
update_dprintf_commands, NULL,
|
||||||
|
&setlist, &showlist);
|
||||||
|
|
||||||
automatic_hardware_breakpoints = 1;
|
automatic_hardware_breakpoints = 1;
|
||||||
|
|
||||||
observer_attach_about_to_proceed (breakpoint_about_to_proceed);
|
observer_attach_about_to_proceed (breakpoint_about_to_proceed);
|
||||||
|
|
|
@ -154,6 +154,13 @@ enum bptype
|
||||||
bp_fast_tracepoint,
|
bp_fast_tracepoint,
|
||||||
bp_static_tracepoint,
|
bp_static_tracepoint,
|
||||||
|
|
||||||
|
/* A dynamic printf stops at the given location, does a formatted
|
||||||
|
print, then automatically continues. (Although this is sort of
|
||||||
|
like a macro packaging up standard breakpoint functionality,
|
||||||
|
GDB doesn't have a way to construct types of breakpoint from
|
||||||
|
elements of behavior.) */
|
||||||
|
bp_dprintf,
|
||||||
|
|
||||||
/* Event for JIT compiled code generation or deletion. */
|
/* Event for JIT compiled code generation or deletion. */
|
||||||
bp_jit_event,
|
bp_jit_event,
|
||||||
|
|
||||||
|
@ -552,6 +559,7 @@ struct breakpoint_ops
|
||||||
void (*create_breakpoints_sal) (struct gdbarch *,
|
void (*create_breakpoints_sal) (struct gdbarch *,
|
||||||
struct linespec_result *,
|
struct linespec_result *,
|
||||||
struct linespec_sals *, char *,
|
struct linespec_sals *, char *,
|
||||||
|
char *,
|
||||||
enum bptype, enum bpdisp, int, int,
|
enum bptype, enum bpdisp, int, int,
|
||||||
int, const struct breakpoint_ops *,
|
int, const struct breakpoint_ops *,
|
||||||
int, int, int, unsigned);
|
int, int, int, unsigned);
|
||||||
|
@ -674,8 +682,9 @@ struct breakpoint
|
||||||
/* String form of the breakpoint condition (malloc'd), or NULL if
|
/* String form of the breakpoint condition (malloc'd), or NULL if
|
||||||
there is no condition. */
|
there is no condition. */
|
||||||
char *cond_string;
|
char *cond_string;
|
||||||
/* String form of exp to use for displaying to the user
|
|
||||||
(malloc'd), or NULL if none. */
|
/* String form of extra parameters, or NULL if there are none. */
|
||||||
|
char *extra_string;
|
||||||
|
|
||||||
/* Holds the address of the related watchpoint_scope breakpoint
|
/* Holds the address of the related watchpoint_scope breakpoint
|
||||||
when using watchpoints on local variables (might the concept of
|
when using watchpoints on local variables (might the concept of
|
||||||
|
@ -1210,6 +1219,7 @@ enum breakpoint_create_flags
|
||||||
|
|
||||||
extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
|
extern int create_breakpoint (struct gdbarch *gdbarch, char *arg,
|
||||||
char *cond_string, int thread,
|
char *cond_string, int thread,
|
||||||
|
char *extra_string,
|
||||||
int parse_condition_and_thread,
|
int parse_condition_and_thread,
|
||||||
int tempflag, enum bptype wanted_type,
|
int tempflag, enum bptype wanted_type,
|
||||||
int ignore_count,
|
int ignore_count,
|
||||||
|
|
|
@ -1,3 +1,7 @@
|
||||||
|
2012-05-14 Stan Shebs <stan@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.texinfo (Dynamic Printf): New subsection.
|
||||||
|
|
||||||
2012-05-13 Siva Chandra Reddy <sivachandra@google.com>
|
2012-05-13 Siva Chandra Reddy <sivachandra@google.com>
|
||||||
|
|
||||||
* gdb.texinfo (Basic Python): Add description about the function
|
* gdb.texinfo (Basic Python): Add description about the function
|
||||||
|
|
|
@ -3341,6 +3341,7 @@ all breakpoints in that range are operated on.
|
||||||
* Disabling:: Disabling breakpoints
|
* Disabling:: Disabling breakpoints
|
||||||
* Conditions:: Break conditions
|
* Conditions:: Break conditions
|
||||||
* Break Commands:: Breakpoint command lists
|
* Break Commands:: Breakpoint command lists
|
||||||
|
* Dynamic Printf:: Dynamic printf
|
||||||
* Save Breakpoints:: How to save breakpoints in a file
|
* Save Breakpoints:: How to save breakpoints in a file
|
||||||
* Static Probe Points:: Listing static probe points
|
* Static Probe Points:: Listing static probe points
|
||||||
* Error in Breakpoints:: ``Cannot insert breakpoints''
|
* Error in Breakpoints:: ``Cannot insert breakpoints''
|
||||||
|
@ -4628,6 +4629,89 @@ cont
|
||||||
end
|
end
|
||||||
@end smallexample
|
@end smallexample
|
||||||
|
|
||||||
|
@node Dynamic Printf
|
||||||
|
@subsection Dynamic Printf
|
||||||
|
|
||||||
|
@cindex dynamic printf
|
||||||
|
@cindex dprintf
|
||||||
|
The dynamic printf command @code{dprintf} combines a breakpoint with
|
||||||
|
formatted printing of your program's data to give you the effect of
|
||||||
|
inserting @code{printf} calls into your program on-the-fly, without
|
||||||
|
having to recompile it.
|
||||||
|
|
||||||
|
In its most basic form, the output goes to the GDB console. However,
|
||||||
|
you can set the variable @code{dprintf-style} for alternate handling.
|
||||||
|
For instance, you can ask to format the output by calling your
|
||||||
|
program's @code{printf} function. This has the advantage that the
|
||||||
|
characters go to the program's output device, so they can recorded in
|
||||||
|
redirects to files and so forth.
|
||||||
|
|
||||||
|
@table @code
|
||||||
|
@kindex dprintf
|
||||||
|
@item dprintf @var{location},@var{template},@var{expression}[,@var{expression}@dots{}]
|
||||||
|
Whenever execution reaches @var{location}, print the values of one or
|
||||||
|
more @var{expressions} under the control of the string @var{template}.
|
||||||
|
To print several values, separate them with commas.
|
||||||
|
|
||||||
|
@item set dprintf-style @var{style}
|
||||||
|
Set the dprintf output to be handled in one of several different
|
||||||
|
styles enumerated below. A change of style affects all existing
|
||||||
|
dynamic printfs immediately. (If you need individual control over the
|
||||||
|
print commands, simply define normal breakpoints with
|
||||||
|
explicitly-supplied command lists.)
|
||||||
|
|
||||||
|
@item gdb
|
||||||
|
@kindex dprintf-style gdb
|
||||||
|
Handle the output using the @value{GDBN} @code{printf} command.
|
||||||
|
|
||||||
|
@item call
|
||||||
|
@kindex dprintf-style call
|
||||||
|
Handle the output by calling a function in your program (normally
|
||||||
|
@code{printf}).
|
||||||
|
|
||||||
|
@item set dprintf-function @var{function}
|
||||||
|
Set the function to call if the dprintf style is @code{call}. By
|
||||||
|
default its value is @code{printf}. You may set it to any expression.
|
||||||
|
that @value{GDBN} can evaluate to a function, as per the @code{call}
|
||||||
|
command.
|
||||||
|
|
||||||
|
@item set dprintf-channel @var{channel}
|
||||||
|
Set a ``channel'' for dprintf. If set to a non-empty value,
|
||||||
|
@value{GDBN} will evaluate it as an expression and pass the result as
|
||||||
|
a first argument to the @code{dprintf-function}, in the manner of
|
||||||
|
@code{fprintf} and similar functions. Otherwise, the dprintf format
|
||||||
|
string will be the first argument, in the manner of @code{printf}.
|
||||||
|
|
||||||
|
As an example, if you wanted @code{dprintf} output to go to a logfile
|
||||||
|
that is a standard I/O stream assigned to the variable @code{mylog},
|
||||||
|
you could do the following:
|
||||||
|
|
||||||
|
@example
|
||||||
|
(gdb) set dprintf-style call
|
||||||
|
(gdb) set dprintf-function fprintf
|
||||||
|
(gdb) set dprintf-channel mylog
|
||||||
|
(gdb) dprintf 25,"at line 25, glob=%d\n",glob
|
||||||
|
Dprintf 1 at 0x123456: file main.c, line 25.
|
||||||
|
(gdb) info break
|
||||||
|
1 dprintf keep y 0x00123456 in main at main.c:25
|
||||||
|
call (void) fprintf (mylog,"at line 25, glob=%d\n",glob)
|
||||||
|
continue
|
||||||
|
(gdb)
|
||||||
|
@end example
|
||||||
|
|
||||||
|
Note that the @code{info break} displays the dynamic printf commands
|
||||||
|
as normal breakpoint commands; you can thus easily see the effect of
|
||||||
|
the variable settings.
|
||||||
|
|
||||||
|
@end table
|
||||||
|
|
||||||
|
@value{GDBN} does not check the validity of function and channel,
|
||||||
|
relying on you to supply values that are meaningful for the contexts
|
||||||
|
in which they are being used. For instance, the function and channel
|
||||||
|
may be the values of local variables, but if that is the case, then
|
||||||
|
all enabled dynamic prints must be at locations within the scope of
|
||||||
|
those locals. If evaluation fails, @value{GDBN} will report an error.
|
||||||
|
|
||||||
@node Save Breakpoints
|
@node Save Breakpoints
|
||||||
@subsection How to save breakpoints to a file
|
@subsection How to save breakpoints to a file
|
||||||
|
|
||||||
|
|
|
@ -164,6 +164,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
|
||||||
: (hardware ? bp_hardware_breakpoint : bp_breakpoint));
|
: (hardware ? bp_hardware_breakpoint : bp_breakpoint));
|
||||||
|
|
||||||
create_breakpoint (get_current_arch (), address, condition, thread,
|
create_breakpoint (get_current_arch (), address, condition, thread,
|
||||||
|
NULL,
|
||||||
0 /* condition and thread are valid. */,
|
0 /* condition and thread are valid. */,
|
||||||
temp_p, type_wanted,
|
temp_p, type_wanted,
|
||||||
ignore_count,
|
ignore_count,
|
||||||
|
|
|
@ -622,7 +622,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
case bp_breakpoint:
|
case bp_breakpoint:
|
||||||
{
|
{
|
||||||
create_breakpoint (python_gdbarch,
|
create_breakpoint (python_gdbarch,
|
||||||
copy, NULL, -1,
|
copy, NULL, -1, NULL,
|
||||||
0,
|
0,
|
||||||
0, bp_breakpoint,
|
0, bp_breakpoint,
|
||||||
0,
|
0,
|
||||||
|
|
|
@ -281,7 +281,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
|
||||||
addr_str = small_buf;
|
addr_str = small_buf;
|
||||||
|
|
||||||
create_breakpoint (python_gdbarch,
|
create_breakpoint (python_gdbarch,
|
||||||
addr_str, NULL, thread,
|
addr_str, NULL, thread, NULL,
|
||||||
0,
|
0,
|
||||||
1 /*temp_flag*/,
|
1 /*temp_flag*/,
|
||||||
bp_breakpoint,
|
bp_breakpoint,
|
||||||
|
|
|
@ -1,3 +1,8 @@
|
||||||
|
2012-05-14 Stan Shebs <stan@codesourcery.com>
|
||||||
|
|
||||||
|
* gdb.base/dprintf.c: New file.
|
||||||
|
* gdb.base/dprintf.exp: New file.
|
||||||
|
|
||||||
2012-05-14 Hui Zhu <hui_zhu@mentor.com>
|
2012-05-14 Hui Zhu <hui_zhu@mentor.com>
|
||||||
|
|
||||||
* gdb.trace/Makefile.in (PROGS): Add disconnected-tracing.
|
* gdb.trace/Makefile.in (PROGS): Add disconnected-tracing.
|
||||||
|
|
44
gdb/testsuite/gdb.base/dprintf.c
Normal file
44
gdb/testsuite/gdb.base/dprintf.c
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
/* This testcase is part of GDB, the GNU debugger.
|
||||||
|
|
||||||
|
Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
This program is free software; you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU General Public License as published by
|
||||||
|
the Free Software Foundation; either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
static int g;
|
||||||
|
|
||||||
|
void
|
||||||
|
foo (int arg)
|
||||||
|
{
|
||||||
|
g += arg;
|
||||||
|
g *= 2; /* set dprintf 1 here */
|
||||||
|
g /= 2.5; /* set breakpoint 1 here */
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
main (int argc, char *argv[])
|
||||||
|
{
|
||||||
|
int loc = 1234;
|
||||||
|
|
||||||
|
/* Ensure these functions are available. */
|
||||||
|
printf ("kickoff\n");
|
||||||
|
fprintf (stderr, "also to stderr\n");
|
||||||
|
|
||||||
|
foo (loc++);
|
||||||
|
foo (loc++);
|
||||||
|
foo (loc++);
|
||||||
|
return g;
|
||||||
|
}
|
||||||
|
|
89
gdb/testsuite/gdb.base/dprintf.exp
Normal file
89
gdb/testsuite/gdb.base/dprintf.exp
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
# Copyright (C) 2012 Free Software Foundation, Inc.
|
||||||
|
|
||||||
|
# This program is free software; you can redistribute it and/or modify
|
||||||
|
# it under the terms of the GNU General Public License as published by
|
||||||
|
# the Free Software Foundation; either version 3 of the License, or
|
||||||
|
# (at your option) any later version.
|
||||||
|
#
|
||||||
|
# This program is distributed in the hope that it will be useful,
|
||||||
|
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
# GNU General Public License for more details.
|
||||||
|
#
|
||||||
|
# You should have received a copy of the GNU General Public License
|
||||||
|
# along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
|
||||||
|
if { [prepare_for_testing dprintf.exp "dprintf" {} {debug}] } {
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
set srcfile dprintf.c
|
||||||
|
|
||||||
|
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
|
||||||
|
set dp_location1 [gdb_get_line_number "set dprintf 1 here"]
|
||||||
|
|
||||||
|
gdb_breakpoint "main"
|
||||||
|
gdb_run_cmd
|
||||||
|
|
||||||
|
gdb_test "dprintf" "Format string required"
|
||||||
|
|
||||||
|
gdb_test "dprintf foo" "Format string required"
|
||||||
|
|
||||||
|
gdb_test "dprintf 29" "Format string required"
|
||||||
|
|
||||||
|
delete_breakpoints
|
||||||
|
|
||||||
|
gdb_breakpoint "main"
|
||||||
|
|
||||||
|
gdb_test "dprintf foo,\"At foo entry\\n\"" \
|
||||||
|
"Dprintf .*"
|
||||||
|
|
||||||
|
gdb_test "dprintf $dp_location1,\"arg=%d, g=%d\\n\", arg, g" \
|
||||||
|
"Dprintf .*"
|
||||||
|
|
||||||
|
gdb_test "break $bp_location1" \
|
||||||
|
"Breakpoint .*"
|
||||||
|
|
||||||
|
gdb_run_cmd
|
||||||
|
|
||||||
|
gdb_test "" "Breakpoint"
|
||||||
|
|
||||||
|
gdb_test "continue" "At foo entry.*arg=1234, g=1234.*" "1st dprintf, gdb"
|
||||||
|
|
||||||
|
gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" "2nd dprintf, gdb"
|
||||||
|
|
||||||
|
# The "call" style depends on having I/O functions available, so test.
|
||||||
|
|
||||||
|
if ![target_info exists gdb,noinferiorio] {
|
||||||
|
|
||||||
|
# Now switch styles and rerun; in the absence of redirection the
|
||||||
|
# output should be the same.
|
||||||
|
|
||||||
|
gdb_test_no_output "set dprintf-style call" "Set dprintf style to call"
|
||||||
|
|
||||||
|
gdb_run_cmd
|
||||||
|
|
||||||
|
gdb_test "" "Breakpoint"
|
||||||
|
|
||||||
|
gdb_test "continue" "At foo entry.*arg=1234, g=1234.*" "1st dprintf, call"
|
||||||
|
|
||||||
|
gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" "2nd dprintf, call"
|
||||||
|
|
||||||
|
gdb_test_no_output "set dprintf-function fprintf" "Set dprintf function"
|
||||||
|
gdb_test_no_output "set dprintf-channel stderr" "Set dprintf channel"
|
||||||
|
|
||||||
|
gdb_run_cmd
|
||||||
|
|
||||||
|
gdb_test "" "Breakpoint"
|
||||||
|
|
||||||
|
gdb_test "continue" "At foo entry.*arg=1234, g=1234.*" \
|
||||||
|
"1st dprintf, fprintf"
|
||||||
|
|
||||||
|
gdb_test "continue" "At foo entry.*arg=1235, g=2222.*" \
|
||||||
|
"2nd dprintf, fprintf"
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_test "set dprintf-style foobar" "Undefined item: \"foobar\"." \
|
||||||
|
"Set dprintf style to an unrecognized type"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue