2013-05-21 Hui Zhu <hui@codesourcery.com>

* breakpoint.c (dprintf_breakpoint_ops): Remove its static.
	* breakpoint.h (dprintf_breakpoint_ops): Add extern.
	* mi/mi-cmd-break.c (ctype.h): New include.
	(gdb_obstack.h): New include.
	(mi_argv_to_format, mi_cmd_break_insert_1): New.
	(mi_cmd_break_insert): Call mi_cmd_break_insert_1.
	(mi_cmd_dprintf_insert): New.
	* mi/mi-cmds.c (mi_cmds): Add "dprintf-insert".
	* mi/mi-cmds.h (mi_cmd_dprintf_insert): New extern.

2013-05-21  Hui Zhu  <hui@codesourcery.com>

	* gdb.texinfo (GDB/MI Breakpoint Commands): Describe the
	"-dprintf-insert" command.

2013-05-21  Hui Zhu  <hui@codesourcery.com>

	* gdb.mi/Makefile.in (PROGS): Add "mi-dprintf".
	* gdb.mi/mi-dprintf.exp, gdb.mi/mi-dprintf.c: New.
This commit is contained in:
Hui Zhu 2013-05-21 04:18:55 +00:00
parent 624852650a
commit c5867ab65c
13 changed files with 452 additions and 23 deletions

View File

@ -1,3 +1,15 @@
2013-05-21 Hui Zhu <hui@codesourcery.com>
* breakpoint.c (dprintf_breakpoint_ops): Remove its static.
* breakpoint.h (dprintf_breakpoint_ops): Add extern.
* mi/mi-cmd-break.c (ctype.h): New include.
(gdb_obstack.h): New include.
(mi_argv_to_format, mi_cmd_break_insert_1): New.
(mi_cmd_break_insert): Call mi_cmd_break_insert_1.
(mi_cmd_dprintf_insert): New.
* mi/mi-cmds.c (mi_cmds): Add "dprintf-insert".
* mi/mi-cmds.h (mi_cmd_dprintf_insert): New extern.
2013-05-20 Tom Tromey <tromey@redhat.com>
* python/py-prettyprint.c (search_pp_list): Decref 'attr'.

View File

@ -70,6 +70,8 @@ show debug nios2
** The -trace-save MI command can optionally save trace buffer in Common
Trace Format now.
** The new command -dprintf-insert sets a dynamic printf breakpoint.
*** Changes in GDB 7.6
* Target record has been renamed to record-full.

View File

@ -301,7 +301,7 @@ struct breakpoint_ops bkpt_breakpoint_ops;
static struct breakpoint_ops bkpt_probe_breakpoint_ops;
/* Dynamic printf class type. */
static struct breakpoint_ops dprintf_breakpoint_ops;
struct breakpoint_ops dprintf_breakpoint_ops;
/* The style in which to perform a dynamic printf. This is a user
option because different output options have different tradeoffs;

View File

@ -1212,6 +1212,7 @@ extern void tbreak_command (char *, int);
extern struct breakpoint_ops base_breakpoint_ops;
extern struct breakpoint_ops bkpt_breakpoint_ops;
extern struct breakpoint_ops tracepoint_breakpoint_ops;
extern struct breakpoint_ops dprintf_breakpoint_ops;
extern void initialize_breakpoint_ops (void);

View File

@ -1,3 +1,8 @@
2013-05-21 Hui Zhu <hui@codesourcery.com>
* gdb.texinfo (GDB/MI Breakpoint Commands): Describe the
"-dprintf-insert" command.
2013-05-17 Doug Evans <dje@google.com>
* gdb.texinfo (Maintenance Commands): Update doc for

View File

@ -29789,6 +29789,84 @@ times="0"@}]@}
@c (gdb)
@end smallexample
@subheading The @code{-dprintf-insert} Command
@findex -dprintf-insert
@subsubheading Synopsis
@smallexample
-dprintf-insert [ -t ] [ -f ] [ -d ]
[ -c @var{condition} ] [ -i @var{ignore-count} ]
[ -p @var{thread-id} ] [ @var{location} ] [ @var{format} ]
[ @var{argument} ]
@end smallexample
@noindent
If specified, @var{location}, can be one of:
@itemize @bullet
@item @var{function}
@c @item +offset
@c @item -offset
@c @item @var{linenum}
@item @var{filename}:@var{linenum}
@item @var{filename}:function
@item *@var{address}
@end itemize
The possible optional parameters of this command are:
@table @samp
@item -t
Insert a temporary breakpoint.
@item -f
If @var{location} cannot be parsed (for example, if it
refers to unknown files or functions), create a pending
breakpoint. Without this flag, @value{GDBN} will report
an error, and won't create a breakpoint, if @var{location}
cannot be parsed.
@item -d
Create a disabled breakpoint.
@item -c @var{condition}
Make the breakpoint conditional on @var{condition}.
@item -i @var{ignore-count}
Set the ignore count of the breakpoint (@pxref{Conditions, ignore count})
to @var{ignore-count}.
@item -p @var{thread-id}
Restrict the breakpoint to the specified @var{thread-id}.
@end table
@subsubheading Result
@xref{GDB/MI Breakpoint Information}, for details on the format of the
resulting breakpoint.
@c An out-of-band breakpoint instead of part of the result?
@subsubheading @value{GDBN} Command
The corresponding @value{GDBN} command is @samp{dprintf}.
@subsubheading Example
@smallexample
(gdb)
4-dprintf-insert foo "At foo entry\n"
4^done,bkpt=@{number="1",type="dprintf",disp="keep",enabled="y",
addr="0x000000000040061b",func="foo",file="mi-dprintf.c",
fullname="mi-dprintf.c",line="25",thread-groups=["i1"],
times="0",script=@{"printf \"At foo entry\\n\"","continue"@},
original-location="foo"@}
(gdb)
5-dprintf-insert 26 "arg=%d, g=%d\n" arg g
5^done,bkpt=@{number="2",type="dprintf",disp="keep",enabled="y",
addr="0x000000000040062a",func="foo",file="mi-dprintf.c",
fullname="mi-dprintf.c",line="26",thread-groups=["i1"],
times="0",script=@{"printf \"arg=%d, g=%d\\n\", arg, g","continue"@},
original-location="mi-dprintf.c:26"@}
(gdb)
@end smallexample
@subheading The @code{-break-list} Command
@findex -break-list

View File

@ -30,6 +30,8 @@
#include "observer.h"
#include "mi-main.h"
#include "mi-cmd-break.h"
#include "gdb_obstack.h"
#include <ctype.h>
enum
{
@ -84,11 +86,83 @@ setup_breakpoint_reporting (void)
}
/* Implements the -break-insert command.
See the MI manual for the list of possible options. */
/* Convert arguments in ARGV to the string in "format",argv,argv...
and return it. */
void
mi_cmd_break_insert (char *command, char **argv, int argc)
static char *
mi_argv_to_format (char **argv, int argc)
{
int i;
struct obstack obstack;
char *ret;
obstack_init (&obstack);
/* Convert ARGV[OIND + 1] to format string and save to FORMAT. */
obstack_1grow (&obstack, '\"');
for (i = 0; i < strlen (argv[0]); i++)
{
switch (argv[0][i])
{
case '\\':
obstack_grow (&obstack, "\\\\", 2);
break;
case '\a':
obstack_grow (&obstack, "\\a", 2);
break;
case '\b':
obstack_grow (&obstack, "\\b", 2);
break;
case '\f':
obstack_grow (&obstack, "\\f", 2);
break;
case '\n':
obstack_grow (&obstack, "\\n", 2);
break;
case '\r':
obstack_grow (&obstack, "\\r", 2);
break;
case '\t':
obstack_grow (&obstack, "\\t", 2);
break;
case '\v':
obstack_grow (&obstack, "\\v", 2);
break;
default:
if (isprint (argv[0][i]))
obstack_grow (&obstack, argv[0] + i, 1);
else
{
char tmp[5];
sprintf (tmp, "\\%o", (unsigned char) argv[0][i]);
obstack_grow (&obstack, tmp, strlen (tmp));
}
break;
}
}
obstack_1grow (&obstack, '\"');
/* Apply other argv to FORMAT. */
for (i = 1; i < argc; i++)
{
obstack_1grow (&obstack, ',');
obstack_grow (&obstack, argv[i], strlen (argv[i]));
}
obstack_1grow (&obstack, '\0');
ret = xstrdup (obstack_finish (&obstack));
obstack_free (&obstack, NULL);
return ret;
}
/* Insert breakpoint.
If dprintf is true, it will insert dprintf.
If not, it will insert other type breakpoint. */
static void
mi_cmd_break_insert_1 (int dprintf, char *command, char **argv, int argc)
{
char *address = NULL;
int hardware = 0;
@ -99,9 +173,10 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
int pending = 0;
int enabled = 1;
int tracepoint = 0;
struct cleanup *back_to;
struct cleanup *back_to = make_cleanup (null_cleanup, NULL);
enum bptype type_wanted;
struct breakpoint_ops *ops;
char *extra_string = NULL;
enum opt
{
@ -163,35 +238,79 @@ mi_cmd_break_insert (char *command, char **argv, int argc)
}
if (oind >= argc)
error (_("-break-insert: Missing <location>"));
if (oind < argc - 1)
error (_("-break-insert: Garbage following <location>"));
error (_("-%s-insert: Missing <location>"),
dprintf ? "dprintf" : "break");
address = argv[oind];
if (dprintf)
{
int format_num = oind + 1;
if (hardware || tracepoint)
error (_("-dprintf-insert: does not support -h or -a"));
if (format_num >= argc)
error (_("-dprintf-insert: Missing <format>"));
extra_string = mi_argv_to_format (argv + format_num, argc - format_num);
make_cleanup (xfree, extra_string);
}
else
{
if (oind < argc - 1)
error (_("-break-insert: Garbage following <location>"));
}
/* Now we have what we need, let's insert the breakpoint! */
back_to = setup_breakpoint_reporting ();
setup_breakpoint_reporting ();
/* Note that to request a fast tracepoint, the client uses the
"hardware" flag, although there's nothing of hardware related to
fast tracepoints -- one can implement slow tracepoints with
hardware breakpoints, but fast tracepoints are always software.
"fast" is a misnomer, actually, "jump" would be more appropriate.
A simulator or an emulator could conceivably implement fast
regular non-jump based tracepoints. */
type_wanted = (tracepoint
? (hardware ? bp_fast_tracepoint : bp_tracepoint)
: (hardware ? bp_hardware_breakpoint : bp_breakpoint));
ops = tracepoint ? &tracepoint_breakpoint_ops : &bkpt_breakpoint_ops;
if (tracepoint)
{
/* Note that to request a fast tracepoint, the client uses the
"hardware" flag, although there's nothing of hardware related to
fast tracepoints -- one can implement slow tracepoints with
hardware breakpoints, but fast tracepoints are always software.
"fast" is a misnomer, actually, "jump" would be more appropriate.
A simulator or an emulator could conceivably implement fast
regular non-jump based tracepoints. */
type_wanted = hardware ? bp_fast_tracepoint : bp_tracepoint;
ops = &tracepoint_breakpoint_ops;
}
else if (dprintf)
{
type_wanted = bp_dprintf;
ops = &dprintf_breakpoint_ops;
}
else
{
type_wanted = hardware ? bp_hardware_breakpoint : bp_breakpoint;
ops = &bkpt_breakpoint_ops;
}
create_breakpoint (get_current_arch (), address, condition, thread,
NULL,
extra_string,
0 /* condition and thread are valid. */,
temp_p, type_wanted,
ignore_count,
pending ? AUTO_BOOLEAN_TRUE : AUTO_BOOLEAN_FALSE,
ops, 0, enabled, 0, 0);
do_cleanups (back_to);
}
/* Implements the -break-insert command.
See the MI manual for the list of possible options. */
void
mi_cmd_break_insert (char *command, char **argv, int argc)
{
mi_cmd_break_insert_1 (0, command, argv, argc);
}
/* Implements the -dprintf-insert command.
See the MI manual for the list of possible options. */
void
mi_cmd_dprintf_insert (char *command, char **argv, int argc)
{
mi_cmd_break_insert_1 (1, command, argv, argc);
}
enum wp_type

View File

@ -61,6 +61,8 @@ static struct mi_cmd mi_cmds[] =
DEF_MI_CMD_CLI ("break-info", "info break", 1),
DEF_MI_CMD_MI_1 ("break-insert", mi_cmd_break_insert,
&mi_suppress_notification.breakpoint),
DEF_MI_CMD_MI_1 ("dprintf-insert", mi_cmd_dprintf_insert,
&mi_suppress_notification.breakpoint),
DEF_MI_CMD_CLI ("break-list", "info break", 0),
DEF_MI_CMD_MI_1 ("break-passcount", mi_cmd_break_passcount,
&mi_suppress_notification.breakpoint),

View File

@ -39,6 +39,7 @@ typedef void (mi_cmd_argv_ftype) (char *command, char **argv, int argc);
extern mi_cmd_argv_ftype mi_cmd_ada_task_info;
extern mi_cmd_argv_ftype mi_cmd_add_inferior;
extern mi_cmd_argv_ftype mi_cmd_break_insert;
extern mi_cmd_argv_ftype mi_cmd_dprintf_insert;
extern mi_cmd_argv_ftype mi_cmd_break_commands;
extern mi_cmd_argv_ftype mi_cmd_break_passcount;
extern mi_cmd_argv_ftype mi_cmd_break_watch;

View File

@ -1,3 +1,8 @@
2013-05-21 Hui Zhu <hui@codesourcery.com>
* gdb.mi/Makefile.in (PROGS): Add "mi-dprintf".
* gdb.mi/mi-dprintf.exp, gdb.mi/mi-dprintf.c: New.
2013-05-20 Doug Evans <dje@google.com>
* lib/dwarf.exp (Dwarf): New variable _abbrev_section.

View File

@ -3,7 +3,7 @@ srcdir = @srcdir@
PROGS = basics c_variable cpp_variable var-cmd dw2-ref-missing-frame \
gdb669-pthreads gdb701 gdb792 mi-async mi-basics mi-break \
mi-cli mi-console mi-disassemble mi-eval mi-file \
mi-cli mi-console mi-disassemble mi-dprintf mi-eval mi-file \
mi-file-transfer mi-non-stop mi-non-stop-exit \
mi-ns-stale-regcache mi-nsintrall mi-nsmoribund mi-nsthrexec \
mi-pending mi-pthreads mi-read-memory mi-regs mi-return \

View File

@ -0,0 +1,59 @@
/* This testcase is part of GDB, the GNU debugger.
Copyright (C) 2013 Free Software Foundation, Inc.
Contributed by Hui Zhu <hui@codesourcery.com>
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>
#include <stdlib.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 %d\n", loc);
fprintf (stderr, "also to stderr %d\n", loc);
foo (loc++);
foo (loc++);
foo (loc++);
return g;
}
/* Make sure function 'malloc' is linked into program. On some bare-metal
port, if we don't use 'malloc', it will not be linked in program. 'malloc'
is needed, otherwise we'll see such error message
evaluation of this expression requires the program to have a function
"malloc". */
void
bar (void)
{
void *p = malloc (16);
free (p);
}

View File

@ -0,0 +1,145 @@
# Copyright (C) 2013 Free Software Foundation, Inc.
# Contributed by Hui Zhu <hui@codesourcery.com>
# 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/>.
load_lib mi-support.exp
set MIFLAGS "-i=mi"
gdb_exit
if [mi_gdb_start] {
continue
}
standard_testfile
if {[build_executable $testfile.exp $testfile $srcfile {debug}] == -1} {
untested "failed to compile $testfile"
return -1
}
mi_delete_breakpoints
set bp_location1 [gdb_get_line_number "set breakpoint 1 here"]
set dp_location1 [gdb_get_line_number "set dprintf 1 here"]
mi_run_to_main
mi_gdb_test "1-dprintf-insert" \
"1\\^error,msg=\"-dprintf-insert: Missing <location>\"" "mi insert without location"
mi_gdb_test "2-dprintf-insert foo" \
"2\\^error,msg=\"-dprintf-insert: Missing <format>\"" "mi insert breakpoint without format string"
mi_gdb_test "3-dprintf-insert 29" \
"3\\^error,msg=\"-dprintf-insert: Missing <format>\"" "mi insert second breakpoint without format string"
mi_gdb_test "-break-insert main" ".*" "mi insert breakpoint main"
mi_delete_breakpoints
mi_gdb_test "4-dprintf-insert foo \"At foo entry\\n\"" \
"4\\^done,bkpt=\{number=\".*\",type=\"dprintf\".*func=\"foo\",file=\".*mi-dprintf.c\",fullname=\".*mi-dprintf.c\",line=\".*\".*" "mi insert dprintf foo"
mi_gdb_test "5-dprintf-insert $dp_location1 \"arg=%d, g=%d\\n\" arg g" \
"5\\^done,bkpt=\{number=\".*\",type=\"dprintf\".*func=\"foo\",file=\".*mi-dprintf.c\",fullname=\".*mi-dprintf.c\",line=\"$dp_location1\".*" \
"mi insert dprintf dp_location1"
mi_gdb_test "6-break-info" \
"6\\^done,BreakpointTable=\{nr_rows=\".\",nr_cols=\".\",hdr=\\\[\{width=\".*\",alignment=\".*\",col_name=\"number\",colhdr=\"Num\"\},\{width=\".*\",alignment=\".*\",col_name=\"type\",colhdr=\"Type\"\},\{width=\".*\",alignment=\".*\",col_name=\"disp\",colhdr=\"Disp\"\},\{width=\".*\",alignment=\".*\",col_name=\"enabled\",colhdr=\"Enb\"\},\{width=\".*\",alignment=\".*\",col_name=\"addr\",colhdr=\"Address\"\},\{width=\".*\",alignment=\".*\",col_name=\"what\",colhdr=\"What\"\}\\\],body=\\\[bkpt=\{number=\"3\",type=\"dprintf\".*func=\"foo\",file=\".*mi-dprintf.c\",fullname=\".*mi-dprintf.c\",line=\".*\".*,bkpt=\{number=\".*\",type=\"dprintf\".*func=\"foo\",file=\".*mi-dprintf.c\",fullname=\".*mi-dprintf.c\",line=\"$dp_location1\".*" \
"mi info dprintf"
mi_gdb_test "-break-insert $bp_location1" ".*" "mi insert breakpoint bp_location1"
proc mi_continue_dprintf {args} {
with_test_prefix $args {
global mi_gdb_prompt
mi_run_cmd
set msg "mi 1st dprintf"
gdb_expect {
-re ".*At foo entry.*arg=1234, g=1234.*" {
pass $msg
}
-re ".*$mi_gdb_prompt$" {
fail $msg
}
timeout {
fail $msg
}
}
mi_expect_stop ".*" ".*" ".*" ".*" ".*" "" "$msg stop"
set msg "mi 2nd dprintf"
mi_send_resuming_command "exec-continue" "$msg continue"
gdb_expect {
-re ".*At foo entry.*arg=1235, g=2222.*" {
pass $msg
}
-re ".*$mi_gdb_prompt$" {
fail $msg
}
timeout {
fail $msg
}
}
}
}
mi_continue_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.
mi_gdb_test "set dprintf-style call" ".*" "mi set dprintf style to call"
mi_continue_dprintf "call"
mi_gdb_test "set dprintf-function fprintf" ".*" "mi set dprintf-channel stderr"
mi_gdb_test "set dprintf-channel stderr" ".*" "mi set dprintf channel"
mi_continue_dprintf "fprintf"
}
set target_can_dprintf 0
set msg "set dprintf style to agent"
send_gdb "set dprintf-style agent\n"
gdb_expect {
-re "warning: Target cannot run dprintf commands, falling back to GDB printf.*$mi_gdb_prompt$" {
unsupported "$msg"
}
-re ".*done.*$mi_gdb_prompt$" {
set target_can_dprintf 1
pass "$msg"
}
-re ".*$mi_gdb_prompt$" {
fail "$msg"
}
timeout {
fail "$msg"
}
}
if $target_can_dprintf {
mi_run_cmd
mi_gdb_test "continue" ".*breakpoint-hit.*func=\"foo\".*" "mi 1st dprintf, agent"
mi_gdb_test "continue" ".*breakpoint-hit.*func=\"foo\".*" "mi 2nd dprintf, agent"
mi_gdb_test "6-break-info" ".*modified.*" "mi info dprintf second time"
}
mi_gdb_test "set dprintf-style foobar" ".*error.*" "mi set dprintf style to an unrecognized type"