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:
Stan Shebs 2012-05-14 15:38:41 +00:00
parent 27d799802a
commit e7e0cddfb0
12 changed files with 572 additions and 24 deletions

View File

@ -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>
* mips-tdep.c (mips_push_dummy_code): Correct description typo.

View File

@ -142,6 +142,11 @@
"info auto-load python-scripts", "set auto-load python-scripts on|off"
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
Renesas RL78 rl78-*-elf
@ -200,6 +205,19 @@ set debug auto-load on|off
show debug auto-load
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
--with-auto-load-dir

View File

@ -109,7 +109,7 @@ static void create_sals_from_address_default (char **,
static void create_breakpoints_sal_default (struct gdbarch *,
struct linespec_result *,
struct linespec_sals *,
char *, enum bptype,
char *, char *, enum bptype,
enum bpdisp, int, int,
int,
const struct breakpoint_ops *,
@ -294,6 +294,9 @@ struct breakpoint_ops bkpt_breakpoint_ops;
/* Breakpoints set on probes. */
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
breakpoints share a single command list. */
struct counted_command_line
@ -1494,7 +1497,8 @@ int
is_breakpoint (const struct breakpoint *bpt)
{
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. */
@ -5178,6 +5182,11 @@ bpstat_what (bpstat bs_head)
PC of the former breakpoint. */
this_action = BPSTAT_WHAT_KEEP_CHECKING;
break;
case bp_dprintf:
this_action = BPSTAT_WHAT_STOP_SILENT;
break;
default:
internal_error (__FILE__, __LINE__,
_("bpstat_what: unhandled bptype %d"), (int) bptype);
@ -5442,6 +5451,7 @@ bptype_string (enum bptype type)
{bp_tracepoint, "tracepoint"},
{bp_fast_tracepoint, "fast tracepoint"},
{bp_static_tracepoint, "static tracepoint"},
{bp_dprintf, "dprintf"},
{bp_jit_event, "jit events"},
{bp_gnu_ifunc_resolver, "STT_GNU_IFUNC resolver"},
{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_fast_tracepoint:
case bp_static_tracepoint:
case bp_dprintf:
case bp_jit_event:
case bp_gnu_ifunc_resolver:
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_gnu_ifunc_resolver:
case bp_gnu_ifunc_resolver_return:
case bp_dprintf:
loc->loc_type = bp_loc_software_breakpoint;
mark_breakpoint_location_modified (loc);
break;
@ -8382,7 +8394,122 @@ bp_loc_is_permanent (struct bp_location *loc)
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
as textual description of the location, and COND_STRING
@ -8392,6 +8519,7 @@ static void
init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
char *filter, char *cond_string,
char *extra_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
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->cond_string = cond_string;
b->extra_string = extra_string;
b->ignore_count = ignore_count;
b->enable_state = enabled ? bp_enabled : bp_disabled;
b->disposition = disposition;
@ -8502,6 +8631,18 @@ init_breakpoint_sal (struct breakpoint *b, struct gdbarch *gdbarch,
if (*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;
@ -8519,6 +8660,7 @@ static void
create_breakpoint_sal (struct gdbarch *gdbarch,
struct symtabs_and_lines sals, char *addr_string,
char *filter, char *cond_string,
char *extra_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
const struct breakpoint_ops *ops, int from_tty,
@ -8542,7 +8684,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
init_breakpoint_sal (b, gdbarch,
sals, addr_string,
filter, cond_string,
filter, cond_string, extra_string,
type, disposition,
thread, task, ignore_count,
ops, from_tty,
@ -8571,7 +8713,7 @@ create_breakpoint_sal (struct gdbarch *gdbarch,
static void
create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
char *cond_string,
char *cond_string, char *extra_string,
enum bptype type, enum bpdisp disposition,
int thread, int task, int ignore_count,
const struct breakpoint_ops *ops, int from_tty,
@ -8597,7 +8739,8 @@ create_breakpoints_sal (struct gdbarch *gdbarch,
create_breakpoint_sal (gdbarch, lsal->sals,
addr_string,
filter_string,
cond_string, type, disposition,
cond_string, extra_string,
type, disposition,
thread, task, ignore_count, ops,
from_tty, enabled, internal, flags,
canonical->special_display);
@ -8734,7 +8877,8 @@ check_fast_tracepoint_sals (struct gdbarch *gdbarch,
If no thread is found, *THREAD is set to -1. */
static void
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;
*thread = -1;
@ -8746,7 +8890,13 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
char *cond_end = NULL;
tok = skip_spaces (tok);
if ((*tok == '"' || *tok == ',') && rest)
{
*rest = savestring (tok, strlen (tok));
return;
}
end_tok = skip_to_space (tok);
toklen = end_tok - tok;
@ -8786,6 +8936,11 @@ find_condition_and_thread (char *tok, CORE_ADDR pc,
if (!valid_task_id (*task))
error (_("Unknown task %d."), *task);
}
else if (rest)
{
*rest = savestring (tok, strlen (tok));
tok += toklen;
}
else
error (_("Junk at end of arguments."));
}
@ -8853,7 +9008,8 @@ decode_static_tracepoint_spec (char **arg_p)
int
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 tempflag, enum bptype type_wanted,
int ignore_count,
@ -8975,16 +9131,22 @@ create_breakpoint (struct gdbarch *gdbarch,
if (parse_condition_and_thread)
{
char *rest;
/* Here we only parse 'arg' to separate condition
from thread number, so parsing in context of first
sal is OK. When setting the breakpoint we'll
re-parse it in context of each sal. */
cond_string = NULL;
thread = -1;
rest = NULL;
find_condition_and_thread (arg, lsal->sals.sals[0].pc, &cond_string,
&thread, &task);
&thread, &task, &rest);
if (cond_string)
make_cleanup (xfree, cond_string);
if (rest)
make_cleanup (xfree, rest);
if (rest)
extra_string = rest;
}
else
{
@ -8994,10 +9156,16 @@ create_breakpoint (struct gdbarch *gdbarch,
cond_string = xstrdup (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,
cond_string, type_wanted,
cond_string, extra_string, type_wanted,
tempflag ? disp_del : disp_donttouch,
thread, task, ignore_count, ops,
from_tty, enabled, internal, flags);
@ -9022,6 +9190,7 @@ create_breakpoint (struct gdbarch *gdbarch,
b->addr_string = copy_arg;
b->cond_string = NULL;
b->extra_string = NULL;
b->ignore_count = ignore_count;
b->disposition = tempflag ? disp_del : disp_donttouch;
b->condition_not_parsed = 1;
@ -9077,7 +9246,7 @@ break_command_1 (char *arg, int flag, int from_tty)
create_breakpoint (get_current_arch (),
arg,
NULL, 0, 1 /* parse arg */,
NULL, 0, NULL, 1 /* parse arg */,
tempflag, type_wanted,
0 /* Ignore count */,
pending_break_support,
@ -9242,6 +9411,29 @@ stopat_command (char *arg, int 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
ranged breakpoints. */
@ -10953,7 +11145,7 @@ handle_gnu_v3_exceptions (int tempflag, char *cond_string,
trigger_func_name = "__cxa_throw";
create_breakpoint (get_current_arch (),
trigger_func_name, cond_string, -1,
trigger_func_name, cond_string, -1, NULL,
0 /* condition and thread are valid. */,
tempflag, bp_breakpoint,
0,
@ -12182,6 +12374,7 @@ base_breakpoint_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *c,
struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
@ -12344,6 +12537,9 @@ bkpt_print_mention (struct breakpoint *b)
case bp_hardware_breakpoint:
printf_filtered (_("Hardware assisted breakpoint %d"), b->number);
break;
case bp_dprintf:
printf_filtered (_("Dprintf %d"), b->number);
break;
}
say_where (b);
@ -12384,6 +12580,7 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
@ -12393,7 +12590,8 @@ bkpt_create_breakpoints_sal (struct gdbarch *gdbarch,
int internal, unsigned flags)
{
create_breakpoints_sal_default (gdbarch, canonical, lsal,
cond_string, type_wanted,
cond_string, extra_string,
type_wanted,
disposition, thread, task,
ignore_count, ops, from_tty,
enabled, internal, flags);
@ -12705,6 +12903,7 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
@ -12714,7 +12913,8 @@ tracepoint_create_breakpoints_sal (struct gdbarch *gdbarch,
int internal, unsigned flags)
{
create_breakpoints_sal_default (gdbarch, canonical, lsal,
cond_string, type_wanted,
cond_string, extra_string,
type_wanted,
disposition, thread, task,
ignore_count, ops, from_tty,
enabled, internal, flags);
@ -12778,6 +12978,7 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
@ -12811,7 +13012,8 @@ strace_marker_create_breakpoints_sal (struct gdbarch *gdbarch,
tp = XCNEW (struct tracepoint);
init_breakpoint_sal (&tp->base, gdbarch, expanded,
addr_string, NULL,
cond_string, type_wanted, disposition,
cond_string, extra_string,
type_wanted, disposition,
thread, task, ignore_count, ops,
from_tty, enabled, internal, flags,
canonical->special_display);
@ -13438,13 +13640,17 @@ addr_string_to_sals (struct breakpoint *b, char *addr_string, int *found)
char *cond_string = 0;
int thread = -1;
int task = 0;
char *extra_string = NULL;
find_condition_and_thread (s, sals.sals[0].pc,
&cond_string, &thread, &task);
&cond_string, &thread, &task,
&extra_string);
if (cond_string)
b->cond_string = cond_string;
b->thread = thread;
b->task = task;
if (extra_string)
b->extra_string = extra_string;
b->condition_not_parsed = 0;
}
@ -13512,6 +13718,7 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch,
struct linespec_result *canonical,
struct linespec_sals *lsal,
char *cond_string,
char *extra_string,
enum bptype type_wanted,
enum bpdisp disposition,
int thread,
@ -13521,6 +13728,7 @@ create_breakpoints_sal_default (struct gdbarch *gdbarch,
int internal, unsigned flags)
{
create_breakpoints_sal (gdbarch, canonical, cond_string,
extra_string,
type_wanted, disposition,
thread, task, ignore_count, ops, from_tty,
enabled, internal, flags);
@ -14394,7 +14602,7 @@ trace_command (char *arg, int from_tty)
if (create_breakpoint (get_current_arch (),
arg,
NULL, 0, 1 /* parse arg */,
NULL, 0, NULL, 1 /* parse arg */,
0 /* tempflag */,
bp_tracepoint /* type_wanted */,
0 /* Ignore count */,
@ -14411,7 +14619,7 @@ ftrace_command (char *arg, int from_tty)
{
if (create_breakpoint (get_current_arch (),
arg,
NULL, 0, 1 /* parse arg */,
NULL, 0, NULL, 1 /* parse arg */,
0 /* tempflag */,
bp_fast_tracepoint /* type_wanted */,
0 /* Ignore count */,
@ -14439,7 +14647,7 @@ strace_command (char *arg, int from_tty)
if (create_breakpoint (get_current_arch (),
arg,
NULL, 0, 1 /* parse arg */,
NULL, 0, NULL, 1 /* parse arg */,
0 /* tempflag */,
bp_static_tracepoint /* type_wanted */,
0 /* Ignore count */,
@ -14504,7 +14712,8 @@ create_tracepoint_from_upload (struct uploaded_tp *utp)
if (!create_breakpoint (get_current_arch (),
addr_str,
utp->cond_string, -1, 0 /* parse cond/thread */,
utp->cond_string, -1, NULL,
0 /* parse cond/thread */,
0 /* tempflag */,
utp->type /* type_wanted */,
0 /* Ignore count */,
@ -15260,6 +15469,14 @@ initialize_breakpoint_ops (void)
ops->print_one = print_one_catch_solib;
ops->print_mention = print_mention_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
@ -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\
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;
observer_attach_about_to_proceed (breakpoint_about_to_proceed);

View File

@ -154,6 +154,13 @@ enum bptype
bp_fast_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. */
bp_jit_event,
@ -552,6 +559,7 @@ struct breakpoint_ops
void (*create_breakpoints_sal) (struct gdbarch *,
struct linespec_result *,
struct linespec_sals *, char *,
char *,
enum bptype, enum bpdisp, int, int,
int, const struct breakpoint_ops *,
int, int, int, unsigned);
@ -674,8 +682,9 @@ struct breakpoint
/* String form of the breakpoint condition (malloc'd), or NULL if
there is no condition. */
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
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,
char *cond_string, int thread,
char *extra_string,
int parse_condition_and_thread,
int tempflag, enum bptype wanted_type,
int ignore_count,

View File

@ -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>
* gdb.texinfo (Basic Python): Add description about the function

View File

@ -3341,6 +3341,7 @@ all breakpoints in that range are operated on.
* Disabling:: Disabling breakpoints
* Conditions:: Break conditions
* Break Commands:: Breakpoint command lists
* Dynamic Printf:: Dynamic printf
* Save Breakpoints:: How to save breakpoints in a file
* Static Probe Points:: Listing static probe points
* Error in Breakpoints:: ``Cannot insert breakpoints''
@ -4628,6 +4629,89 @@ cont
end
@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
@subsection How to save breakpoints to a file

View File

@ -164,6 +164,7 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
: (hardware ? bp_hardware_breakpoint : bp_breakpoint));
create_breakpoint (get_current_arch (), address, condition, thread,
NULL,
0 /* condition and thread are valid. */,
temp_p, type_wanted,
ignore_count,

View File

@ -622,7 +622,7 @@ bppy_init (PyObject *self, PyObject *args, PyObject *kwargs)
case bp_breakpoint:
{
create_breakpoint (python_gdbarch,
copy, NULL, -1,
copy, NULL, -1, NULL,
0,
0, bp_breakpoint,
0,

View File

@ -281,7 +281,7 @@ bpfinishpy_init (PyObject *self, PyObject *args, PyObject *kwargs)
addr_str = small_buf;
create_breakpoint (python_gdbarch,
addr_str, NULL, thread,
addr_str, NULL, thread, NULL,
0,
1 /*temp_flag*/,
bp_breakpoint,

View File

@ -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>
* gdb.trace/Makefile.in (PROGS): Add disconnected-tracing.

View 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;
}

View 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"