* [PATCH] Tracepoint source strings
@ 2010-03-25 22:01 Stan Shebs
2010-03-26 8:24 ` Eli Zaretskii
2010-03-30 13:18 ` Pedro Alves
0 siblings, 2 replies; 7+ messages in thread
From: Stan Shebs @ 2010-03-25 22:01 UTC (permalink / raw)
To: gdb-patches
[-- Attachment #1: Type: text/plain, Size: 2060 bytes --]
This patch is another step towards the promised land of
accurately-restored tracepoint definitions. For those just tuning in,
the problem is that in both the disconnected tracing and the trace file
cases, it's very difficult to use tracepoints if the definitions in GDB
do not match up with what was used to create the trace frames on the
target or in the file. This patch takes a more audacious approach that
seems to work well in practice; it literally downloads and uploads the
original source form of the tracepoint, whitespace and all. As freaky
as it sounds, it works because if the source strings don't parse
(because the executable has changed, for instance), then there is almost
no chance that the trace frame data is going to be meaningful at the
symbolic level.
This is not quite the end of the story, the heuristic matchup of new/old
tracepoints still needs work, and there are some minor patches still
queued up. For testing, I'll add to the tfile.exp test after
incorporating Pedro's feedback from the previous patch. I'll hold off
committing this for a couple days in case anybody has comments.
Stan
2010-03-25 Stan Shebs <stan@codesourcery.com>
* tracepoint.h (struct uploaded_string): New struct.
(struct uploaded_tp): New fields for source strings.
* breakpoint.c (this_utp, next_cmd): New globals.
(read_uploaded_action): New function.
(create_tracepoint_from_upload): Fill in more parts
of a tracepoint.
* tracepoint.c (encode_source_string): New function.
(trace_save): Write out source strings, fix error checks.
(parse_tracepoint_definition): Add source string parsing.
* remote.c (PACKET_TracepointSource): New packet type.
(remote_download_command_source): New function.
(remote_download_tracepoint): Download source pieces also.
(_initialize_remote): Add packet config command.
* gdb.texinfo (Tracepoint Packets): Describe QTDPsrc.
(General Query Packets): Describe TracepointSource.
[-- Attachment #2: tpsrc-patch-1 --]
[-- Type: text/plain, Size: 22314 bytes --]
Index: breakpoint.c
===================================================================
RCS file: /cvs/src/src/gdb/breakpoint.c,v
retrieving revision 1.468
diff -p -r1.468 breakpoint.c
*** breakpoint.c 25 Mar 2010 20:48:52 -0000 1.468
--- breakpoint.c 25 Mar 2010 21:31:44 -0000
*************** ftrace_command (char *arg, int from_tty)
*** 10364,10369 ****
--- 10364,10389 ----
set_tracepoint_count (breakpoint_count);
}
+ /* Set up a fake reader function that gets command lines from a linked
+ list that was acquired during tracepoint uploading. */
+
+ static struct uploaded_tp *this_utp;
+ static struct uploaded_string *next_cmd;
+
+ static char *
+ read_uploaded_action (void)
+ {
+ char *rslt;
+
+ if (!next_cmd)
+ return NULL;
+
+ rslt = next_cmd->str;
+ next_cmd = next_cmd->next;
+
+ return rslt;
+ }
+
/* Given information about a tracepoint as recorded on a target (which
can be either a live system or a trace file), attempt to create an
equivalent GDB tracepoint. This is not a reliable process, since
*************** ftrace_command (char *arg, int from_tty)
*** 10373,10387 ****
struct breakpoint *
create_tracepoint_from_upload (struct uploaded_tp *utp)
{
! char buf[100];
struct breakpoint *tp;
! /* In the absence of a source location, fall back to raw address. */
! sprintf (buf, "*%s", paddress (get_current_arch(), utp->addr));
if (!create_breakpoint (get_current_arch (),
! buf,
! NULL, 0, 1 /* parse arg */,
0 /* tempflag */,
(utp->type == bp_fast_tracepoint) /* hardwareflag */,
1 /* traceflag */,
--- 10393,10423 ----
struct breakpoint *
create_tracepoint_from_upload (struct uploaded_tp *utp)
{
! char *addr_str, small_buf[100];
struct breakpoint *tp;
! if (utp->at_string)
! addr_str = utp->at_string;
! else
! {
! /* In the absence of a source location, fall back to raw
! address. Since there is no way to confirm that the address
! means the same thing as when the trace was started, warn the
! user. */
! warning ("Uploaded tracepoint %d has no source location, using raw address",
! utp->number);
! sprintf (small_buf, "*%s", hex_string (utp->addr));
! addr_str = small_buf;
! }
!
! /* There's not much we can do with a sequence of bytecodes. */
! if (utp->cond && !utp->cond_string)
! warning ("Uploaded tracepoint %d condition has no source form, ignoring it",
! utp->number);
if (!create_breakpoint (get_current_arch (),
! addr_str,
! utp->cond_string, -1, 0 /* parse cond/thread */,
0 /* tempflag */,
(utp->type == bp_fast_tracepoint) /* hardwareflag */,
1 /* traceflag */,
*************** create_tracepoint_from_upload (struct up
*** 10394,10423 ****
set_tracepoint_count (breakpoint_count);
tp = get_tracepoint (tracepoint_count);
gdb_assert (tp != NULL);
if (utp->pass > 0)
{
! sprintf (buf, "%d %d", utp->pass, tp->number);
! trace_pass_command (buf, 0);
}
! if (utp->cond)
{
! printf_filtered ("Want to restore a condition\n");
! }
! if (utp->numactions > 0)
! {
! printf_filtered ("Want to restore action list\n");
! }
! if (utp->num_step_actions > 0)
! {
! printf_filtered ("Want to restore action list\n");
}
return tp;
}
--- 10430,10464 ----
set_tracepoint_count (breakpoint_count);
+ /* Get the tracepoint we just created. */
tp = get_tracepoint (tracepoint_count);
gdb_assert (tp != NULL);
if (utp->pass > 0)
{
! sprintf (small_buf, "%d %d", utp->pass, tp->number);
! trace_pass_command (small_buf, 0);
}
! /* If we have uploaded versions of the original commands, set up a
! special-purpose "reader" function and call the usual command line
! reader, then pass the result to the breakpoint command-setting
! function. */
! if (utp->cmd_strings)
{
! struct command_line *cmd_list;
! this_utp = utp;
! next_cmd = utp->cmd_strings;
! cmd_list = read_command_lines_1 (read_uploaded_action, 1, NULL, NULL);
!
! breakpoint_set_commands (tp, cmd_list);
}
+ else if (utp->numactions > 0 || utp->num_step_actions > 0)
+ warning ("Uploaded tracepoint %d actions have no source form, ignoring them",
+ utp->number);
return tp;
}
Index: remote.c
===================================================================
RCS file: /cvs/src/src/gdb/remote.c,v
retrieving revision 1.394
diff -p -r1.394 remote.c
*** remote.c 24 Mar 2010 01:12:13 -0000 1.394
--- remote.c 25 Mar 2010 21:31:44 -0000
*************** enum {
*** 1154,1159 ****
--- 1154,1160 ----
PACKET_FastTracepoints,
PACKET_bc,
PACKET_bs,
+ PACKET_TracepointSource,
PACKET_MAX
};
*************** static struct protocol_feature remote_pr
*** 3462,3467 ****
--- 3463,3470 ----
PACKET_bc },
{ "ReverseStep", PACKET_DISABLE, remote_supported_packet,
PACKET_bs },
+ { "TracepointSource", PACKET_DISABLE, remote_supported_packet,
+ PACKET_TracepointSource },
};
static void
*************** free_actions_list (char **actions_list)
*** 9267,9278 ****
xfree (actions_list);
}
static void
remote_download_tracepoint (struct breakpoint *t)
{
struct bp_location *loc;
CORE_ADDR tpaddr;
! char tmp[40];
char buf[2048];
char **tdp_actions;
char **stepping_actions;
--- 9270,9319 ----
xfree (actions_list);
}
+ /* Recursive routine to walk through command list including loops, and
+ download packets for each command. */
+
+ static void
+ remote_download_command_source (int num, ULONGEST addr,
+ struct command_line *cmds)
+ {
+ struct remote_state *rs = get_remote_state ();
+ struct command_line *cmd;
+
+ for (cmd = cmds; cmd; cmd = cmd->next)
+ {
+ QUIT; /* allow user to bail out with ^C */
+ strcpy (rs->buf, "QTDPsrc:");
+ encode_source_string (num, addr, "cmd", cmd->line,
+ rs->buf + strlen (rs->buf));
+ putpkt (rs->buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ warning (_("Target does not support source download."));
+
+ if (cmd->control_type == while_control
+ || cmd->control_type == while_stepping_control)
+ {
+ remote_download_command_source (num, addr, *cmd->body_list);
+
+ QUIT; /* allow user to bail out with ^C */
+ strcpy (rs->buf, "QTDPsrc:");
+ encode_source_string (num, addr, "cmd", "end",
+ rs->buf + strlen (rs->buf));
+ putpkt (rs->buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ warning (_("Target does not support source download."));
+ }
+ }
+ }
+
static void
remote_download_tracepoint (struct breakpoint *t)
{
struct bp_location *loc;
CORE_ADDR tpaddr;
! char addrbuf[40];
char buf[2048];
char **tdp_actions;
char **stepping_actions;
*************** remote_download_tracepoint (struct break
*** 9293,9301 ****
(void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
tpaddr = loc->address;
! sprintf_vma (tmp, (loc ? tpaddr : 0));
sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
! tmp, /* address */
(t->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
/* Fast tracepoints are mostly handled by the target, but we can
--- 9334,9342 ----
(void) make_cleanup (free_actions_list_cleanup_wrapper, stepping_actions);
tpaddr = loc->address;
! sprintf_vma (addrbuf, tpaddr);
sprintf (buf, "QTDP:%x:%s:%c:%lx:%x", t->number,
! addrbuf, /* address */
(t->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
/* Fast tracepoints are mostly handled by the target, but we can
*************** remote_download_tracepoint (struct break
*** 9352,9360 ****
if (strcmp (target_buf, "OK"))
error (_("Target does not support tracepoints."));
- if (!t->commands && !*default_collect)
- continue;
-
/* do_single_steps (t); */
if (tdp_actions)
{
--- 9393,9398 ----
*************** remote_download_tracepoint (struct break
*** 9362,9368 ****
{
QUIT; /* allow user to bail out with ^C */
sprintf (buf, "QTDP:-%x:%s:%s%c",
! t->number, tmp, /* address */
tdp_actions[ndx],
((tdp_actions[ndx + 1] || stepping_actions)
? '-' : 0));
--- 9400,9406 ----
{
QUIT; /* allow user to bail out with ^C */
sprintf (buf, "QTDP:-%x:%s:%s%c",
! t->number, addrbuf, /* address */
tdp_actions[ndx],
((tdp_actions[ndx + 1] || stepping_actions)
? '-' : 0));
*************** remote_download_tracepoint (struct break
*** 9379,9385 ****
{
QUIT; /* allow user to bail out with ^C */
sprintf (buf, "QTDP:-%x:%s:%s%s%s",
! t->number, tmp, /* address */
((ndx == 0) ? "S" : ""),
stepping_actions[ndx],
(stepping_actions[ndx + 1] ? "-" : ""));
--- 9417,9423 ----
{
QUIT; /* allow user to bail out with ^C */
sprintf (buf, "QTDP:-%x:%s:%s%s%s",
! t->number, addrbuf, /* address */
((ndx == 0) ? "S" : ""),
stepping_actions[ndx],
(stepping_actions[ndx + 1] ? "-" : ""));
*************** remote_download_tracepoint (struct break
*** 9390,9395 ****
--- 9428,9460 ----
error (_("Error on target while setting tracepoints."));
}
}
+
+ if (remote_protocol_packets[PACKET_TracepointSource].support == PACKET_ENABLE)
+ {
+ if (t->addr_string)
+ {
+ strcpy (buf, "QTDPsrc:");
+ encode_source_string (t->number, loc->address,
+ "at", t->addr_string, buf + strlen (buf));
+ putpkt (buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ warning (_("Target does not support source download."));
+ }
+ if (t->cond_string)
+ {
+ strcpy (buf, "QTDPsrc:");
+ encode_source_string (t->number, loc->address,
+ "cond", t->cond_string, buf + strlen (buf));
+ putpkt (buf);
+ remote_get_noisy_reply (&target_buf, &target_buf_size);
+ if (strcmp (target_buf, "OK"))
+ warning (_("Target does not support source download."));
+ }
+ remote_download_command_source (t->number, loc->address,
+ t->commands->commands);
+ }
+
do_cleanups (old_chain);
}
}
*************** Show the maximum size of the address (in
*** 10231,10236 ****
--- 10296,10304 ----
add_packet_config_cmd (&remote_protocol_packets[PACKET_FastTracepoints],
"FastTracepoints", "fast-tracepoints", 0);
+ add_packet_config_cmd (&remote_protocol_packets[PACKET_TracepointSource],
+ "TracepointSource", "TracepointSource", 0);
+
/* Keep the old ``set remote Z-packet ...'' working. Each individual
Z sub-packet has its own set and show commands, but users may
have sets to this variable in their .gdbinit files (or in their
Index: tracepoint.c
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.c,v
retrieving revision 1.155
diff -p -r1.155 tracepoint.c
*** tracepoint.c 24 Mar 2010 21:12:18 -0000 1.155
--- tracepoint.c 25 Mar 2010 21:31:44 -0000
*************** trace_dump_command (char *args, int from
*** 2403,2408 ****
--- 2403,2421 ----
discard_cleanups (old_cleanups);
}
+ /* Encode a piece of a tracepoint's source-level definition in a form
+ that is suitable for both protocol and saving in files. */
+ /* This version does not make multiple packets for long strings. FIXME */
+
+ void
+ encode_source_string (int tpnum, ULONGEST addr,
+ char *srctype, char *src, char *buf)
+ {
+ sprintf (buf, "%x:%s:%s:%x:%x:",
+ tpnum, phex_nz (addr, sizeof (addr)), srctype, 0, (int) strlen (src));
+ bin2hex (src, buf + strlen (buf), 0);
+ }
+
extern int trace_regblock_size;
/* Save tracepoint data to file named FILENAME. If TARGET_DOES_SAVE is
*************** trace_save (const char *filename, int ta
*** 2420,2425 ****
--- 2433,2439 ----
struct uploaded_tp *uploaded_tps = NULL, *utp;
struct uploaded_tsv *uploaded_tsvs = NULL, *utsv;
int a;
+ struct uploaded_string *cmd;
LONGEST gotten = 0;
ULONGEST offset = 0;
#define MAX_TRACE_UPLOAD 2000
*************** trace_save (const char *filename, int ta
*** 2454,2460 ****
binary file, plus a hint as what this file is, and a version
number in case of future needs. */
written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
! if (written < 8)
perror_with_name (pathname);
/* Write descriptive info. */
--- 2468,2474 ----
binary file, plus a hint as what this file is, and a version
number in case of future needs. */
written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
! if (written < 1)
perror_with_name (pathname);
/* Write descriptive info. */
*************** trace_save (const char *filename, int ta
*** 2529,2534 ****
--- 2543,2565 ----
fprintf (fp, "tp S%x:%s:%s\n",
utp->number, phex_nz (utp->addr, sizeof (utp->addr)),
utp->step_actions[a]);
+ if (utp->at_string)
+ {
+ encode_source_string (utp->number, utp->addr,
+ "at", utp->at_string, buf);
+ fprintf (fp, "tp Z%s\n", buf);
+ }
+ if (utp->cond_string)
+ {
+ encode_source_string (utp->number, utp->addr,
+ "cond", utp->cond_string, buf);
+ fprintf (fp, "tp Z%s\n", buf);
+ }
+ for (cmd = utp->cmd_strings; cmd; cmd = cmd->next)
+ {
+ encode_source_string (utp->number, utp->addr, "cmd", cmd->str, buf);
+ fprintf (fp, "tp Z%s\n", buf);
+ }
}
free_uploaded_tps (&uploaded_tps);
*************** trace_save (const char *filename, int ta
*** 2548,2561 ****
if (gotten == 0)
break;
written = fwrite (buf, gotten, 1, fp);
! if (written < gotten)
perror_with_name (pathname);
offset += gotten;
}
! /* Mark the end of trace data. */
written = fwrite (&gotten, 4, 1, fp);
! if (written < 4)
perror_with_name (pathname);
do_cleanups (cleanup);
--- 2579,2592 ----
if (gotten == 0)
break;
written = fwrite (buf, gotten, 1, fp);
! if (written < 1)
perror_with_name (pathname);
offset += gotten;
}
! /* Mark the end of trace data. (We know that gotten is 0 at this point.) */
written = fwrite (&gotten, 4, 1, fp);
! if (written < 1)
perror_with_name (pathname);
do_cleanups (cleanup);
*************** Status line: '%s'\n"), p, line);
*** 3197,3214 ****
}
}
! /* Given a line of text defining a tracepoint or tracepoint action, parse
! it into an "uploaded tracepoint". */
void
parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
{
char *p;
char piece;
! ULONGEST num, addr, step, pass, orig_size, xlen;
! int enabled, i;
enum bptype type;
! char *cond;
struct uploaded_tp *utp = NULL;
p = line;
--- 3228,3245 ----
}
}
! /* Given a line of text defining a part of a tracepoint, parse it into
! an "uploaded tracepoint". */
void
parse_tracepoint_definition (char *line, struct uploaded_tp **utpp)
{
char *p;
char piece;
! ULONGEST num, addr, step, pass, orig_size, xlen, start;
! int enabled, i, end;
enum bptype type;
! char *cond, *srctype, *src, *buf;
struct uploaded_tp *utp = NULL;
p = line;
*************** parse_tracepoint_definition (char *line,
*** 3268,3276 ****
utp = get_uploaded_tp (num, addr, utpp);
utp->step_actions[utp->num_step_actions++] = xstrdup (p);
}
else
{
! error ("Invalid tracepoint piece");
}
}
--- 3299,3347 ----
utp = get_uploaded_tp (num, addr, utpp);
utp->step_actions[utp->num_step_actions++] = xstrdup (p);
}
+ else if (piece == 'Z')
+ {
+ /* Parse a chunk of source form definition. */
+ utp = get_uploaded_tp (num, addr, utpp);
+ srctype = p;
+ p = strchr (p, ':');
+ p++; /* skip a colon */
+ p = unpack_varlen_hex (p, &start);
+ p++; /* skip a colon */
+ p = unpack_varlen_hex (p, &xlen);
+ p++; /* skip a colon */
+
+ buf = alloca (strlen (line));
+
+ end = hex2bin (p, (gdb_byte *) buf, strlen (p) / 2);
+ buf[end] = '\0';
+
+ if (strncmp (srctype, "at:", strlen ("at:")) == 0)
+ utp->at_string = xstrdup (buf);
+ else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
+ utp->cond_string = xstrdup (buf);
+ else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
+ {
+ /* FIXME consider using a vector? */
+ struct uploaded_string *last, *newlast;
+ newlast = (struct uploaded_string *) xmalloc (sizeof (struct uploaded_string));
+ newlast->str = xstrdup (buf);
+ newlast->next = NULL;
+ if (utp->cmd_strings)
+ {
+ for (last = utp->cmd_strings; last->next; last = last->next)
+ ;
+ last->next = newlast;
+ }
+ else
+ utp->cmd_strings = newlast;
+ }
+ }
else
{
! /* Don't error out, the target might be sending us optional
! info that we don't care about. */
! warning ("Unrecognized tracepoint piece '%c', ignoring", piece);
}
}
Index: tracepoint.h
===================================================================
RCS file: /cvs/src/src/gdb/tracepoint.h,v
retrieving revision 1.29
diff -p -r1.29 tracepoint.h
*** tracepoint.h 23 Mar 2010 22:05:45 -0000 1.29
--- tracepoint.h 25 Mar 2010 21:31:44 -0000
*************** extern char *default_collect;
*** 116,122 ****
/* Struct to collect random info about tracepoints on the target. */
! struct uploaded_tp {
int number;
enum bptype type;
ULONGEST addr;
--- 116,129 ----
/* Struct to collect random info about tracepoints on the target. */
! struct uploaded_string
! {
! char *str;
! struct uploaded_string *next;
! };
!
! struct uploaded_tp
! {
int number;
enum bptype type;
ULONGEST addr;
*************** struct uploaded_tp {
*** 129,140 ****
char *actions[100];
int num_step_actions;
char *step_actions[100];
struct uploaded_tp *next;
};
/* Struct recording info about trace state variables on the target. */
! struct uploaded_tsv {
const char *name;
int number;
LONGEST initial_value;
--- 136,158 ----
char *actions[100];
int num_step_actions;
char *step_actions[100];
+
+ /* The original string defining the location of the tracepoint. */
+ char *at_string;
+
+ /* The original string defining the tracepoint's condition. */
+ char *cond_string;
+
+ /* List of original strings defining the tracepoint's actions. */
+ struct uploaded_string *cmd_strings;
+
struct uploaded_tp *next;
};
/* Struct recording info about trace state variables on the target. */
! struct uploaded_tsv
! {
const char *name;
int number;
LONGEST initial_value;
*************** extern void while_stepping_pseudocommand
*** 160,165 ****
--- 178,186 ----
extern struct trace_state_variable *find_trace_state_variable (const char *name);
extern struct trace_state_variable *create_trace_state_variable (const char *name);
+ extern void encode_source_string (int num, ULONGEST addr,
+ char *srctype, char *src, char *buf);
+
extern void parse_trace_status (char *line, struct trace_status *ts);
extern void parse_tracepoint_definition (char *line, struct uploaded_tp **utpp);
Index: doc/gdb.texinfo
===================================================================
RCS file: /cvs/src/src/gdb/doc/gdb.texinfo,v
retrieving revision 1.683
diff -p -r1.683 gdb.texinfo
*** doc/gdb.texinfo 24 Mar 2010 21:24:08 -0000 1.683
--- doc/gdb.texinfo 25 Mar 2010 21:31:45 -0000
*************** These are the currently defined stub fea
*** 30713,30718 ****
--- 30713,30723 ----
@tab @samp{-}
@tab No
+ @item @samp{TracepointSource}
+ @tab No
+ @tab @samp{-}
+ @tab No
+
@end multitable
These are the currently defined stub features, in more detail:
*************** The remote stub accepts and implements t
*** 30806,30811 ****
--- 30811,30820 ----
The remote stub accepts and implements the reverse step packet
(@pxref{bs}).
+ @item TracepointSource
+ The remote stub understands the @samp{QTDPsrc} packet that supplies
+ the source form of tracepoint definitions.
+
@end table
@item qSymbol::
*************** encoded). @value{GDBN} will continue to
*** 30849,30854 ****
--- 30858,30864 ----
@item QTBuffer
@item QTDisconnected
@itemx QTDP
+ @itemx QTDPsrc
@itemx QTDV
@itemx qTfP
@itemx qTfV
*************** The packet was understood and carried ou
*** 31250,31255 ****
--- 31260,31284 ----
The packet was not recognized.
@end table
+ @item QTDPsrc:@var{n}:@var{addr}:@var{type}:@var{start}:@var{slen}:@var{bytes}
+ @cindex @samp{QTDPsrc} packet
+ Specify a source string of tracepoint @var{n} at address @var{var}.
+ This is useful to get accurate reproduction of the tracepoints
+ originally downloaded at the beginning of the trace run. The
+ @var{type} is a name of the part, such as @samp{cond} for the
+ conditional expression, while @var{bytes} is the string, encoded in
+ hexadecimal. @var{start} is a starting offset, while @var{slen} is
+ the total length; use a nonzero @var{start} and multiple
+ @samp{QTDPsrc} packets when the source string is too long to fit in a
+ single packet.
+
+ The available string types are: @samp{at} for the location,
+ @samp{cond} for the conditional, and @samp{cmd} for an action command.
+ @value{GDBN} issues a separate packet, in order, for each command in a
+ list. The target does not need to do anything with source strings
+ except report them back as part of the @samp{qTfP}/@samp{qTsP}
+ queries.
+
@item QTDV:@var{n}:@var{value}
@cindex define trace state variable, remote request
@cindex @samp{QTDV} packet
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Tracepoint source strings
2010-03-25 22:01 [PATCH] Tracepoint source strings Stan Shebs
@ 2010-03-26 8:24 ` Eli Zaretskii
2010-03-26 17:51 ` Stan Shebs
2010-03-30 13:18 ` Pedro Alves
1 sibling, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2010-03-26 8:24 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
> Date: Thu, 25 Mar 2010 15:01:25 -0700
> From: Stan Shebs <stan@codesourcery.com>
>
> This patch is another step towards the promised land of
> accurately-restored tracepoint definitions. For those just tuning in,
> the problem is that in both the disconnected tracing and the trace file
> cases, it's very difficult to use tracepoints if the definitions in GDB
> do not match up with what was used to create the trace frames on the
> target or in the file. This patch takes a more audacious approach that
> seems to work well in practice; it literally downloads and uploads the
> original source form of the tracepoint, whitespace and all.
Thanks.
> struct breakpoint *
> create_tracepoint_from_upload (struct uploaded_tp *utp)
> {
> ! char *addr_str, small_buf[100];
> [...]
> ! sprintf (small_buf, "*%s", hex_string (utp->addr));
Tz-tz-tz... Using a constant-size buffer in sprintf without any check
for overflow? Are you sure that calling the buffer ``small'' will
magically keep you from trouble? ;-)
> ! if (utp->cond && !utp->cond_string)
> ! warning ("Uploaded tracepoint %d condition has no source form, ignoring it",
What about _() ?
> + warning ("Uploaded tracepoint %d actions have no source form, ignoring them",
> + utp->number);
Ditto.
> + remote_get_noisy_reply (&target_buf, &target_buf_size);
> + if (strcmp (target_buf, "OK"))
> + warning (_("Target does not support source download."));
> +
> + if (cmd->control_type == while_control
> + || cmd->control_type == while_stepping_control)
> + {
> + remote_download_command_source (num, addr, *cmd->body_list);
> +
> + QUIT; /* allow user to bail out with ^C */
> + strcpy (rs->buf, "QTDPsrc:");
> + encode_source_string (num, addr, "cmd", "end",
> + rs->buf + strlen (rs->buf));
> + putpkt (rs->buf);
> + remote_get_noisy_reply (&target_buf, &target_buf_size);
> + if (strcmp (target_buf, "OK"))
> + warning (_("Target does not support source download."));
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
Can we have this string defined only once, and then use it in all the
places where you need it? (The two uses above are not the only ones.)
> + void
> + encode_source_string (int tpnum, ULONGEST addr,
> + char *srctype, char *src, char *buf)
> + {
> + sprintf (buf, "%x:%s:%s:%x:%x:",
> + tpnum, phex_nz (addr, sizeof (addr)), srctype, 0, (int) strlen (src));
Again, sprintf on a buffer whose size is not even known.
> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
> ! if (written < 8)
> perror_with_name (pathname);
>
> /* Write descriptive info. */
> --- 2468,2474 ----
> binary file, plus a hint as what this file is, and a version
> number in case of future needs. */
> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
> ! if (written < 1)
> perror_with_name (pathname);
Why did you change this to accept partial writes?
> written = fwrite (&gotten, 4, 1, fp);
> ! if (written < 4)
> perror_with_name (pathname);
>
> do_cleanups (cleanup);
> --- 2579,2592 ----
> if (gotten == 0)
> break;
> written = fwrite (buf, gotten, 1, fp);
> ! if (written < 1)
> perror_with_name (pathname);
Same here.
> + if (strncmp (srctype, "at:", strlen ("at:")) == 0)
> + utp->at_string = xstrdup (buf);
> + else if (strncmp (srctype, "cond:", strlen ("cond:")) == 0)
> + utp->cond_string = xstrdup (buf);
> + else if (strncmp (srctype, "cmd:", strlen ("cmd:")) == 0)
Isn't it better to use sizeof here instead of strlen?
> ! warning ("Unrecognized tracepoint piece '%c', ignoring", piece);
No _() .
> + Specify a source string of tracepoint @var{n} at address @var{var}.
^^^^^^^^^
You meant @var{addr}, I presume.
Anyway, can we have several tracepoints with the same number? If not,
why do we need to give the address as well?
> + This is useful to get accurate reproduction of the tracepoints
> + originally downloaded at the beginning of the trace run.
It would be good to include here at least some of the text of the mail
I'm responding to, where you explain why this feature is useful.
> The
> + @var{type} is a name of the part
I would lose the "The" part, as the usual style is not to have it
before parameter names. Also, I think "the name" is more correct,
English-wise. Finally, please say something like "see below", because
you delay the description of TYPE to several sentences later.
> such as @samp{cond} for the
> + conditional expression
Conditional expression for what or from where? I'm guessing this is
somehow related to the original definition of the tracepoint, but
please connect the dots more explicitly.
> while @var{bytes} is the string, encoded in
> + hexadecimal. @var{start} is a starting offset, while @var{slen} is
> + the total length; use a nonzero @var{start} and multiple
> + @samp{QTDPsrc} packets when the source string is too long to fit in a
> + single packet.
Same here: please help the reader understand how to construct each of
these elements.
> + @value{GDBN} issues a separate packet, in order, for each command in a
> + list.
What list?
> The target does not need to do anything with source strings
> + except report them back as part of the @samp{qTfP}/@samp{qTsP}
> + queries.
"As part of queries" or as part or _responses_?
Thanks.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Tracepoint source strings
2010-03-26 8:24 ` Eli Zaretskii
@ 2010-03-26 17:51 ` Stan Shebs
2010-03-26 18:03 ` Eli Zaretskii
0 siblings, 1 reply; 7+ messages in thread
From: Stan Shebs @ 2010-03-26 17:51 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Stan Shebs, gdb-patches
Eli Zaretskii wrote:
>> struct breakpoint *
>> create_tracepoint_from_upload (struct uploaded_tp *utp)
>> {
>> ! char *addr_str, small_buf[100];
>> [...]
>> ! sprintf (small_buf, "*%s", hex_string (utp->addr));
>>
>
> Tz-tz-tz... Using a constant-size buffer in sprintf without any check
> for overflow? Are you sure that calling the buffer ``small'' will
> magically keep you from trouble? ;-)
>
Presumably even a hypothetical future 128-bit address won't need more
than 65 chars to print. :-)
>> ! if (utp->cond && !utp->cond_string)
>> ! warning ("Uploaded tracepoint %d condition has no source form, ignoring it",
>>
>
> What about _() ?
>
>
Oops, yeah.
>
>> + void
>> + encode_source_string (int tpnum, ULONGEST addr,
>> + char *srctype, char *src, char *buf)
>> + {
>> + sprintf (buf, "%x:%s:%s:%x:%x:",
>> + tpnum, phex_nz (addr, sizeof (addr)), srctype, 0, (int) strlen (src));
>>
>
> Again, sprintf on a buffer whose size is not even known.
>
Hmmm, I'll see what I can do.
>> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
>> ! if (written < 8)
>> perror_with_name (pathname);
>>
>> /* Write descriptive info. */
>> --- 2468,2474 ----
>> binary file, plus a hint as what this file is, and a version
>> number in case of future needs. */
>> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
>> ! if (written < 1)
>> perror_with_name (pathname);
>>
>
> Why did you change this to accept partial writes?
>
I was hoping to fix a major brain cramp of mine without anybody noticing
- oh well. :-) The two numeric arguments to fwrite are semi-redundant a
la calloc, and the return result is based on the *second* argument,
which is the number of "items". The other way to fix is to swap the two
arguments; about the only advantage of this way is that we always test
against 1, instead of repeating the fwrite argument.
>> + Specify a source string of tracepoint @var{n} at address @var{var}.
>>
> ^^^^^^^^^
> You meant @var{addr}, I presume.
>
> Anyway, can we have several tracepoints with the same number? If not,
> why do we need to give the address as well?
>
Yes and yes.
>> such as @samp{cond} for the
>> + conditional expression
>>
>
> Conditional expression for what or from where? I'm guessing this is
> somehow related to the original definition of the tracepoint, but
> please connect the dots more explicitly.
>
Yes, it's the tracepoint's condition, I can make an xref. I tend to
think we can be a little more abbreviated when describing the protocol,
because presumably anybody writing a target agent is going to know GDB
concepts pretty well.
>> + @value{GDBN} issues a separate packet, in order, for each command in a
>> + list.
>>
>
> What list?
>
Command list.
>> The target does not need to do anything with source strings
>> + except report them back as part of the @samp{qTfP}/@samp{qTsP}
>> + queries.
>>
>
> "As part of queries" or as part or _responses_?
>
As part of replies. I've glossed over details of the qT[fs]P reply to
date, so as to not to have to rewrite so much as the rest of the
tracepoint patches go in. The grand plan is that there is a notion of
"tracepoint description" with a syntax that is common between remote
download, remote upload, and trace file, and it should go into its own
section that is referenced from both protocol and file format descriptions.
Stan
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Tracepoint source strings
2010-03-26 17:51 ` Stan Shebs
@ 2010-03-26 18:03 ` Eli Zaretskii
2010-03-26 18:38 ` Stan Shebs
0 siblings, 1 reply; 7+ messages in thread
From: Eli Zaretskii @ 2010-03-26 18:03 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
> Date: Fri, 26 Mar 2010 10:51:02 -0700
> From: Stan Shebs <stan@codesourcery.com>
> CC: Stan Shebs <stan@codesourcery.com>, gdb-patches@sourceware.org
>
> Eli Zaretskii wrote:
> >> struct breakpoint *
> >> create_tracepoint_from_upload (struct uploaded_tp *utp)
> >> {
> >> ! char *addr_str, small_buf[100];
> >> [...]
> >> ! sprintf (small_buf, "*%s", hex_string (utp->addr));
> >>
> >
> > Tz-tz-tz... Using a constant-size buffer in sprintf without any check
> > for overflow? Are you sure that calling the buffer ``small'' will
> > magically keep you from trouble? ;-)
> >
>
> Presumably even a hypothetical future 128-bit address won't need more
> than 65 chars to print. :-)
Yes, and then someone comes up and changes the code to put there
something in addition to the address (you already prepend an asterisk
to it).
But if I'm the only one who is bothered by this, I withdraw my
objections.
> >> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
> >> ! if (written < 8)
> >> perror_with_name (pathname);
> >>
> >> /* Write descriptive info. */
> >> --- 2468,2474 ----
> >> binary file, plus a hint as what this file is, and a version
> >> number in case of future needs. */
> >> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
> >> ! if (written < 1)
> >> perror_with_name (pathname);
> >>
> >
> > Why did you change this to accept partial writes?
> >
>
> I was hoping to fix a major brain cramp of mine without anybody noticing
> - oh well. :-) The two numeric arguments to fwrite are semi-redundant a
> la calloc, and the return result is based on the *second* argument,
> which is the number of "items".
So you are writing a string as if it were an 8-byte int? Won't that
swap bytes on some architectures? And why pretend that a string is a
number, anyway?
As for the rest, my questions were meant to signal that portions of
the description are not clear enough, and could use some more explicit
description and/or references to other parts of the manual.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Tracepoint source strings
2010-03-26 18:03 ` Eli Zaretskii
@ 2010-03-26 18:38 ` Stan Shebs
2010-03-26 20:02 ` Eli Zaretskii
0 siblings, 1 reply; 7+ messages in thread
From: Stan Shebs @ 2010-03-26 18:38 UTC (permalink / raw)
To: Eli Zaretskii; +Cc: Stan Shebs, gdb-patches
Eli Zaretskii wrote:
>> Date: Fri, 26 Mar 2010 10:51:02 -0700
>> From: Stan Shebs <stan@codesourcery.com>
>> CC: Stan Shebs <stan@codesourcery.com>, gdb-patches@sourceware.org
>>
>> Eli Zaretskii wrote:
>>
>>>> struct breakpoint *
>>>> create_tracepoint_from_upload (struct uploaded_tp *utp)
>>>> {
>>>> ! char *addr_str, small_buf[100];
>>>> [...]
>>>> ! sprintf (small_buf, "*%s", hex_string (utp->addr));
>>>>
>>>>
>>> Tz-tz-tz... Using a constant-size buffer in sprintf without any check
>>> for overflow? Are you sure that calling the buffer ``small'' will
>>> magically keep you from trouble? ;-)
>>>
>>>
>> Presumably even a hypothetical future 128-bit address won't need more
>> than 65 chars to print. :-)
>>
>
> Yes, and then someone comes up and changes the code to put there
> something in addition to the address (you already prepend an asterisk
> to it).
>
> But if I'm the only one who is bothered by this, I withdraw my
> objections.
>
What's a better thing to do then? Am I missing something in our current
coding preferences for this kind of thing? (Which is entirely possible,
oldtimers often get out of date on best practices... :-) )
>>>> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
>>>> ! if (written < 8)
>>>> perror_with_name (pathname);
>>>>
>>>> /* Write descriptive info. */
>>>> --- 2468,2474 ----
>>>> binary file, plus a hint as what this file is, and a version
>>>> number in case of future needs. */
>>>> written = fwrite ("\x7fTRACE0\n", 8, 1, fp);
>>>> ! if (written < 1)
>>>> perror_with_name (pathname);
>>>>
>>>>
>>> Why did you change this to accept partial writes?
>>>
>>>
>> I was hoping to fix a major brain cramp of mine without anybody noticing
>> - oh well. :-) The two numeric arguments to fwrite are semi-redundant a
>> la calloc, and the return result is based on the *second* argument,
>> which is the number of "items".
>>
>
> So you are writing a string as if it were an 8-byte int? Won't that
> swap bytes on some architectures? And why pretend that a string is a
> number, anyway?
>
fwrite doesn't know about ints and such; as the man page says, it's just
doing repeated putc starting at the given address. The only effect of
the two arguments is the way the results are reported, so if you ask to
write 2 elements of size 4, but low-level writing fails at byte 6, it's
going to report that it wrote 1 element. Kind of a weak API concept, I
suspect there are few production uses where neither argument is 1...
> As for the rest, my questions were meant to signal that portions of
> the description are not clear enough, and could use some more explicit
> description and/or references to other parts of the manual.
>
>
Indeed, and I will be working on that. Having been so close to this
stuff for a while, it's good to get the fresh perspective!
Stan
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Tracepoint source strings
2010-03-26 18:38 ` Stan Shebs
@ 2010-03-26 20:02 ` Eli Zaretskii
0 siblings, 0 replies; 7+ messages in thread
From: Eli Zaretskii @ 2010-03-26 20:02 UTC (permalink / raw)
To: Stan Shebs; +Cc: gdb-patches
> Date: Fri, 26 Mar 2010 11:38:01 -0700
> From: Stan Shebs <stan@codesourcery.com>
> CC: Stan Shebs <stan@codesourcery.com>, gdb-patches@sourceware.org
>
> What's a better thing to do then? Am I missing something in our current
> coding preferences for this kind of thing?
I'd take a look at asprintf and xstrprintf.
^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: [PATCH] Tracepoint source strings
2010-03-25 22:01 [PATCH] Tracepoint source strings Stan Shebs
2010-03-26 8:24 ` Eli Zaretskii
@ 2010-03-30 13:18 ` Pedro Alves
1 sibling, 0 replies; 7+ messages in thread
From: Pedro Alves @ 2010-03-30 13:18 UTC (permalink / raw)
To: gdb-patches; +Cc: Stan Shebs
On Thursday 25 March 2010 22:01:25, Stan Shebs wrote:
> * gdb.texinfo (Tracepoint Packets): Describe QTDPsrc.
> (General Query Packets): Describe TracepointSource.
Could you add a NEWS entry for these new packets, please?
--
Pedro Alves
^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2010-03-30 13:18 UTC | newest]
Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-03-25 22:01 [PATCH] Tracepoint source strings Stan Shebs
2010-03-26 8:24 ` Eli Zaretskii
2010-03-26 17:51 ` Stan Shebs
2010-03-26 18:03 ` Eli Zaretskii
2010-03-26 18:38 ` Stan Shebs
2010-03-26 20:02 ` Eli Zaretskii
2010-03-30 13:18 ` Pedro Alves
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).