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