Index: gdb/gdbserver/tracepoint.c |
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c |
index f103dfce81a8ffe54d468554deb43e19a195074b..ea1a8a106fa2efd41d127e3a99fd9004e560eeeb 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-2012 Free Software Foundation, Inc. |
+ Copyright (C) 2009-2013 Free Software Foundation, Inc. |
This file is part of GDB. |
@@ -17,6 +17,7 @@ |
along with this program. If not, see <http://www.gnu.org/licenses/>. */ |
#include "server.h" |
+#include "tracepoint.h" |
#include "gdbthread.h" |
#include "agent.h" |
@@ -29,6 +30,9 @@ |
#include <stdint.h> |
#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,7 +61,7 @@ |
*/ |
-static void trace_vdebug (const char *, ...) ATTR_FORMAT (printf, 1, 2); |
+static void trace_vdebug (const char *, ...) ATTRIBUTE_PRINTF (1, 2); |
static void |
trace_vdebug (const char *fmt, ...) |
@@ -979,6 +983,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 +1000,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; |
@@ -1346,12 +1358,6 @@ struct trap_tracepoint_ctx |
#endif |
-static enum eval_result_type |
-eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx, |
- struct traceframe *tframe, |
- struct agent_expr *aexpr, |
- ULONGEST *rslt); |
- |
#ifndef IN_PROCESS_AGENT |
static CORE_ADDR traceframe_get_pc (struct traceframe *tframe); |
static int traceframe_read_tsv (int num, LONGEST *val); |
@@ -1484,10 +1490,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 (); |
} |
@@ -1527,7 +1542,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: |
@@ -1902,18 +1917,6 @@ find_next_tracepoint_by_number (struct tracepoint *prev_tp, int num) |
#endif |
-static char * |
-save_string (const char *str, size_t len) |
-{ |
- char *s; |
- |
- s = xmalloc (len + 1); |
- memcpy (s, str, len); |
- s[len] = '\0'; |
- |
- return s; |
-} |
- |
/* Append another action to perform when the tracepoint triggers. */ |
static void |
@@ -2034,7 +2037,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) |
* tpoint->num_step_actions)); |
tpoint->step_actions[tpoint->num_step_actions - 1] = action; |
tpoint->step_actions_str[tpoint->num_step_actions - 1] |
- = save_string (act_start, act - act_start); |
+ = savestring (act_start, act - act_start); |
} |
else |
{ |
@@ -2047,7 +2050,7 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet) |
sizeof (*tpoint->actions_str) * tpoint->numactions); |
tpoint->actions[tpoint->numactions - 1] = action; |
tpoint->actions_str[tpoint->numactions - 1] |
- = save_string (act_start, act - act_start); |
+ = savestring (act_start, act - act_start); |
} |
} |
} |
@@ -2216,7 +2219,8 @@ add_traceframe (struct tracepoint *tpoint) |
/* Add a block to the traceframe currently being worked on. */ |
static unsigned char * |
-add_traceframe_block (struct traceframe *tframe, int amt) |
+add_traceframe_block (struct traceframe *tframe, |
+ struct tracepoint *tpoint, int amt) |
{ |
unsigned char *block; |
@@ -2228,7 +2232,10 @@ add_traceframe_block (struct traceframe *tframe, int amt) |
if (!block) |
return NULL; |
+ gdb_assert (tframe->tpnum == tpoint->number); |
+ |
tframe->data_size += amt; |
+ tpoint->traceframe_usage += amt; |
return block; |
} |
@@ -2358,6 +2365,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 (); |
@@ -2808,7 +2817,7 @@ static void |
cmd_qtv (char *own_buf) |
{ |
ULONGEST num; |
- LONGEST val; |
+ LONGEST val = 0; |
int err; |
char *packet = own_buf; |
@@ -3657,14 +3666,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); |
} |
@@ -3698,8 +3708,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; |
@@ -3773,7 +3783,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) |
@@ -3798,17 +3808,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 |
@@ -3823,7 +3833,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); |
@@ -3873,15 +3883,9 @@ cmd_qtfv (char *packet) |
static void |
cmd_qtsv (char *packet) |
{ |
- trace_debug ("Returning first trace state variable definition"); |
+ trace_debug ("Returning additional trace state variable definition"); |
- if (!cur_tpoint) |
- { |
- /* This case would normally never occur, but be prepared for |
- GDB misbehavior. */ |
- strcpy (packet, "l"); |
- } |
- else if (cur_tsv) |
+ if (cur_tsv) |
{ |
cur_tsv = cur_tsv->next; |
if (cur_tsv) |
@@ -3923,6 +3927,38 @@ cmd_qtstmat (char *packet) |
run_inferior_command (packet, strlen (packet) + 1); |
} |
+/* Sent the agent a command to close it. */ |
+ |
+void |
+gdb_agent_about_to_close (int pid) |
+{ |
+ char buf[IPA_CMD_BUF_SIZE]; |
+ |
+ if (!maybe_write_ipa_not_loaded (buf)) |
+ { |
+ struct thread_info *save_inferior; |
+ struct inferior_list_entry *inf = all_threads.head; |
+ |
+ save_inferior = current_inferior; |
+ |
+ /* Find a certain thread which belongs to process PID. */ |
+ while (inf != NULL) |
+ { |
+ if (ptid_get_pid (inf->id) == pid) |
+ break; |
+ inf = inf->next; |
+ } |
+ |
+ current_inferior = (struct thread_info *) inf; |
+ |
+ strcpy (buf, "close"); |
+ |
+ run_inferior_command (buf, strlen (buf) + 1); |
+ |
+ current_inferior = save_inferior; |
+ } |
+} |
+ |
/* Return the minimum instruction size needed for fast tracepoints as a |
hexadecimal number. */ |
@@ -3957,7 +3993,7 @@ cmd_qtbuffer (char *own_buf) |
unpack_varlen_hex (packet, &num); |
trace_debug ("Want to get trace buffer, %d bytes at offset 0x%s", |
- (int) num, pulongest (offset)); |
+ (int) num, phex_nz (offset, 0)); |
tot = (trace_buffer_hi - trace_buffer_lo) - free_space (); |
@@ -3990,7 +4026,6 @@ cmd_qtbuffer (char *own_buf) |
num = (PBUFSIZ - 16) / 2; |
convert_int_to_ascii (tbp, own_buf, num); |
- own_buf[num] = '\0'; |
} |
static void |
@@ -4009,6 +4044,37 @@ cmd_bigqtbuffer_circular (char *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) |
{ |
size_t nbytes; |
@@ -4030,6 +4096,7 @@ cmd_qtnotes (char *own_buf) |
user[nbytes] = '\0'; |
++packet; /* skip the semicolon */ |
trace_debug ("User is '%s'", user); |
+ xfree (tracing_user_name); |
tracing_user_name = user; |
} |
else if (strncmp ("notes:", packet, strlen ("notes:")) == 0) |
@@ -4043,6 +4110,7 @@ cmd_qtnotes (char *own_buf) |
notes[nbytes] = '\0'; |
++packet; /* skip the semicolon */ |
trace_debug ("Notes is '%s'", notes); |
+ xfree (tracing_notes); |
tracing_notes = notes; |
} |
else if (strncmp ("tstop:", packet, strlen ("tstop:")) == 0) |
@@ -4056,6 +4124,7 @@ cmd_qtnotes (char *own_buf) |
stopnote[nbytes] = '\0'; |
++packet; /* skip the semicolon */ |
trace_debug ("tstop note is '%s'", stopnote); |
+ xfree (tracing_stop_note); |
tracing_stop_note = stopnote; |
} |
else |
@@ -4129,6 +4198,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); |
@@ -4613,6 +4687,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) |
{ |
@@ -4625,7 +4707,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); |
} |
@@ -4640,7 +4722,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. */ |
@@ -4679,15 +4761,19 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx, |
case 'M': |
{ |
struct collect_memory_action *maction; |
+ struct eval_agent_expr_context ax_ctx; |
maction = (struct collect_memory_action *) taction; |
+ ax_ctx.regcache = NULL; |
+ ax_ctx.tframe = tframe; |
+ ax_ctx.tpoint = tpoint; |
trace_debug ("Want to collect %s bytes at 0x%s (basereg %d)", |
pulongest (maction->len), |
paddress (maction->addr), maction->basereg); |
/* (should use basereg) */ |
- agent_mem_read (tframe, NULL, |
- (CORE_ADDR) maction->addr, maction->len); |
+ agent_mem_read (&ax_ctx, NULL, (CORE_ADDR) maction->addr, |
+ maction->len); |
break; |
} |
case 'R': |
@@ -4695,13 +4781,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, |
- 1 + register_cache_size ()); |
+ regspace = add_traceframe_block (tframe, tpoint, 1 + regcache_size); |
if (regspace == NULL) |
{ |
trace_debug ("Trace buffer block allocation failed, skipping"); |
@@ -4710,11 +4798,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); |
@@ -4742,12 +4829,16 @@ do_action_at_tracepoint (struct tracepoint_hit_ctx *ctx, |
case 'X': |
{ |
struct eval_expr_action *eaction; |
+ struct eval_agent_expr_context ax_ctx; |
eaction = (struct eval_expr_action *) taction; |
+ ax_ctx.regcache = get_context_regcache (ctx); |
+ ax_ctx.tframe = tframe; |
+ ax_ctx.tpoint = tpoint; |
trace_debug ("Want to evaluate expression"); |
- err = eval_tracepoint_agent_expr (ctx, tframe, eaction->expr, NULL); |
+ err = gdb_eval_agent_expr (&ax_ctx, eaction->expr, NULL); |
if (err != expr_eval_no_error) |
{ |
@@ -4799,8 +4890,15 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx, |
err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value); |
else |
#endif |
- err = eval_tracepoint_agent_expr (ctx, NULL, tpoint->cond, &value); |
+ { |
+ struct eval_agent_expr_context ax_ctx; |
+ ax_ctx.regcache = get_context_regcache (ctx); |
+ ax_ctx.tframe = NULL; |
+ ax_ctx.tpoint = tpoint; |
+ |
+ err = gdb_eval_agent_expr (&ax_ctx, tpoint->cond, &value); |
+ } |
if (err != expr_eval_no_error) |
{ |
record_tracepoint_error (tpoint, "condition", err); |
@@ -4814,27 +4912,11 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx, |
return (value ? 1 : 0); |
} |
-/* Evaluates a tracepoint agent expression with context CTX, |
- traceframe TFRAME, agent expression AEXPR and store the |
- result in RSLT. */ |
- |
-static enum eval_result_type |
-eval_tracepoint_agent_expr (struct tracepoint_hit_ctx *ctx, |
- struct traceframe *tframe, |
- struct agent_expr *aexpr, |
- ULONGEST *rslt) |
-{ |
- struct regcache *regcache; |
- regcache = get_context_regcache (ctx); |
- |
- return gdb_eval_agent_expr (regcache, tframe, aexpr, rslt); |
-} |
- |
/* Do memory copies for bytecodes. */ |
/* Do the recording of memory blocks for actions and bytecodes. */ |
int |
-agent_mem_read (struct traceframe *tframe, |
+agent_mem_read (struct eval_agent_expr_context *ctx, |
unsigned char *to, CORE_ADDR from, ULONGEST len) |
{ |
unsigned char *mspace; |
@@ -4855,7 +4937,7 @@ agent_mem_read (struct traceframe *tframe, |
blocklen = (remaining > 65535 ? 65535 : remaining); |
sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen; |
- mspace = add_traceframe_block (tframe, sp); |
+ mspace = add_traceframe_block (ctx->tframe, ctx->tpoint, sp); |
if (mspace == NULL) |
return 1; |
/* Identify block as a memory block. */ |
@@ -4876,7 +4958,7 @@ agent_mem_read (struct traceframe *tframe, |
} |
int |
-agent_mem_read_string (struct traceframe *tframe, |
+agent_mem_read_string (struct eval_agent_expr_context *ctx, |
unsigned char *to, CORE_ADDR from, ULONGEST len) |
{ |
unsigned char *buf, *mspace; |
@@ -4912,7 +4994,7 @@ agent_mem_read_string (struct traceframe *tframe, |
} |
} |
sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen; |
- mspace = add_traceframe_block (tframe, sp); |
+ mspace = add_traceframe_block (ctx->tframe, ctx->tpoint, sp); |
if (mspace == NULL) |
{ |
xfree (buf); |
@@ -4938,12 +5020,12 @@ agent_mem_read_string (struct traceframe *tframe, |
/* Record the value of a trace state variable. */ |
int |
-agent_tsv_read (struct traceframe *tframe, int n) |
+agent_tsv_read (struct eval_agent_expr_context *ctx, int n) |
{ |
unsigned char *vspace; |
LONGEST val; |
- vspace = add_traceframe_block (tframe, |
+ vspace = add_traceframe_block (ctx->tframe, ctx->tpoint, |
1 + sizeof (n) + sizeof (LONGEST)); |
if (vspace == NULL) |
return 1; |
@@ -5022,7 +5104,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. */ |
@@ -5117,12 +5199,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); |
} |
@@ -5198,6 +5281,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"); |
@@ -5220,7 +5304,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), |
@@ -5235,16 +5320,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 |
@@ -5326,6 +5412,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, "<tvar id=\"%d\"/>\n", vnum); |
+ break; |
+ } |
case 'R': |
case 'S': |
{ |
@@ -5673,7 +5766,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"); |
@@ -5930,7 +6023,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); |
} |
} |
@@ -6320,7 +6413,8 @@ upload_fast_traceframes (void) |
{ |
/* Copy the whole set of blocks in one go for now. FIXME: |
split this in smaller blocks. */ |
- block = add_traceframe_block (tframe, ipa_tframe.data_size); |
+ block = add_traceframe_block (tframe, tpoint, |
+ ipa_tframe.data_size); |
if (block != NULL) |
{ |
if (read_inferior_memory (tf |
@@ -6532,7 +6626,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"); |
@@ -6619,7 +6713,7 @@ collect_ust_data_at_tracepoint (struct tracepoint_hit_ctx *ctx, |
trace_debug ("Want to collect ust data"); |
/* 'S' + size + string */ |
- bufspace = add_traceframe_block (tframe, |
+ bufspace = add_traceframe_block (tframe, umd->tpoint, |
1 + sizeof (blocklen) + size + 1); |
if (bufspace == NULL) |
{ |
@@ -6666,7 +6760,7 @@ static int |
run_inferior_command (char *cmd, int len) |
{ |
int err = -1; |
- int pid = ptid_get_pid (current_inferior->entry.id); |
+ int pid = ptid_get_pid (current_ptid); |
trace_debug ("run_inferior_command: running: %s", cmd); |
@@ -6748,13 +6842,14 @@ init_named_socket (const char *name) |
return fd; |
} |
+static char agent_socket_name[UNIX_PATH_MAX]; |
+ |
static int |
gdb_agent_socket_init (void) |
{ |
int result, fd; |
- char name[UNIX_PATH_MAX]; |
- result = xsnprintf (name, UNIX_PATH_MAX, "%s/gdb_ust%d", |
+ result = xsnprintf (agent_socket_name, UNIX_PATH_MAX, "%s/gdb_ust%d", |
SOCK_DIR, getpid ()); |
if (result >= UNIX_PATH_MAX) |
{ |
@@ -6762,11 +6857,11 @@ gdb_agent_socket_init (void) |
return -1; |
} |
- fd = init_named_socket (name); |
+ fd = init_named_socket (agent_socket_name); |
if (fd < 0) |
warning ("Error initializing named socket (%s) for communication with the " |
"ust helper thread. Check that directory exists and that it " |
- "is writable.", name); |
+ "is writable.", agent_socket_name); |
return fd; |
} |
@@ -6995,6 +7090,13 @@ gdb_ust_init (void) |
#endif /* HAVE_UST */ |
#include <sys/syscall.h> |
+#include <stdlib.h> |
+ |
+static void |
+gdb_agent_remove_socket (void) |
+{ |
+ unlink (agent_socket_name); |
+} |
/* Helper thread of agent. */ |
@@ -7003,6 +7105,8 @@ gdb_agent_helper_thread (void *arg) |
{ |
int listen_fd; |
+ atexit (gdb_agent_remove_socket); |
+ |
while (1) |
{ |
listen_fd = gdb_agent_socket_init (); |
@@ -7023,6 +7127,7 @@ gdb_agent_helper_thread (void *arg) |
int fd; |
char buf[1]; |
int ret; |
+ int stop_loop = 0; |
tmp = sizeof (sockaddr); |
@@ -7055,8 +7160,12 @@ gdb_agent_helper_thread (void *arg) |
if (cmd_buf[0]) |
{ |
+ if (strncmp ("close", cmd_buf, 5) == 0) |
+ { |
+ stop_loop = 1; |
+ } |
#ifdef HAVE_UST |
- if (strcmp ("qTfSTM", cmd_buf) == 0) |
+ else if (strcmp ("qTfSTM", cmd_buf) == 0) |
{ |
cmd_qtfstm (cmd_buf); |
} |
@@ -7088,6 +7197,20 @@ gdb_agent_helper_thread (void *arg) |
/* Fix compiler's warning: ignoring return value of 'write'. */ |
ret = write (fd, buf, 1); |
close (fd); |
+ |
+ if (stop_loop) |
+ { |
+ close (listen_fd); |
+ unlink (agent_socket_name); |
+ |
+ /* Sleep endlessly to wait the whole inferior stops. This |
+ thread can not exit because GDB or GDBserver may still need |
+ 'current_inferior' (representing this thread) to access |
+ inferior memory. Otherwise, this thread exits earlier than |
+ other threads, and 'current_inferior' is set to NULL. */ |
+ while (1) |
+ sleep (10); |
+ } |
} |
} |
@@ -7185,10 +7308,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 |