[PATCH 7/7] Support tracepoints and software breakpoints on ARM aarch32-linux in GDBServer.

Antoine Tremblay
2015-09-11T12:14:52Z

This patch adds support for tracepoints for ARM aarch32-linux in GDBServer.
It also adds support for software breakpoints via a z0 packet in GDBServer.

To enable this, this patch also introduces a new :K (kind) field in the QTDP
packet to encode the breakpoint kind, this is the same kind as a z0 packet.

This is the new qSupported feature : TracepointKinds

This field is decoded by the new breakpoint_from_length target ops in linux-low.

Also GDBServer always need to handle that the software breakpoint size can
coded as a kind field and thus always decode this to the real length of the
breakpoint when doing memory operations on the breakpoint using
check_breakpoint_from_length.

A note about tests :

Some tests expect to use a frame pointer register, however since there no such
thing on the ABI for ARM on linux, references to fp are replaced by sp the stack
pointer. Since this value is usually only meant to be collected there is no
impact on the tests.

Also, since some registers are not available on ARM some tests have been skipped
or adapted to work properly given that situation.

For example the pending.exp test checks if a trace frame is found, however since
some registers are not available some error output is generated about this issue
even if the trace frame is found. The test was made a little more lax so that
such output is accepted.

Other tests are left as failing since what they test is directly impacted by
those missing registers like reports.exp that will output errors like :
"Unable to access DWARF register number 8".

There is some known tests that are failing to due what seems to be a bug in the
ARM stack unwinder, for example collecting a string in collections.exp will not
work properly when calling tdump the first time since it can't compute the frame
id but will work when called the second time... Fixing this issue is left as
work to be done.

This issue also has ripple effects on some other tests like :
mi-trace-frame-collected.exp since it causes a "Register 13 is not available" to
be printed.

Other than that the patch was tested on Ubuntu 14.04 ARMv7 and x86 with no
regression.

Note that a lot of tests are flaky on ARMv7 and care was taken to test each
flaky test before and after the patch to ensure no regression was found.

gdb/ChangeLog:
* NEWS: Add news for tracepoints and software breakpoints.

gdb/gdbserver/ChangeLog:
* linux-arm-low.c (arm_breakpoint_from_length): New function.
(arm_supports_z_point_type): Add software breakpoint support.
(arm_supports_tracepoints): New function.
(struct linux_target_ops): Add arm_supports_tracepoints and
arm_breakpoint_from_length operations.
* linux-low.c (linux_supports_breakpoint_kinds): New function.
(linux_breakpoint_from_length): New function.
* linux-low.h: Add breakpoint_from_length operation.
* mem-break.c (check_breakpoint_from_length): New function.
(insert_memory_breakpoint): Call check_breakpoint_from_length.
(remove_memory_breakpoint): Likewise.
(set_breakpoint_at_with_length): New function.
(validate_inserted_breakpoint): Call check_breakpoint_from_length.
(check_mem_read): Likewise.
(check_mem_write): Likewise.
* mem-break.h: Add set_breakpoint_at_with_length.
* server.c (handle_query): Add TracepointKinds+.
* target.h (struct target_ops): Add breakpoint_from_length and
supports_breakpoint_kinds operations.
* tracepoint.c (struct tracepoint): Add breakpoint_len field.
(add_tracepoint): Add breakpoint_len init.
(cmd_qtdp): Handle :K kind parameter.
(install_tracepoint): Handle breakpoint_len.
(cmd_qtstart): Likewise.
* remote.c (remote_supports_tracepoint_kinds): Add
TracepointKinds packet.
(remote_download_tracepoint): Add breakpoint lenght to :K kind
parameter.

gdb/testsuite/ChangeLog:
* gdb.trace/backtrace.exp: Use sp for fp.
* gdb.trace/collection.exp: Use sp for fp and sip tests that
can't be supported on aarch32.
* gdb.trace/mi-trace-frame-collected.exp: Add aarch32 pc register.
* gdb.trace/pending.exp: Be more permissive on test output in
case of unrelated errors printed to stdout.
* gdb.trace/report.exp: Use sp for fp.
* gdb.trace/trace-break.exp: Add aarch32 sp register.
* gdb.trace/while-dyn.exp: Likewise.

gdb/doc/ChangeLog:
* doc/gdb.texinfo: Add documentation for QTDP kind parameter.
---
gdb/NEWS | 4 ++
gdb/doc/gdb.texinfo | 36 ++++++----
gdb/gdbserver/linux-arm-low.c | 32 ++++++++-
gdb/gdbserver/linux-low.c | 21 +++++-
gdb/gdbserver/linux-low.h | 4 ++
gdb/gdbserver/mem-break.c | 77 +++++++++++++++++++---
gdb/gdbserver/mem-break.h | 6 ++
gdb/gdbserver/server.c | 2 +
gdb/gdbserver/target.h | 12 ++++
gdb/gdbserver/tracepoint.c | 43 ++++++++++--
gdb/remote.c | 34 +++++++++-
gdb/testsuite/gdb.trace/backtrace.exp | 3 +
gdb/testsuite/gdb.trace/collection.exp | 18 ++++-
.../gdb.trace/mi-trace-frame-collected.exp | 2 +
gdb/testsuite/gdb.trace/pending.exp | 6 +-
gdb/testsuite/gdb.trace/report.exp | 4 ++
gdb/testsuite/gdb.trace/trace-break.exp | 2 +
gdb/testsuite/gdb.trace/while-dyn.exp | 2 +
18 files changed, 271 insertions(+), 37 deletions(-)

diff --git a/gdb/NEWS b/gdb/NEWS
index 0cf51e1..085d844 100644
--- a/gdb/NEWS
+++ b/gdb/NEWS
@@ -3,6 +3,10 @@

*** Changes since GDB 7.10

+* Support for tracepoints on aarch32-linux was added in GDBServer.
+
+* Support for software breakpoints on aarch32-linux was added in GDBServer.
+
* Support for tracepoints on aarch64-linux was added in GDBserver.

* The 'record instruction-history' command now indicates speculative execution
diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo
index cd0abad..a604eed 100644
--- a/gdb/doc/gdb.texinfo
+++ b/gdb/doc/gdb.texinfo
@@ -36373,6 +36373,11 @@ These are the currently defined stub features and their properties:
@tab @samp{-}
@tab No

+@item @samp{TracepointKinds}
+@tab No
+@tab @samp{-}
+@tab No
+
@end multitable

These are the currently defined stub features, in more detail:
@@ -36578,6 +36583,9 @@ The remote stub reports the @samp{fork} stop reason for fork events.
The remote stub reports the @samp{vfork} stop reason for vfork events
and vforkdone events.

+@item TracepointKinds
+The remote stub reports the @samp{:K} kind parameter for @samp{QTDP} packets.
+
@end table

@item qSymbol::
@@ -37088,7 +37096,8 @@ details of XML target descriptions for each architecture.
@subsubsection @acronym{ARM} Breakpoint Kinds
@cindex breakpoint kinds, @acronym{ARM}

-These breakpoint kinds are defined for the @samp{Z0} and @samp{Z1} packets.
+These breakpoint kinds are defined for the @samp{Z0}, @samp{Z1}
+and @samp{QTDP} packets.

@table @r

@@ -37168,20 +37177,23 @@ tracepoints (@pxref{Tracepoints}).

@table @samp

-@item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}[:F@var{flen}][:X@var{len},@var{bytes}]@r{[}-@r{]}
+@item QTDP:@var{n}:@var{addr}:@var{ena}:@var{step}:@var{pass}[:F@var{flen}][:X@var{len},@var{bytes}][:K@var{kind}]@r{[}-@r{]}
@cindex @samp{QTDP} packet
Create a new tracepoint, number @var{n}, at @var{addr}. If @var{ena}
is @samp{E}, then the tracepoint is enabled; if it is @samp{D}, then
-the tracepoint is disabled. The @var{step} gives the tracepoint's step
-count, and @var{pass} gives its pass count. If an @samp{F} is present,
-then the tracepoint is to be a fast tracepoint, and the @var{flen} is
-the number of bytes that the target should copy elsewhere to make room
-for the tracepoint. If an @samp{X} is present, it introduces a
-tracepoint condition, which consists of a hexadecimal length, followed
-by a comma and hex-encoded bytes, in a manner similar to action
-encodings as described below. If the trailing @samp{-} is present,
-further @samp{QTDP} packets will follow to specify this tracepoint's
-actions.
+the tracepoint is disabled. The @var{step} gives the tracepoint's
+step count, and @var{pass} gives its pass count. If an @samp{F} is
+present, then the tracepoint is to be a fast tracepoint, and the
+@var{flen} is the number of bytes that the target should copy
+elsewhere to make room for the tracepoint. If an @samp{X} is present,
+it introduces a tracepoint condition, which consists of a hexadecimal
+length, followed by a comma and hex-encoded bytes, in a manner similar
+to action encodings as described below. If a @samp{K} is present, it
+indicates a target specific breakpoint length. E.g., the arm and mips
+can insert either a 2 or 4 byte breakpoint. Some architectures have
+additional meanings for kind see : @ref{Architecture-Specific Protocol
+Details} . If the trailing @samp{-} is present, further @samp{QTDP}
+packets will follow to specify this tracepoint's actions.

Replies:
@table @samp
diff --git a/gdb/gdbserver/linux-arm-low.c b/gdb/gdbserver/linux-arm-low.c
index a9ed91d..86df966 100644
--- a/gdb/gdbserver/linux-arm-low.c
+++ b/gdb/gdbserver/linux-arm-low.c
@@ -438,6 +438,28 @@ arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
}
}

+/* Get the breakpoint from the remote length
+ 2 is thumb-16
+ 3 is thumb2-32
+ 4 is arm
+*/
+static const unsigned char *
+arm_breakpoint_from_length (int *len)
+{
+ switch (*len) {
+ case 2:
+ return thumb_breakpoint;
+ case 3:
+ *len = 4;
+ return thumb2_breakpoint;
+ case 4:
+ return arm_breakpoint;
+ default:
+ return NULL;
+ }
+ return NULL;
+}
+
/* Sets the breakpoints to the endianness in argument. */

static void
@@ -769,6 +791,7 @@ arm_supports_z_point_type (char z_type)
{
switch (z_type)
{
+ case Z_PACKET_SW_BP:
case Z_PACKET_HW_BP:
case Z_PACKET_WRITE_WP:
case Z_PACKET_READ_WP:
@@ -1167,6 +1190,12 @@ arm_regs_info (void)
return &regs_info_arm;
}

+static int
+arm_supports_tracepoints (void)
+{
+ return 1;
+}
+
struct linux_target_ops the_low_target = {
arm_arch_setup,
arm_regs_info,
@@ -1192,13 +1221,14 @@ struct linux_target_ops the_low_target = {
arm_new_fork,
arm_prepare_to_resume,
NULL, /* process_qsupported */
- NULL, /* supports_tracepoints */
+ arm_supports_tracepoints,
NULL, /* get_thread_area */
NULL, /* install_fast_tracepoint_jump_pad */
NULL, /* emit_ops */
NULL, /* get_min_fast_tracepoint_insn_len */
NULL, /* supports_range_stepping */
arm_supports_hardware_single_step,
+ arm_breakpoint_from_length
};

void
diff --git a/gdb/gdbserver/linux-low.c b/gdb/gdbserver/linux-low.c
index f19769d..495181d 100644
--- a/gdb/gdbserver/linux-low.c
+++ b/gdb/gdbserver/linux-low.c
@@ -313,8 +313,14 @@ supports_fast_tracepoints (void)
return the_low_target.install_fast_tracepoint_jump_pad != NULL;
}

-/* True if LWP is stopped in its stepping range. */
+/* True if a breakpoint/tracepoint can differ based on kind/length. */
+static int
+linux_supports_breakpoint_kinds (void)
+{
+ return the_low_target.breakpoint_from_length != NULL;
+}

+/* True if LWP is stopped in its stepping range. */
static int
lwp_in_step_range (struct lwp_info *lwp)
{
@@ -5998,6 +6004,17 @@ linux_supports_range_stepping (void)
return (*the_low_target.supports_range_stepping) ();
}

+static const unsigned char*
+linux_breakpoint_from_length (int *len)
+{
+ if (*the_low_target.breakpoint_from_length != NULL)
+ {
+ return (*the_low_target.breakpoint_from_length) (len);
+ }
+ else
+ return NULL;
+
+}
/* Enumerate spufs IDs for process PID. */
static int
spu_enumerate_spu_ids (long pid, unsigned char *buf, CORE_ADDR offset, int len)
@@ -7095,6 +7112,8 @@ static struct target_ops linux_target_ops = {
linux_mntns_readlink,
linux_breakpoint_from_pc,
linux_supports_software_single_step,
+ linux_breakpoint_from_length,
+ linux_supports_breakpoint_kinds
};

static void
diff --git a/gdb/gdbserver/linux-low.h b/gdb/gdbserver/linux-low.h
index b6f8175..913021a 100644
--- a/gdb/gdbserver/linux-low.h
+++ b/gdb/gdbserver/linux-low.h
@@ -243,6 +243,10 @@ struct linux_target_ops

/* Returns true if the low target supports hardware single step. */
int (*supports_hardware_single_step) (void);
+
+ /* Returns the proper breakpoint from size, the length can have target
+ specific meaning like the z0 or QTDP kind parameter */
+ const unsigned char *(*breakpoint_from_length) (int *length);
};

extern struct linux_target_ops the_low_target;
diff --git a/gdb/gdbserver/mem-break.c b/gdb/gdbserver/mem-break.c
index 1a87d01..bc793e9 100644
--- a/gdb/gdbserver/mem-break.c
+++ b/gdb/gdbserver/mem-break.c
@@ -295,6 +295,36 @@ find_raw_breakpoint_at (CORE_ADDR addr, enum raw_bkpt_type type, int size)
return NULL;
}

+int
+check_breakpoint_from_length (struct raw_breakpoint *bp,
+ const unsigned char **breakpoint_data,
+ int *breakpoint_len)
+{
+ /* If the architecture treats the size field of Z packets as a
+ 'kind' field, then we'll need to be able to know which is the
+ breakpoint instruction too. This is also true for tracepoint kind
+ field. */
+ if (bp->size != *breakpoint_len)
+ {
+ /* Get the arch dependent breakpoint */
+ if (*the_target->breakpoint_from_length != NULL)
+ {
+ /* Update magic coded size to the right size if needed. */
+ int size = bp->size;
+ *breakpoint_data =
+ (*the_target->breakpoint_from_length) (&size);
+ *breakpoint_len = size;
+ }
+ else {
+ if (debug_threads)
+ debug_printf ("Don't know breakpoints of size %d.\n",
+ bp->size);
+ return -1;
+ }
+ }
+
+ return 1;
+}
/* See mem-break.h. */

int
@@ -312,16 +342,9 @@ insert_memory_breakpoint (struct raw_breakpoint *bp)
if (breakpoint_data == NULL)
return 1;

- /* If the architecture treats the size field of Z packets as a
- 'kind' field, then we'll need to be able to know which is the
- breakpoint instruction too. */
- if (bp->size != breakpoint_len)
- {
- if (debug_threads)
- debug_printf ("Don't know how to insert breakpoints of size %d.\n",
- bp->size);
- return -1;
- }
+ if ((err = check_breakpoint_from_length (bp, &breakpoint_data,
+ &breakpoint_len)) < 0)
+ return err;

/* Note that there can be fast tracepoint jumps installed in the
same memory range, so to get at the original memory, we need to
@@ -356,6 +379,7 @@ int
remove_memory_breakpoint (struct raw_breakpoint *bp)
{
unsigned char buf[MAX_BREAKPOINT_LEN];
+ const unsigned char* breakpoint_data;
int err;
int breakpoint_len;
CORE_ADDR pc;
@@ -363,6 +387,10 @@ remove_memory_breakpoint (struct raw_breakpoint *bp)
pc = bp->pcfull;
the_target->breakpoint_from_pc (&pc, &breakpoint_len);

+ if ((err = check_breakpoint_from_length (bp, &breakpoint_data,
+ &breakpoint_len)) < 0)
+ return err;
+
/* Since there can be trap breakpoints inserted in the same address
range, we use `write_inferior_memory', which takes care of
layering breakpoints on top of fast tracepoints, and on top of
@@ -806,6 +834,17 @@ set_breakpoint_at (CORE_ADDR where, int (*handler) (CORE_ADDR))
&err_ignored);
}

+struct breakpoint *
+set_breakpoint_at_with_length (CORE_ADDR where, int (*handler) (CORE_ADDR),
+ int size)
+{
+ int err_ignored;
+
+ return set_breakpoint (other_breakpoint, raw_bkpt_type_sw,
+ where, size, handler,
+ &err_ignored);
+}
+

static int
delete_raw_breakpoint (struct process_info *proc, struct raw_breakpoint *todel)
@@ -1710,6 +1749,14 @@ validate_inserted_breakpoint (struct raw_breakpoint *bp)

breakpoint_data = the_target->breakpoint_from_pc (&raw_pc, &breakpoint_len);

+ if ((err = check_breakpoint_from_length (bp, &breakpoint_data,
+ &breakpoint_len)) < 0)
+ {
+ /* Tag it as gone. */
+ bp->inserted = -1;
+ return 0;
+ }
+
gdb_assert (bp->inserted);
gdb_assert (bp->raw_type == raw_bkpt_type_sw);

@@ -1808,11 +1855,16 @@ check_mem_read (CORE_ADDR mem_addr, unsigned char *buf, int mem_len)
{
int breakpoint_len;
CORE_ADDR raw_pc;
+ const unsigned char* breakpoint_data;
CORE_ADDR bp_end, start, end;
int copy_offset, copy_len, buf_offset;

raw_pc = bp->pcfull;
+
the_target->breakpoint_from_pc (&raw_pc, &breakpoint_len);
+ check_breakpoint_from_length (bp, &breakpoint_data,
+ &breakpoint_len);
+
bp_end = bp->pc + breakpoint_len;

if (bp->raw_type != raw_bkpt_type_sw)
@@ -1907,8 +1959,13 @@ check_mem_write (CORE_ADDR mem_addr, unsigned char *buf,
int copy_offset, copy_len, buf_offset;

raw_pc = bp->pcfull;
+
breakpoint_data =
the_target->breakpoint_from_pc (&raw_pc, &breakpoint_len);
+
+ check_breakpoint_from_length (bp, &breakpoint_data,
+ &breakpoint_len);
+
bp_end = bp->pc + breakpoint_len;

if (bp->raw_type != raw_bkpt_type_sw)
diff --git a/gdb/gdbserver/mem-break.h b/gdb/gdbserver/mem-break.h
index b1bb91a..ec28998 100644
--- a/gdb/gdbserver/mem-break.h
+++ b/gdb/gdbserver/mem-break.h
@@ -146,6 +146,12 @@ int gdb_breakpoint_here (CORE_ADDR where);
struct breakpoint *set_breakpoint_at (CORE_ADDR where,
int (*handler) (CORE_ADDR));

+/* Same as set_breakpoint_at but allow the length to be specified */
+struct breakpoint *set_breakpoint_at_with_length (CORE_ADDR where,
+ int (*handler)(CORE_ADDR),
+ int size);
+
+
/* Delete a breakpoint. */

int delete_breakpoint (struct breakpoint *bkpt);
diff --git a/gdb/gdbserver/server.c b/gdb/gdbserver/server.c
index fb0e843..40d4e78 100644
--- a/gdb/gdbserver/server.c
+++ b/gdb/gdbserver/server.c
@@ -2190,6 +2190,8 @@ handle_query (char *own_buf, int packet_len, int *new_packet_len_p)
strcat (own_buf, ";EnableDisableTracepoints+");
strcat (own_buf, ";QTBuffer:size+");
strcat (own_buf, ";tracenz+");
+ if (target_supports_breakpoint_kinds ())
+ strcat (own_buf, ";TracepointKinds+");
}

if (target_supports_hardware_single_step () ||
diff --git a/gdb/gdbserver/target.h b/gdb/gdbserver/target.h
index aa40c4a..a076fb4 100644
--- a/gdb/gdbserver/target.h
+++ b/gdb/gdbserver/target.h
@@ -446,6 +446,14 @@ struct target_ops

/* Returns true if the target can do software single step. */
int (*supports_software_single_step) (void);
+
+ /* Returns a breakpoint from a length, the length can have target specific
+ meaning like the z0 kind parameter. */
+ const unsigned char *(*breakpoint_from_length) (int *len);
+
+ /* Returns wether target supports breakpoints kinds like is sent
+ via a QTDP :K packet. */
+ int (*supports_breakpoint_kinds) (void);
};

extern struct target_ops *the_target;
@@ -628,6 +636,10 @@ int kill_inferior (int);
(the_target->supports_software_single_step ? \
(*the_target->supports_software_single_step) () : 0)

+#define target_supports_breakpoint_kinds() \
+ (the_target->supports_breakpoint_kinds ? \
+ (*the_target->supports_breakpoint_kinds) () : 0)
+
/* Start non-stop mode, returns 0 on success, -1 on failure. */

int start_non_stop (int nonstop);
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index fd010ae..6d1eece 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -754,6 +754,11 @@ struct tracepoint
/* Link to the next tracepoint in the list. */
struct tracepoint *next;

+ /* Optional length of the breakpoint to be used
+ note this can mean different things for different archs as z0
+ breakpoint command */
+ uint32_t breakpoint_len;
+
#ifndef IN_PROCESS_AGENT
/* The list of actions to take when the tracepoint triggers, in
string/packet form. */
@@ -1820,6 +1825,7 @@ add_tracepoint (int num, CORE_ADDR addr)
tpoint->compiled_cond = 0;
tpoint->handle = NULL;
tpoint->next = NULL;
+ tpoint->breakpoint_len = 0;

/* Find a place to insert this tracepoint into list in order to keep
the tracepoint list still in the ascending order. There may be
@@ -2487,6 +2493,7 @@ cmd_qtdp (char *own_buf)
ULONGEST num;
ULONGEST addr;
ULONGEST count;
+ ULONGEST breakpoint_len;
struct tracepoint *tpoint;
char *actparm;
char *packet = own_buf;
@@ -2553,6 +2560,12 @@ cmd_qtdp (char *own_buf)
tpoint->cond = gdb_parse_agent_expr (&actparm);
packet = actparm;
}
+ else if (*packet == 'K')
+ {
+ ++packet;
+ packet = unpack_varlen_hex (packet, &breakpoint_len);
+ tpoint->breakpoint_len = breakpoint_len;
+ }
else if (*packet == '-')
break;
else if (*packet == '\0')
@@ -2567,11 +2580,13 @@ cmd_qtdp (char *own_buf)
}

trace_debug ("Defined %stracepoint %d at 0x%s, "
- "enabled %d step %" PRIu64 " pass %" PRIu64,
+ "enabled %d step %" PRIu64 " pass %" PRIu64
+ " length %" PRIu32,
tpoint->type == fast_tracepoint ? "fast "
: tpoint->type == static_tracepoint ? "static " : "",
tpoint->number, paddress (tpoint->address), tpoint->enabled,
- tpoint->step_count, tpoint->pass_count);
+ tpoint->step_count,tpoint->pass_count,
+ tpoint->breakpoint_len);
}
else if (tpoint)
add_tracepoint_action (tpoint, packet);
@@ -3148,9 +3163,17 @@ install_tracepoint (struct tracepoint *tpoint, char *own_buf)
/* Tracepoints are installed as memory breakpoints. Just go
ahead and install the trap. The breakpoints module
handles duplicated breakpoints, and the memory read
- routine handles un-patching traps from memory reads. */
- tpoint->handle = set_breakpoint_at (tpoint->address,
+ routine handles un-patching traps from memory reads.
+ If breakpoint_len is not set, use the default breakpoint len values
+ otherwise what was set from the gdb client will be used.*/
+ if (tpoint->breakpoint_len == 0)
+ tpoint->handle = set_breakpoint_at (tpoint->address,
tracepoint_handler);
+ else
+ tpoint->handle =
+ set_breakpoint_at_with_length (tpoint->address,
+ tracepoint_handler,
+ tpoint->breakpoint_len);
}
else if (tpoint->type == fast_tracepoint || tpoint->type == static_tracepoint)
{
@@ -3243,8 +3266,16 @@ cmd_qtstart (char *packet)
ahead and install the trap. The breakpoints module
handles duplicated breakpoints, and the memory read
routine handles un-patching traps from memory reads. */
- tpoint->handle = set_breakpoint_at (tpoint->address,
- tracepoint_handler);
+
+
+ if (tpoint->breakpoint_len == 0)
+ tpoint->handle = set_breakpoint_at (tpoint->address,
+ tracepoint_handler);
+ else
+ tpoint->handle =
+ set_breakpoint_at_with_length (tpoint->address,
+ tracepoint_handler,
+ tpoint->breakpoint_len);
}
else if (tpoint->type == fast_tracepoint
|| tpoint->type == static_tracepoint)
diff --git a/gdb/remote.c b/gdb/remote.c
index 3afcaf4..67daf70 100644
--- a/gdb/remote.c
+++ b/gdb/remote.c
@@ -230,6 +230,8 @@ static int stop_reply_queue_length (void);

static void readahead_cache_invalidate (void);

+static int remote_supports_tracepoint_kinds (void);
+
/* For "remote". */

static struct cmd_list_element *remote_cmdlist;
@@ -1401,6 +1403,9 @@ enum {
/* Support for the Qbtrace-conf:pt:size packet. */
PACKET_Qbtrace_conf_pt_size,

+ /* Support target dependant tracepoint kinds. */
+ PACKET_TracepointKinds,
+
PACKET_MAX
};

@@ -4280,7 +4285,9 @@ static const struct protocol_feature remote_protocol_features[] = {
{ "vfork-events", PACKET_DISABLE, remote_supported_packet,
PACKET_vfork_event_feature },
{ "Qbtrace-conf:pt:size", PACKET_DISABLE, remote_supported_packet,
- PACKET_Qbtrace_conf_pt_size }
+ PACKET_Qbtrace_conf_pt_size },
+ { "TracepointKinds", PACKET_DISABLE, remote_supported_packet,
+ PACKET_TracepointKinds }
};

static char *remote_support_xml;
@@ -11282,6 +11289,12 @@ remote_can_run_breakpoint_commands (struct target_ops *self)
return packet_support (PACKET_BreakpointCommands) == PACKET_ENABLE;
}

+static int
+remote_supports_tracepoint_kinds (void)
+{
+ return packet_support (PACKET_TracepointKinds) == PACKET_ENABLE;
+}
+
static void
remote_trace_init (struct target_ops *self)
{
@@ -11370,6 +11383,7 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
char *pkt;
struct breakpoint *b = loc->owner;
struct tracepoint *t = (struct tracepoint *) b;
+ int bpsize;

encode_actions_rsp (loc, &tdp_actions, &stepping_actions);
old_chain = make_cleanup (free_actions_list_cleanup_wrapper,
@@ -11378,11 +11392,17 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
stepping_actions);

tpaddr = loc->address;
+
+ /* The length field should be set to the size of a breakpoint
+ instruction, even though we aren't inserting one ourselves. */
+ gdbarch_remote_breakpoint_from_pc (target_gdbarch(), &tpaddr, &bpsize);
+
sprintf_vma (addrbuf, tpaddr);
xsnprintf (buf, BUF_SIZE, "QTDP:%x:%s:%c:%lx:%x", b->number,
addrbuf, /* address */
(b->enable_state == bp_enabled ? 'E' : 'D'),
t->step_count, t->pass_count);
+
/* Fast tracepoints are mostly handled by the target, but we can
tell the target how big of an instruction block should be moved
around. */
@@ -11452,6 +11472,14 @@ remote_download_tracepoint (struct target_ops *self, struct bp_location *loc)
"ignoring tp %d cond"), b->number);
}

+ /* Tracepoint Kinds are modeled after the breakpoint Z0 kind packet.
+ Send the tracepoint kind if we support it. */
+ if (remote_supports_tracepoint_kinds ())
+ {
+ xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":K%x",
+ bpsize);
+ }
+
if (b->commands || *default_collect)
strcat (buf, "-");
putpkt (buf);
@@ -13272,6 +13300,10 @@ Show the maximum size of the address (in bits) in a memory packet."), NULL,
add_packet_config_cmd (&remote_protocol_packets[PACKET_Qbtrace_conf_pt_size],
"Qbtrace-conf:pt:size", "btrace-conf-pt-size", 0);

+ add_packet_config_cmd (&remote_protocol_packets[PACKET_TracepointKinds],
+ "TracepointKinds",
+ "tracepoint-kinds", 0);
+
/* Assert that we've registered "set remote foo-packet" commands
for all packet configs. */
{
diff --git a/gdb/testsuite/gdb.trace/backtrace.exp b/gdb/testsuite/gdb.trace/backtrace.exp
index f69089b..6635de1 100644
--- a/gdb/testsuite/gdb.trace/backtrace.exp
+++ b/gdb/testsuite/gdb.trace/backtrace.exp
@@ -146,6 +146,9 @@ if [is_amd64_regs_target] {
} elseif [is_x86_like_target] {
set fpreg "\$ebp"
set spreg "\$esp"
+} elseif [is_aarch32_target] {
+ set fpreg "\$sp"
+ set spreg "\$sp"
} elseif [is_aarch64_target] {
set fpreg "\$x29"
set spreg "\$sp"
diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp
index 69ad6ee..60c1278 100644
--- a/gdb/testsuite/gdb.trace/collection.exp
+++ b/gdb/testsuite/gdb.trace/collection.exp
@@ -44,6 +44,10 @@ if [is_amd64_regs_target] {
set fpreg "ebp"
set spreg "esp"
set pcreg "eip"
+} elseif [is_aarch32_target] {
+ set fpreg "sp"
+ set spreg "sp"
+ set pcreg "pc"
} elseif [is_aarch64_target] {
set fpreg "x29"
set spreg "sp"
@@ -696,11 +700,16 @@ proc gdb_trace_collection_test {} {
gdb_collect_locals_test local_test_func \
"locc, loci, locf, locd, locst, locar" \
"auto locals individually"
- gdb_collect_locals_test reglocal_test_func "\$locals" \
+
+ #Some registers can't be read on ARM , skip those tests
+ if { ![is_aarch32_target] } {
+ gdb_collect_locals_test reglocal_test_func "\$locals" \
"register locals collectively"
- gdb_collect_locals_test reglocal_test_func \
+ gdb_collect_locals_test reglocal_test_func \
"locc, loci, locf, locd, locst, locar" \
"register locals individually"
+ }
+
gdb_collect_locals_test statlocal_test_func "\$locals" \
"static locals collectively"
gdb_collect_locals_test statlocal_test_func \
@@ -782,7 +791,10 @@ proc gdb_trace_collection_test {} {
gdb_collect_expression_test globals_test_func \
"globalarr\[\(l6, l7\)\]" "7" "a\[\(b, c\)\]"

- gdb_collect_return_test
+ #This architecture has no method to collect a return address.
+ if { ![is_aarch32_target] } {
+ gdb_collect_return_test
+ }

gdb_collect_strings_test strings_test_func "locstr" "abcdef" "" \
"local string"
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index a7bed0b..cc36a2d 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
@@ -56,6 +56,8 @@ if [is_amd64_regs_target] {
set pcreg "rip"
} elseif [is_x86_like_target] {
set pcreg "eip"
+} elseif [is_aarch32_target] {
+ set pcreg "pc"
} elseif [is_aarch64_target] {
set pcreg "pc"
} else {
diff --git a/gdb/testsuite/gdb.trace/pending.exp b/gdb/testsuite/gdb.trace/pending.exp
index 9938c5a..33a8609 100644
--- a/gdb/testsuite/gdb.trace/pending.exp
+++ b/gdb/testsuite/gdb.trace/pending.exp
@@ -159,7 +159,7 @@ proc pending_tracepoint_works { trace_type } {

gdb_test "tstop" "\[\r\n\]+" "stop trace experiment"

- gdb_test "tfind start" "#0 .*" "tfind test frame 0"
+ gdb_test "tfind start" ".*Found trace frame 0.*" "tfind test frame 0"
gdb_test "tfind" "Found trace frame 1, tracepoint 1.*" \
"tfind test frame 1"
gdb_test "tfind" "Found trace frame 2, tracepoint 1.*" \
@@ -234,7 +234,7 @@ proc pending_tracepoint_resolved_during_trace { trace_type } \
\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*pendfunc2.*" \
"tracepoint is resolved"

- gdb_test "tfind start" "#0 .*" "tfind test frame 0"
+ gdb_test "tfind start" ".*Found trace frame 0.*" "tfind test frame 0"
gdb_test "tfind" "Target failed to find requested trace frame..*" "tfind test frame"
}}

@@ -307,7 +307,7 @@ proc pending_tracepoint_installed_during_trace { trace_type } \
\[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \]+keep y.*pendfunc2.*" \
"tracepoint is resolved"

- gdb_test "tfind start" "#0 $hex in pendfunc2 .*" "tfind test frame 0"
+ gdb_test "tfind start" ".*$hex in pendfunc2 .*" "tfind test frame 0"
gdb_test "tfind" "Target failed to find requested trace frame..*" "tfind test frame"
}}

diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
index b3e9000..e48f696 100644
--- a/gdb/testsuite/gdb.trace/report.exp
+++ b/gdb/testsuite/gdb.trace/report.exp
@@ -158,6 +158,10 @@ if [is_amd64_regs_target] {
set fpreg "ebp"
set spreg "esp"
set pcreg "eip"
+} elseif [is_aarch32_target] {
+ set fpreg "sp"
+ set spreg "sp"
+ set pcreg "pc"
} elseif [is_aarch64_target] {
set fpreg "x29"
set spreg "sp"
diff --git a/gdb/testsuite/gdb.trace/trace-break.exp b/gdb/testsuite/gdb.trace/trace-break.exp
index 1f57601..e7dd5d0 100644
--- a/gdb/testsuite/gdb.trace/trace-break.exp
+++ b/gdb/testsuite/gdb.trace/trace-break.exp
@@ -49,6 +49,8 @@ if [is_amd64_regs_target] {
set fpreg "ebp"
set spreg "esp"
set pcreg "eip"
+} elseif [is_aarch32_target] {
+ set fpreg "sp"
} elseif [is_aarch64_target] {
set fpreg "x29"
}
diff --git a/gdb/testsuite/gdb.trace/while-dyn.exp b/gdb/testsuite/gdb.trace/while-dyn.exp
index fe4535e..5b9713f 100644
--- a/gdb/testsuite/gdb.trace/while-dyn.exp
+++ b/gdb/testsuite/gdb.trace/while-dyn.exp
@@ -47,6 +47,8 @@ if [is_amd64_regs_target] {
set fpreg "\$rbp"
} elseif [is_x86_like_target] {
set fpreg "\$ebp"
+} elseif [is_aarch32_target] {
+ set fpreg "\$sp"
} elseif [is_aarch64_target] {
set fpreg "\$x29"
} else {
--
1.9.1