X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fgdbserver%2Ftracepoint.c;h=8e294f64c0b8a7a6307070e431612806f40e984c;hb=ff0e980e6f720fe49608a5a0a37be3a28258c9d7;hp=0f83ae6d09237bbb2d3d00d29150a5f3a66078d0;hpb=736cd5852660e6ff9c5741efb7724bbe0d94ca67;p=deliverable%2Fbinutils-gdb.git
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 0f83ae6d09..8e294f64c0 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -1,5 +1,5 @@
/* Tracepoint code for remote server for GDB.
- Copyright (C) 2009-2013 Free Software Foundation, Inc.
+ Copyright (C) 2009-2014 Free Software Foundation, Inc.
This file is part of GDB.
@@ -17,8 +17,10 @@
along with this program. If not, see . */
#include "server.h"
+#include "tracepoint.h"
#include "gdbthread.h"
#include "agent.h"
+#include "rsp-low.h"
#include
#include
@@ -29,6 +31,9 @@
#include
#include "ax.h"
+#include "tdesc.h"
+
+#define DEFAULT_TRACE_BUFFER_SIZE 5242880 /* 5*1024*1024 */
/* This file is built for both GDBserver, and the in-process
agent (IPA), a shared library that includes a tracing agent that is
@@ -57,6 +62,8 @@
*/
+#ifdef IN_PROCESS_AGENT
+
static void trace_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2);
static void
@@ -77,6 +84,19 @@ trace_vdebug (const char *fmt, ...)
trace_vdebug ((fmt), ##args); \
} while (0)
+#else
+
+#define trace_debug_1(level, fmt, args...) \
+ do { \
+ if (level <= debug_threads) \
+ { \
+ debug_printf ((fmt), ##args); \
+ debug_printf ("\n"); \
+ } \
+ } while (0)
+
+#endif
+
#define trace_debug(FMT, args...) \
trace_debug_1 (1, FMT, ##args)
@@ -334,7 +354,7 @@ tracepoint_look_up_symbols (void)
if (look_up_one_symbol (symbol_list[i].name, addrp, 1) == 0)
{
if (debug_threads)
- fprintf (stderr, "symbol `%s' not found\n", symbol_list[i].name);
+ debug_printf ("symbol `%s' not found\n", symbol_list[i].name);
return;
}
}
@@ -979,6 +999,10 @@ struct traceframe
} ATTR_PACKED;
+/* The size of the EOB marker, in bytes. A traceframe with zeroed
+ fields (and no data) marks the end of trace data. */
+#define TRACEFRAME_EOB_MARKER_SIZE offsetof (struct traceframe, data)
+
/* The traceframe to be used as the source of data to send back to
GDB. A value of -1 means to get data from the live program. */
@@ -992,6 +1016,10 @@ int current_traceframe = -1;
static int circular_trace_buffer;
#endif
+/* Size of the trace buffer. */
+
+static LONGEST trace_buffer_size;
+
/* Pointer to the block of memory that traceframes all go into. */
static unsigned char *trace_buffer_lo;
@@ -1478,10 +1506,19 @@ clear_inferior_trace_buffer (void)
#endif
static void
-init_trace_buffer (unsigned char *buf, int bufsize)
+init_trace_buffer (LONGEST bufsize)
{
- trace_buffer_lo = buf;
- trace_buffer_hi = trace_buffer_lo + bufsize;
+ size_t alloc_size;
+
+ trace_buffer_size = bufsize;
+
+ /* Make sure to internally allocate at least space for the EOB
+ marker. */
+ alloc_size = (bufsize < TRACEFRAME_EOB_MARKER_SIZE
+ ? TRACEFRAME_EOB_MARKER_SIZE : bufsize);
+ trace_buffer_lo = xrealloc (trace_buffer_lo, alloc_size);
+
+ trace_buffer_hi = trace_buffer_lo + trace_buffer_size;
clear_trace_buffer ();
}
@@ -1521,7 +1558,7 @@ trace_buffer_alloc (size_t amt)
(long) amt, (long) sizeof (struct traceframe));
/* Account for the EOB marker. */
- amt += sizeof (struct traceframe);
+ amt += TRACEFRAME_EOB_MARKER_SIZE;
#ifdef IN_PROCESS_AGENT
again:
@@ -2344,6 +2381,8 @@ cmd_qtinit (char *packet)
/* Make sure we don't try to read from a trace frame. */
current_traceframe = -1;
+ stop_tracing ();
+
trace_debug ("Initializing the trace");
clear_installed_tracepoints ();
@@ -2669,7 +2708,7 @@ cmd_qtdpsrc (char *own_buf)
packet = unpack_varlen_hex (packet, &slen);
++packet; /* skip a colon */
src = xmalloc (slen + 1);
- nbytes = unhexify (src, packet, strlen (packet) / 2);
+ nbytes = hex2bin (packet, (gdb_byte *) src, strlen (packet) / 2);
src[nbytes] = '\0';
newlast = xmalloc (sizeof (struct source_string));
@@ -2711,7 +2750,7 @@ cmd_qtdv (char *own_buf)
nbytes = strlen (packet) / 2;
varname = xmalloc (nbytes + 1);
- nbytes = unhexify (varname, packet, nbytes);
+ nbytes = hex2bin (packet, (gdb_byte *) varname, nbytes);
varname[nbytes] = '\0';
tsv = create_trace_state_variable (num, 1);
@@ -2794,7 +2833,7 @@ static void
cmd_qtv (char *own_buf)
{
ULONGEST num;
- LONGEST val;
+ LONGEST val = 0;
int err;
char *packet = own_buf;
@@ -3584,17 +3623,17 @@ cmd_qtstatus (char *packet)
str = (tracing_user_name ? tracing_user_name : "");
slen = strlen (str);
buf1 = (char *) alloca (slen * 2 + 1);
- hexify (buf1, str, slen);
+ bin2hex ((gdb_byte *) str, buf1, slen);
str = (tracing_notes ? tracing_notes : "");
slen = strlen (str);
buf2 = (char *) alloca (slen * 2 + 1);
- hexify (buf2, str, slen);
+ bin2hex ((gdb_byte *) str, buf2, slen);
str = (tracing_stop_note ? tracing_stop_note : "");
slen = strlen (str);
buf3 = (char *) alloca (slen * 2 + 1);
- hexify (buf3, str, slen);
+ bin2hex ((gdb_byte *) str, buf3, slen);
trace_debug ("Returning trace status as %d, stop reason %s",
tracing, tracing_stop_reason);
@@ -3624,7 +3663,7 @@ cmd_qtstatus (char *packet)
p = stop_reason_rsp = alloca (strlen ("terror:") + hexstr_len + 1);
strcpy (p, "terror:");
p += strlen (p);
- convert_int_to_ascii ((gdb_byte *) result_name, p, strlen (result_name));
+ bin2hex ((gdb_byte *) result_name, p, strlen (result_name));
}
/* If this was a forced stop, include any stop note that was supplied. */
@@ -3643,14 +3682,15 @@ cmd_qtstatus (char *packet)
"circular:%d;"
"disconn:%d;"
"starttime:%s;stoptime:%s;"
- "username:%s:;notes:%s:",
+ "username:%s;notes:%s:",
tracing ? 1 : 0,
stop_reason_rsp, tracing_stop_tpnum,
traceframe_count, traceframes_created,
free_space (), phex_nz (trace_buffer_hi - trace_buffer_lo, 0),
circular_trace_buffer,
disconnected_tracing,
- plongest (tracing_start_time), plongest (tracing_stop_time),
+ phex_nz (tracing_start_time, sizeof (tracing_start_time)),
+ phex_nz (tracing_stop_time, sizeof (tracing_stop_time)),
buf1, buf2);
}
@@ -3684,8 +3724,8 @@ cmd_qtp (char *own_buf)
/* State variables to help return all the tracepoint bits. */
static struct tracepoint *cur_tpoint;
-static int cur_action;
-static int cur_step_action;
+static unsigned int cur_action;
+static unsigned int cur_step_action;
static struct source_string *cur_source_string;
static struct trace_state_variable *cur_tsv;
@@ -3742,7 +3782,7 @@ response_source (char *packet,
len = strlen (src->str);
buf = alloca (len * 2 + 1);
- convert_int_to_ascii ((gdb_byte *) src->str, buf, len);
+ bin2hex ((gdb_byte *) src->str, buf, len);
sprintf (packet, "Z%x:%s:%s:%x:%x:%s",
tpoint->number, paddress (tpoint->address),
@@ -3759,7 +3799,7 @@ cmd_qtfp (char *packet)
trace_debug ("Returning first tracepoint definition piece");
cur_tpoint = tracepoints;
- cur_action = cur_step_action = -1;
+ cur_action = cur_step_action = 0;
cur_source_string = NULL;
if (cur_tpoint)
@@ -3784,17 +3824,17 @@ cmd_qtsp (char *packet)
GDB misbehavior. */
strcpy (packet, "l");
}
- else if (cur_action < cur_tpoint->numactions - 1)
+ else if (cur_action < cur_tpoint->numactions)
{
- ++cur_action;
response_action (packet, cur_tpoint,
cur_tpoint->actions_str[cur_action], 0);
+ ++cur_action;
}
- else if (cur_step_action < cur_tpoint->num_step_actions - 1)
+ else if (cur_step_action < cur_tpoint->num_step_actions)
{
- ++cur_step_action;
response_action (packet, cur_tpoint,
cur_tpoint->step_actions_str[cur_step_action], 1);
+ ++cur_step_action;
}
else if ((cur_source_string
? cur_source_string->next
@@ -3809,7 +3849,7 @@ cmd_qtsp (char *packet)
else
{
cur_tpoint = cur_tpoint->next;
- cur_action = cur_step_action = -1;
+ cur_action = cur_step_action = 0;
cur_source_string = NULL;
if (cur_tpoint)
response_tracepoint (packet, cur_tpoint);
@@ -3831,7 +3871,7 @@ response_tsv (char *packet, struct trace_state_variable *tsv)
{
namelen = strlen (tsv->name);
buf = alloca (namelen * 2 + 1);
- convert_int_to_ascii ((gdb_byte *) tsv->name, buf, namelen);
+ bin2hex ((gdb_byte *) tsv->name, buf, namelen);
}
sprintf (packet, "%x:%s:%x:%s", tsv->number, phex_nz (tsv->initial_value, 0),
@@ -4001,7 +4041,7 @@ cmd_qtbuffer (char *own_buf)
if (num >= (PBUFSIZ - 16) / 2 )
num = (PBUFSIZ - 16) / 2;
- convert_int_to_ascii (tbp, own_buf, num);
+ bin2hex (tbp, own_buf, num);
}
static void
@@ -4019,6 +4059,37 @@ cmd_bigqtbuffer_circular (char *own_buf)
write_ok (own_buf);
}
+static void
+cmd_bigqtbuffer_size (char *own_buf)
+{
+ ULONGEST val;
+ LONGEST sval;
+ char *packet = own_buf;
+
+ /* Can't change the size during a tracing run. */
+ if (tracing)
+ {
+ write_enn (own_buf);
+ return;
+ }
+
+ packet += strlen ("QTBuffer:size:");
+
+ /* -1 is sent as literal "-1". */
+ if (strcmp (packet, "-1") == 0)
+ sval = DEFAULT_TRACE_BUFFER_SIZE;
+ else
+ {
+ unpack_varlen_hex (packet, &val);
+ sval = (LONGEST) val;
+ }
+
+ init_trace_buffer (sval);
+ trace_debug ("Trace buffer is now %s bytes",
+ plongest (trace_buffer_size));
+ write_ok (own_buf);
+}
+
static void
cmd_qtnotes (char *own_buf)
{
@@ -4037,7 +4108,7 @@ cmd_qtnotes (char *own_buf)
packet = strchr (packet, ';');
nbytes = (packet - saved) / 2;
user = xmalloc (nbytes + 1);
- nbytes = unhexify (user, saved, nbytes);
+ nbytes = hex2bin (saved, (gdb_byte *) user, nbytes);
user[nbytes] = '\0';
++packet; /* skip the semicolon */
trace_debug ("User is '%s'", user);
@@ -4051,7 +4122,7 @@ cmd_qtnotes (char *own_buf)
packet = strchr (packet, ';');
nbytes = (packet - saved) / 2;
notes = xmalloc (nbytes + 1);
- nbytes = unhexify (notes, saved, nbytes);
+ nbytes = hex2bin (saved, (gdb_byte *) notes, nbytes);
notes[nbytes] = '\0';
++packet; /* skip the semicolon */
trace_debug ("Notes is '%s'", notes);
@@ -4065,7 +4136,7 @@ cmd_qtnotes (char *own_buf)
packet = strchr (packet, ';');
nbytes = (packet - saved) / 2;
stopnote = xmalloc (nbytes + 1);
- nbytes = unhexify (stopnote, saved, nbytes);
+ nbytes = hex2bin (saved, (gdb_byte *) stopnote, nbytes);
stopnote[nbytes] = '\0';
++packet; /* skip the semicolon */
trace_debug ("tstop note is '%s'", stopnote);
@@ -4143,6 +4214,11 @@ handle_tracepoint_general_set (char *packet)
cmd_bigqtbuffer_circular (packet);
return 1;
}
+ else if (strncmp ("QTBuffer:size:", packet, strlen ("QTBuffer:size:")) == 0)
+ {
+ cmd_bigqtbuffer_size (packet);
+ return 1;
+ }
else if (strncmp ("QTNotes:", packet, strlen ("QTNotes:")) == 0)
{
cmd_qtnotes (packet);
@@ -4627,6 +4703,14 @@ collect_data_at_step (struct tracepoint_hit_ctx *ctx,
#endif
+#ifdef IN_PROCESS_AGENT
+/* The target description used by the IPA. Given that the IPA library
+ is built for a specific architecture that is loaded into the
+ inferior, there only needs to be one such description per
+ build. */
+const struct target_desc *ipa_tdesc;
+#endif
+
static struct regcache *
get_context_regcache (struct tracepoint_hit_ctx *ctx)
{
@@ -4639,7 +4723,7 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx)
if (!fctx->regcache_initted)
{
fctx->regcache_initted = 1;
- init_register_cache (&fctx->regcache, fctx->regspace);
+ init_register_cache (&fctx->regcache, ipa_tdesc, fctx->regspace);
supply_regblock (&fctx->regcache, NULL);
supply_fast_tracepoint_registers (&fctx->regcache, fctx->regs);
}
@@ -4654,7 +4738,7 @@ get_context_regcache (struct tracepoint_hit_ctx *ctx)
if (!sctx->regcache_initted)
{
sctx->regcache_initted = 1;
- init_register_cache (&sctx->regcache, sctx->regspace);
+ init_register_cache (&sctx->regcache, ipa_tdesc, sctx->regspace);
supply_regblock (&sctx->regcache, NULL);
/* Pass down the tracepoint address, because REGS doesn't
include the PC, but we know what it must have been. */
@@ -4713,13 +4797,15 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
unsigned char *regspace;
struct regcache tregcache;
struct regcache *context_regcache;
-
+ int regcache_size;
trace_debug ("Want to collect registers");
+ context_regcache = get_context_regcache (ctx);
+ regcache_size = register_cache_size (context_regcache->tdesc);
+
/* Collect all registers for now. */
- regspace = add_traceframe_block (tframe, tpoint,
- 1 + register_cache_size ());
+ regspace = add_traceframe_block (tframe, tpoint, 1 + regcache_size);
if (regspace == NULL)
{
trace_debug ("Trace buffer block allocation failed, skipping");
@@ -4728,11 +4814,10 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx,
/* Identify a register block. */
*regspace = 'R';
- context_regcache = get_context_regcache (ctx);
-
/* Wrap the regblock in a register cache (in the stack, we
don't want to malloc here). */
- init_register_cache (&tregcache, regspace + 1);
+ init_register_cache (&tregcache, context_regcache->tdesc,
+ regspace + 1);
/* Copy the register data to the regblock. */
regcache_cpy (&tregcache, context_regcache);
@@ -5035,7 +5120,7 @@ traceframe_walk_blocks (unsigned char *database, unsigned int datasize,
{
case 'R':
/* Skip over the registers block. */
- dataptr += register_cache_size ();
+ dataptr += current_target_desc ()->registers_size;
break;
case 'M':
/* Skip over the memory block. */
@@ -5130,12 +5215,13 @@ traceframe_get_pc (struct traceframe *tframe)
{
struct regcache regcache;
unsigned char *dataptr;
+ const struct target_desc *tdesc = current_target_desc ();
dataptr = traceframe_find_regblock (tframe, -1);
if (dataptr == NULL)
return 0;
- init_register_cache (®cache, dataptr);
+ init_register_cache (®cache, tdesc, dataptr);
return regcache_read_pc (®cache);
}
@@ -5211,6 +5297,7 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)
unsigned char *database, *dataptr;
unsigned int datasize;
int vnum;
+ int found = 0;
trace_debug ("traceframe_read_tsv");
@@ -5233,7 +5320,8 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)
datasize = tframe->data_size;
database = dataptr = &tframe->data[0];
- /* Iterate through a traceframe's blocks, looking for the tsv. */
+ /* Iterate through a traceframe's blocks, looking for the last
+ matched tsv. */
while ((dataptr = traceframe_find_block_type (dataptr,
datasize
- (dataptr - database),
@@ -5248,16 +5336,17 @@ traceframe_read_tsv (int tsvnum, LONGEST *val)
if (tsvnum == vnum)
{
memcpy (val, dataptr, sizeof (*val));
- return 0;
+ found = 1;
}
/* Skip over this block. */
dataptr += sizeof (LONGEST);
}
- trace_debug ("traceframe %d has no data for variable %d",
- tfnum, tsvnum);
- return 1;
+ if (!found)
+ trace_debug ("traceframe %d has no data for variable %d",
+ tfnum, tsvnum);
+ return !found;
}
/* Read a requested block of static tracepoint data from a trace
@@ -5339,6 +5428,13 @@ build_traceframe_info_xml (char blocktype, unsigned char *dataptr, void *data)
break;
}
case 'V':
+ {
+ int vnum;
+
+ memcpy (&vnum, dataptr, sizeof (vnum));
+ buffer_xml_printf (buffer, "\n", vnum);
+ break;
+ }
case 'R':
case 'S':
{
@@ -5686,7 +5782,7 @@ gdb_collect (struct tracepoint *tpoint, unsigned char *regs)
ctx.regcache_initted = 0;
/* Wrap the regblock in a register cache (in the stack, we don't
want to malloc here). */
- ctx.regspace = alloca (register_cache_size ());
+ ctx.regspace = alloca (ipa_tdesc->registers_size);
if (ctx.regspace == NULL)
{
trace_debug ("Trace buffer block allocation failed, skipping");
@@ -5943,7 +6039,7 @@ download_tracepoint_1 (struct tracepoint *tpoint)
if (ipa_action != 0)
write_inferior_data_ptr
- (actions_array + i * sizeof (sizeof (*tpoint->actions)),
+ (actions_array + i * sizeof (*tpoint->actions),
ipa_action);
}
}
@@ -6546,7 +6642,7 @@ gdb_probe (const struct marker *mdata, void *probe_private,
/* Wrap the regblock in a register cache (in the stack, we don't
want to malloc here). */
- ctx.regspace = alloca (register_cache_size ());
+ ctx.regspace = alloca (ipa_tdesc->registers_size);
if (ctx.regspace == NULL)
{
trace_debug ("Trace buffer block allocation failed, skipping");
@@ -6834,7 +6930,7 @@ cstr_to_hexstr (const char *str)
{
int len = strlen (str);
char *hexstr = xmalloc (len * 2 + 1);
- convert_int_to_ascii ((gdb_byte *) str, hexstr, len);
+ bin2hex ((gdb_byte *) str, hexstr, len);
return hexstr;
}
@@ -7228,10 +7324,8 @@ get_timestamp (void)
void
initialize_tracepoint (void)
{
- /* There currently no way to change the buffer size. */
- const int sizeOfBuffer = 5 * 1024 * 1024;
- unsigned char *buf = xmalloc (sizeOfBuffer);
- init_trace_buffer (buf, sizeOfBuffer);
+ /* Start with the default size. */
+ init_trace_buffer (DEFAULT_TRACE_BUFFER_SIZE);
/* Wire trace state variable 1 to be the timestamp. This will be
uploaded to GDB upon connection and become one of its trace state