diff options
author | Stan Shebs <shebs@codesourcery.com> | 2011-11-02 23:44:21 +0000 |
---|---|---|
committer | Stan Shebs <shebs@codesourcery.com> | 2011-11-02 23:44:21 +0000 |
commit | 3065dfb6b4e2e605b3601c5f71fa25de5dd4970e (patch) | |
tree | ac641720c021164a841a9c669e88e599134191e6 /gdb/gdbserver/tracepoint.c | |
parent | 39f4f51d8bf1d516a5cca652a1d9efe8f3ef9863 (diff) | |
download | fsf-binutils-gdb-3065dfb6b4e2e605b3601c5f71fa25de5dd4970e.zip fsf-binutils-gdb-3065dfb6b4e2e605b3601c5f71fa25de5dd4970e.tar.gz fsf-binutils-gdb-3065dfb6b4e2e605b3601c5f71fa25de5dd4970e.tar.bz2 |
2011-11-02 Stan Shebs <stan@codesourcery.com>
String collection for tracepoints.
* NEWS: Mention string collection.
* common/ax.def (tracenz): New bytecode.
* ax-gdb.h (trace_string_kludge): Declare.
* ax-gdb.c: Include valprint.h and c-lang.h.
(trace_string_kludge): New global.
(gen_traced_pop): Add string case.
(agent_command): Add string case.
* tracepoint.h (decode_agent_options): Declare.
* tracepoint.c: Include cli-utils.h.
(decode_agent_options): New function.
(validate_actionline): Call it.
(encode_actions_1): Ditto.
* target.h (struct target_ops): New method to_supports_string_tracing.
(target_supports_string_tracing): New macro.
* target.c (update_current_target): Add to_supports_string_tracing.
* remote.c (struct remote_state): New field string_tracing.
(remote_string_tracing_feature): New function.
(remote_protocol_features): New feature tracenz.
(remote_supports_string_tracing): New function.
(init_remote_ops): Set to_supports_string_tracing.
* tracepoint.c (agent_mem_read_string): New function.
(eval_agent_expr): Call it for tracenz.
* server.c (handle_query): Report support for tracenz.
* gdb.texinfo (Tracepoint Action Lists): Document collect/s.
(General Query Packets): Describe tracenz feature.
* agentexpr.texi (Bytecode Descriptions): Describe tracenz.
* gdb.trace/collection.c: Add code using strings.
* gdb.trace/collection.exp: Add tests of string collection.
Diffstat (limited to 'gdb/gdbserver/tracepoint.c')
-rw-r--r-- | gdb/gdbserver/tracepoint.c | 70 |
1 files changed, 70 insertions, 0 deletions
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c index eaa54f5..139e30e 100644 --- a/gdb/gdbserver/tracepoint.c +++ b/gdb/gdbserver/tracepoint.c @@ -1209,6 +1209,9 @@ static enum eval_result_type eval_agent_expr (struct tracepoint_hit_ctx *ctx, static int agent_mem_read (struct traceframe *tframe, unsigned char *to, CORE_ADDR from, ULONGEST len); +static int agent_mem_read_string (struct traceframe *tframe, + unsigned char *to, CORE_ADDR from, + ULONGEST len); static int agent_tsv_read (struct traceframe *tframe, int n); #ifndef IN_PROCESS_AGENT @@ -4644,6 +4647,13 @@ eval_agent_expr (struct tracepoint_hit_ctx *ctx, agent_tsv_read (tframe, arg); break; + case gdb_agent_op_tracenz: + agent_mem_read_string (tframe, NULL, (CORE_ADDR) stack[--sp], + (ULONGEST) top); + if (--sp >= 0) + top = stack[sp]; + break; + /* GDB never (currently) generates any of these ops. */ case gdb_agent_op_float: case gdb_agent_op_ref_float: @@ -4727,6 +4737,66 @@ agent_mem_read (struct traceframe *tframe, return 0; } +static int +agent_mem_read_string (struct traceframe *tframe, + unsigned char *to, CORE_ADDR from, ULONGEST len) +{ + unsigned char *buf, *mspace; + ULONGEST remaining = len; + unsigned short blocklen, i; + + /* To save a bit of space, block lengths are 16-bit, so break large + requests into multiple blocks. Bordering on overkill for strings, + but it could happen that someone specifies a large max length. */ + while (remaining > 0) + { + size_t sp; + + blocklen = (remaining > 65535 ? 65535 : remaining); + /* We want working space to accumulate nonzero bytes, since + traceframes must have a predecided size (otherwise it gets + harder to wrap correctly for the circular case, etc). */ + buf = (unsigned char *) xmalloc (blocklen + 1); + for (i = 0; i < blocklen; ++i) + { + /* Read the string one byte at a time, in case the string is + at the end of a valid memory area - we don't want a + correctly-terminated string to engender segvio + complaints. */ + read_inferior_memory (from + i, buf + i, 1); + + if (buf[i] == '\0') + { + blocklen = i + 1; + /* Make sure outer loop stops now too. */ + remaining = blocklen; + break; + } + } + sp = 1 + sizeof (from) + sizeof (blocklen) + blocklen; + mspace = add_traceframe_block (tframe, sp); + if (mspace == NULL) + { + xfree (buf); + return 1; + } + /* Identify block as a memory block. */ + *mspace = 'M'; + ++mspace; + /* Record address and size. */ + memcpy ((void *) mspace, (void *) &from, sizeof (from)); + mspace += sizeof (from); + memcpy ((void *) mspace, (void *) &blocklen, sizeof (blocklen)); + mspace += sizeof (blocklen); + /* Copy the string contents. */ + memcpy ((void *) mspace, (void *) buf, blocklen); + remaining -= blocklen; + from += blocklen; + xfree (buf); + } + return 0; +} + /* Record the value of a trace state variable. */ static int |