public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 1/5 v4] Remove tracepoint_action ops.
@ 2015-06-27 16:21 Wei-cheng Wang
  2015-06-27 16:22 ` [PATCH 5/5 v4] Allow target to decide where to map jump-pad Wei-cheng Wang
                   ` (4 more replies)
  0 siblings, 5 replies; 17+ messages in thread
From: Wei-cheng Wang @ 2015-06-27 16:21 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

Hi,

Ulrich Weigand wrote:
> It would be good to verify this doesn't break Intel by running the
> regression test suite there.

The testing result on my x86_64 Ubuntu 14.04.2

              before   after
  PASS         2625     2625
  FAIL           33       33
  XFAIL          16       16
  KFAIL           2        2
  UNTESTED        1        1
  UNSUPPORTED     3        3

Ulrich Weigand wrote:
> I guess there's not much need to have these "size_in_ipa" variables
> any more, subsequent code might as well just use the sizeof directly.

Ok, I have replaced all the "size_in_ipa" to just sizeof.

Thanks,
Wei-cheng

---
This patch removes 'ops' in tracepoint, and uses helper functions to
call action handler instead.

The object layout of tracepoint_action may differ in gdbserver and
inferior depend on the alignment rule of target ABI, so gdbserver cannot
simply copy the object from its memory to inferior memory.

For example,

  struct collect_memory_action
  {
    struct tracepoint_action base;
    {
      #ifndef IN_PROCESS_AGENT
      const struct tracepoint_action_ops *ops;
      #if
  -   char type;
  | }
  | ULONGEST addr;
  | ULONGEST len;
  - int32_t basereg;
  };

and on PowerPC,

     Wihtout ops           with ops
      0   1   2   3         0   1   2   3
   0 |type| PADDING...    0 |ops-------------|
   4 .................    4 |type|PADDING....|
   8 |addr------------    8 |addr-------------
   c ----------------|    c -----------------|
  10 |len-------------   10 |len--------------
  14 ----------------|   14 -----------------|
  18 |basereg--------|   18 |basereg---------|

so we cannot directly copy the object.

In this patch, 'ops' is removed in order to make the objects identical.

gdbserver/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* tracepoint.c (struct tracepoint_action): Remove ops.
	(m_tracepoint_action_download, r_tracepoint_action_download,
	x_tracepoint_action_download, l_tracepoint_action_download): Adjust
	size and offset accordingly.
	(m_tracepoint_action_ops, r_tracepoint_action_ops,
	x_tracepoint_action_ops, l_tracepoint_action_ops): Delete
	(tracepoint_action_send, tracepoint_action_download): New functions.
	Helpers for tracetion action handlers.
	(add_tracepoint_action): Remove setup actions ops.
	(download_tracepoint_1, tracepoint_send_agent): Call helper functions.
---
 gdb/gdbserver/tracepoint.c | 103 +++++++++++++++++++++------------------------
 1 file changed, 49 insertions(+), 54 deletions(-)

diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index a934866..57b329d9 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -483,9 +483,6 @@ struct tracepoint_action_ops
 
 struct tracepoint_action
 {
-#ifndef IN_PROCESS_AGENT
-  const struct tracepoint_action_ops *ops;
-#endif
   char type;
 };
 
@@ -525,12 +522,10 @@ struct collect_static_trace_data_action
 static CORE_ADDR
 m_tracepoint_action_download (const struct tracepoint_action *action)
 {
-  int size_in_ipa = (sizeof (struct collect_memory_action)
-		     - offsetof (struct tracepoint_action, type));
-  CORE_ADDR ipa_action = target_malloc (size_in_ipa);
+  CORE_ADDR ipa_action = target_malloc (sizeof (struct collect_memory_action));
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			 size_in_ipa);
+  write_inferior_memory (ipa_action, (unsigned char *) action,
+			 sizeof (struct collect_memory_action));
 
   return ipa_action;
 }
@@ -547,21 +542,13 @@ m_tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
   return buffer;
 }
 
-static const struct tracepoint_action_ops m_tracepoint_action_ops =
-{
-  m_tracepoint_action_download,
-  m_tracepoint_action_send,
-};
-
 static CORE_ADDR
 r_tracepoint_action_download (const struct tracepoint_action *action)
 {
-  int size_in_ipa = (sizeof (struct collect_registers_action)
-		     - offsetof (struct tracepoint_action, type));
-  CORE_ADDR ipa_action  = target_malloc (size_in_ipa);
+  CORE_ADDR ipa_action  = target_malloc (sizeof (struct collect_registers_action));
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			size_in_ipa);
+  write_inferior_memory (ipa_action, (unsigned char *) action,
+			 sizeof (struct collect_registers_action));
 
   return ipa_action;
 }
@@ -572,28 +559,19 @@ r_tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
   return buffer;
 }
 
-static const struct tracepoint_action_ops r_tracepoint_action_ops =
-{
-  r_tracepoint_action_download,
-  r_tracepoint_action_send,
-};
-
 static CORE_ADDR download_agent_expr (struct agent_expr *expr);
 
 static CORE_ADDR
 x_tracepoint_action_download (const struct tracepoint_action *action)
 {
-  int size_in_ipa = (sizeof (struct eval_expr_action)
-		     - offsetof (struct tracepoint_action, type));
-  CORE_ADDR ipa_action = target_malloc (size_in_ipa);
+  CORE_ADDR ipa_action = target_malloc (sizeof (struct eval_expr_action));
   CORE_ADDR expr;
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			 size_in_ipa);
-  expr = download_agent_expr (((struct eval_expr_action *)action)->expr);
+  write_inferior_memory (ipa_action, (unsigned char *) action,
+			 sizeof (struct eval_expr_action));
+  expr = download_agent_expr (((struct eval_expr_action *) action)->expr);
   write_inferior_data_pointer (ipa_action
-			       + offsetof (struct eval_expr_action, expr)
-			       - offsetof (struct tracepoint_action, type),
+			       + offsetof (struct eval_expr_action, expr),
 			       expr);
 
   return ipa_action;
@@ -631,21 +609,14 @@ x_tracepoint_action_send ( char *buffer, const struct tracepoint_action *action)
   return agent_expr_send (buffer, eaction->expr);
 }
 
-static const struct tracepoint_action_ops x_tracepoint_action_ops =
-{
-  x_tracepoint_action_download,
-  x_tracepoint_action_send,
-};
-
 static CORE_ADDR
 l_tracepoint_action_download (const struct tracepoint_action *action)
 {
-  int size_in_ipa = (sizeof (struct collect_static_trace_data_action)
-		     - offsetof (struct tracepoint_action, type));
-  CORE_ADDR ipa_action = target_malloc (size_in_ipa);
+  CORE_ADDR ipa_action =
+    target_malloc (sizeof (struct collect_static_trace_data_action));
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			 size_in_ipa);
+  write_inferior_memory (ipa_action, (unsigned char *) action,
+			 sizeof (struct collect_static_trace_data_action));
 
   return ipa_action;
 }
@@ -656,11 +627,39 @@ l_tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
   return buffer;
 }
 
-static const struct tracepoint_action_ops l_tracepoint_action_ops =
+static char *
+tracepoint_action_send (char *buffer, const struct tracepoint_action *action)
 {
-  l_tracepoint_action_download,
-  l_tracepoint_action_send,
-};
+  switch (action->type)
+    {
+    case 'M':
+      return m_tracepoint_action_send (buffer, action);
+    case 'R':
+      return r_tracepoint_action_send (buffer, action);
+    case 'X':
+      return x_tracepoint_action_send (buffer, action);
+    case 'L':
+      return l_tracepoint_action_send (buffer, action);
+    }
+  error ("Unknown trace action '%c'.", action->type);
+}
+
+static CORE_ADDR
+tracepoint_action_download (const struct tracepoint_action *action)
+{
+  switch (action->type)
+    {
+    case 'M':
+      return m_tracepoint_action_download (action);
+    case 'R':
+      return r_tracepoint_action_download (action);
+    case 'X':
+      return x_tracepoint_action_download (action);
+    case 'L':
+      return l_tracepoint_action_download (action);
+    }
+  error ("Unknown trace action '%c'.", action->type);
+}
 #endif
 
 /* This structure describes a piece of the source-level definition of
@@ -1944,7 +1943,6 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
 	    maction = xmalloc (sizeof *maction);
 	    maction->base.type = *act;
-	    maction->base.ops = &m_tracepoint_action_ops;
 	    action = &maction->base;
 
 	    ++act;
@@ -1970,7 +1968,6 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
 	    raction = xmalloc (sizeof *raction);
 	    raction->base.type = *act;
-	    raction->base.ops = &r_tracepoint_action_ops;
 	    action = &raction->base;
 
 	    trace_debug ("Want to collect registers");
@@ -1986,7 +1983,6 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
 	    raction = xmalloc (sizeof *raction);
 	    raction->base.type = *act;
-	    raction->base.ops = &l_tracepoint_action_ops;
 	    action = &raction->base;
 
 	    trace_debug ("Want to collect static trace data");
@@ -2003,7 +1999,6 @@ add_tracepoint_action (struct tracepoint *tpoint, char *packet)
 
 	    xaction = xmalloc (sizeof (*xaction));
 	    xaction->base.type = *act;
-	    xaction->base.ops = &x_tracepoint_action_ops;
 	    action = &xaction->base;
 
 	    trace_debug ("Want to evaluate expression");
@@ -6046,7 +6041,7 @@ download_tracepoint_1 (struct tracepoint *tpoint)
       for (i = 0; i < tpoint->numactions; i++)
 	{
 	  struct tracepoint_action *action = tpoint->actions[i];
-	  CORE_ADDR ipa_action = action->ops->download (action);
+	  CORE_ADDR ipa_action = tracepoint_action_download (action);
 
 	  if (ipa_action != 0)
 	    write_inferior_data_pointer
@@ -6096,7 +6091,7 @@ tracepoint_send_agent (struct tracepoint *tpoint)
       struct tracepoint_action *action = tpoint->actions[i];
 
       p[0] = action->type;
-      p = action->ops->send (&p[1], action);
+      p = tracepoint_action_send (&p[1], action);
     }
 
   get_jump_space_head ();
-- 
1.9.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 4/5 v4] Tracepoint for ppc64.
  2015-06-27 16:21 [PATCH 1/5 v4] Remove tracepoint_action ops Wei-cheng Wang
                   ` (2 preceding siblings ...)
  2015-06-27 16:22 ` [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver Wei-cheng Wang
@ 2015-06-27 16:22 ` Wei-cheng Wang
  2015-06-28  6:21   ` Wei-cheng Wang
                     ` (2 more replies)
  2015-06-30  9:57 ` [PATCH 1/5 v4] Remove tracepoint_action ops Pedro Alves
  4 siblings, 3 replies; 17+ messages in thread
From: Wei-cheng Wang @ 2015-06-27 16:22 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

Hi,

The main patch for tracepoint for ppc64 and snippets for
enabling tracepoint tests.

Ulrich Weigand wrote:
> I think if there is no benefit in having this code on the GDB side,
> it would be better to move it to gdbsever.  (Potential benefits could
> be: we need information that isn't available in gdbserver, like symbol
> data; or the code can be shared with other users if in GDB.  But on
> PowerPC, I think none of this applies.)

relocate_instruction is removed from rs6000-tdep.c and move to gdbserver side.

Ulrich Weigand wrote:
> Wei-cheng Wang wrote:
> > Ulrich Weigand wrote:
> > >Wei-cheng Wang wrote:
> > >> +static int
> > >> +ppc_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
> > >> +                        CORE_ADDR addr, int *isize, char **msg)
> > >> +{
> > >> +  if (isize)
> > >> +    *isize = gdbarch_max_insn_length (gdbarch);
> > >> +  if (msg)
> > >> +    *msg = NULL;
> > >> +  return 1;
> > >> +}
> > >
> > > Should/can we check here where the jump to the jump pad will be in
> > > range?  Might be better to detect this early ...
> >
> >Client has no idea about where the jump pad will be installed.
> >If it's out of range, gdbserver will report it right after user
> >entered 'tstart' command
> Well, but we know the logic the stub uses.  For example, we know that
> we certainly cannot install a fast tracepoint in any shared library code,
> since the jump pad will definitely be too far away.  We can check for
> this condition here.  (We could also check for tracepoints in executables
> that have a text section larger than 32 MB ...)

Now in this path, ppc_fast_tracepoint_valid_at will check the distance
and return 0 (invalid) if ADDR is too far from jumppad.

However, if a tracepoint was pending and later found it's not valid,
it will cause an internal-error.  See remote.c

  if (gdbarch_fast_tracepoint_valid_at (target_gdbarch (),
					tpaddr, &isize, NULL))
    xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":F%x",
	       isize);
  else
    /* If it passed validation at definition but fails now,
       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
       something is very wrong.  */
    internal_error (__FILE__, __LINE__, _("Fast tracepoint not "
					  "valid during download"));

If the tracepoint is pending at definition, it won't be checked at all.

  /* Fast tracepoints may have additional restrictions on location.  */
  if (!pending && type_wanted == bp_fast_tracepoint)
      ^^^^^^^^
    {
      for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
	check_fast_tracepoint_sals (gdbarch, &iter->sals);
    }

Maybe we use "error" instead of "internal_error"?


BTW, in this patch, unlock is implemented by simply writing 0 instead
of a full atomic-swap.  It that ok?

  /* Prepare collecting_t object for lock.  */
  p += GEN_STORE (p, 3, 1, min_frame + 37 * rsz);
  p += GEN_STORE (p, tp_reg, 1, min_frame + 38 *rsz);
  /* Set R5 to collecting object.  */
  p += GEN_ADDI (p, 5, 1, 37 * rsz);

  p += gen_atomic_xchg (p, lockaddr, 0, 5);

  /* Call to collector.  */
  p += gen_call (p, collector);

  /* Simply write 0 to release the lock.  */
  p += gen_limm (p, 3, lockaddr);
  p += gen_limm (p, 4, 0);
  p += GEN_LWSYNC (p);
  p += GEN_STORE (p, 4, 3, 0);

Thanks,
Wei-cheng

---

gdb/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* rs6000-tdep.c (ppc_fast_tracepoint_valid_at,
	ppc_gen_return_address): New functions.
	(rs6000_gdbarch_init): Hook ppc_fast_tracepoint_valid_at,
	and ppc_gen_return_address.

gdb/gdbserver/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* Makefile.in (linux-ppc-ipa.o, powerpc-64l-ipa.o,
	powerpc-32l-ipa.o): New rules.
	* configure.srv (powerpc*-*-linux*): Add powerpc-64l-ipa.o,
	powerpc-32l-ipa.o, and linux-ppc-ipa.o in ipa_obj
	* linux-ppc-ipa.c: New file.
	* linux-ppc-low.c (gen_ds_form, gen_d_form, gen_xfx_form, gen_x_form,
	gen_md_form, gen_i_form, gen_b_form, gen_limm,
	gen_atomic_xchg, gen_call, ppc_supports_tracepoints,
	ppc_install_fast_tracepoint_jump_pad,
	ppc_get_min_fast_tracepoint_insn_len, emit_insns, ppc64_emit_prologue,
	ppc64_emit_epilogue, ppc64_emit_add, ppc64_emit_sub, ppc64_emit_mul,
	ppc64_emit_lsh, ppc64_emit_rsh_signed, ppc64_emit_rsh_unsigned,
	ppc64_emit_ext, ppc64_emit_zero_ext, ppc64_emit_log_not,
	ppc64_emit_bit_and, ppc64_emit_bit_or, ppc64_emit_bit_xor,
	ppc64_emit_bit_not, ppc64_emit_equal, ppc64_emit_less_signed,
	ppc64_emit_less_unsigned, ppc64_emit_ref, ppc64_emit_const,
	ppc64_emit_reg, ppc64_emit_pop, ppc64_emit_stack_flush,
	ppc64_emit_swap, ppc64_emit_stack_adjust, ppc64_emit_call,
	ppc64_emit_int_call_1, ppc64_emit_void_call_2, ppc64_emit_if_goto,
	ppc64_emit_goto, ppc64_emit_eq_goto, ppc64_emit_ne_goto,
	ppc64_emit_lt_goto, ppc64_emit_le_goto, ppc64_emit_gt_goto,
	ppc64_emit_ge_goto, ppc_write_goto_address, ppc_emit_ops,
	ppc_supports_range_stepping, ppc_fast_tracepoint_valid_at,
	ppc_relocate_instruction): New functions.
	(ppc64_emit_ops_vector): New struct for bytecode compilation.
	(the_low_target): Add target ops - ppc_supports_tracepoints,
	ppc_install_fast_tracepoint_jump_pad, ppc_emit_ops,
	ppc_get_min_fast_tracepoint_insn_len, ppc_supports_range_stepping.

gdb/testsuite/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* gdb.trace/backtrace.exp: Set registers for powerpc*-*-*.
	* gdb.trace/collection.exp: Ditto.
	* gdb.trace/entry-values.exp: Ditto.
	* gdb.trace/mi-trace-frame-collected.exp: Ditto.
	* gdb.trace/mi-trace-unavailable.exp: Ditto.
	* gdb.trace/pending.exp: Ditto.
	* gdb.trace/report.exp: Ditto.
	* gdb.trace/trace-break.exp: Ditto.
	* gdb.trace/while-dyn.exp: Ditto.
	* gdb.trace/change-loc.h: set_point for powerpc.
	* gdb.trace/ftrace.c: Ditto
	* gdb.trace/pendshr1.c: Ditto.
	* gdb.trace/pendshr2.c: Ditto.
	* gdb.trace/range-stepping.c: Ditto.
	* gdb.trace/trace-break.c: Ditto.
	* gdb.trace/trace-mt.c: Ditto.
	* gdb.trace/ftrace.exp: Enable testing for powerpc*-*-*.
---
 gdb/gdbserver/Makefile.in                          |    9 +
 gdb/gdbserver/configure.srv                        |    1 +
 gdb/gdbserver/linux-ppc-ipa.c                      |  120 ++
 gdb/gdbserver/linux-ppc-low.c                      | 1408 +++++++++++++++++++-
 gdb/rs6000-tdep.c                                  |  117 ++
 gdb/testsuite/gdb.trace/actions.c                  |    9 +-
 gdb/testsuite/gdb.trace/backtrace.exp              |    3 +
 gdb/testsuite/gdb.trace/change-loc.h               |    2 +
 gdb/testsuite/gdb.trace/collection.exp             |    4 +
 gdb/testsuite/gdb.trace/entry-values.exp           |    4 +-
 gdb/testsuite/gdb.trace/ftrace.c                   |    4 +
 gdb/testsuite/gdb.trace/ftrace.exp                 |    7 +-
 .../gdb.trace/mi-trace-frame-collected.exp         |    2 +
 gdb/testsuite/gdb.trace/mi-trace-unavailable.exp   |    2 +
 gdb/testsuite/gdb.trace/pending.exp                |    2 +
 gdb/testsuite/gdb.trace/pendshr1.c                 |    2 +
 gdb/testsuite/gdb.trace/pendshr2.c                 |    2 +
 gdb/testsuite/gdb.trace/range-stepping.c           |    2 +
 gdb/testsuite/gdb.trace/report.exp                 |    4 +
 gdb/testsuite/gdb.trace/trace-break.c              |    4 +
 gdb/testsuite/gdb.trace/trace-break.exp            |    4 +
 gdb/testsuite/gdb.trace/trace-mt.c                 |    2 +
 gdb/testsuite/gdb.trace/unavailable.exp            |    4 +
 gdb/testsuite/gdb.trace/while-dyn.exp              |    2 +
 24 files changed, 1712 insertions(+), 8 deletions(-)
 create mode 100644 gdb/gdbserver/linux-ppc-ipa.c

diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index fc250fb..6dab7e3 100644
--- a/gdb/gdbserver/Makefile.in
+++ b/gdb/gdbserver/Makefile.in
@@ -499,6 +499,15 @@ linux-amd64-ipa.o: linux-amd64-ipa.c
 amd64-linux-ipa.o: amd64-linux.c
 	$(IPAGENT_COMPILE) $<
 	$(POSTCOMPILE)
+linux-ppc-ipa.o: linux-ppc-ipa.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+powerpc-64l-ipa.o: powerpc-64l.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
+powerpc-32l-ipa.o: powerpc-32l.c
+	$(IPAGENT_COMPILE) $<
+	$(POSTCOMPILE)
 tdesc-ipa.o: tdesc.c
 	$(IPAGENT_COMPILE) $<
 	$(POSTCOMPILE)
diff --git a/gdb/gdbserver/configure.srv b/gdb/gdbserver/configure.srv
index 7f89f2f..4f34bd8 100644
--- a/gdb/gdbserver/configure.srv
+++ b/gdb/gdbserver/configure.srv
@@ -246,6 +246,7 @@ case "${target}" in
 			srv_linux_usrregs=yes
 			srv_linux_regsets=yes
 			srv_linux_thread_db=yes
+			ipa_obj="powerpc-64l-ipa.o powerpc-32l-ipa.o linux-ppc-ipa.o"
 			;;
   powerpc-*-lynxos*)	srv_regobj="powerpc-32.o"
 			srv_tgtobj="lynx-low.o lynx-ppc-low.o"
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
new file mode 100644
index 0000000..73d8899
--- /dev/null
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -0,0 +1,120 @@
+/* GNU/Linux/PowerPC specific low level interface, for the in-process
+   agent library for GDB.
+
+   Copyright (C) 2010-2015 Free Software Foundation, Inc.
+
+   This file is part of GDB.
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
+
+#include "server.h"
+#include "tracepoint.h"
+
+#if defined __PPC64__
+void init_registers_powerpc_64l (void);
+extern const struct target_desc *tdesc_powerpc_64l;
+#define REGSZ		8
+#else
+void init_registers_powerpc_32l (void);
+extern const struct target_desc *tdesc_powerpc_32l;
+#define REGSZ		4
+#endif
+
+/* These macros define the position of registers in the buffer collected
+   by the fast tracepoint jump pad.  */
+#define FT_CR_R0	0
+#define FT_CR_CR	32
+#define FT_CR_XER	33
+#define FT_CR_LR	34
+#define FT_CR_CTR	35
+#define FT_CR_PC	36
+#define FT_CR_GPR(n)	(FT_CR_R0 + (n))
+
+static const int ppc_ft_collect_regmap[] = {
+  /* GPRs */
+  FT_CR_GPR (0), FT_CR_GPR (1), FT_CR_GPR (2),
+  FT_CR_GPR (3), FT_CR_GPR (4), FT_CR_GPR (5),
+  FT_CR_GPR (6), FT_CR_GPR (7), FT_CR_GPR (8),
+  FT_CR_GPR (9), FT_CR_GPR (10), FT_CR_GPR (11),
+  FT_CR_GPR (12), FT_CR_GPR (13), FT_CR_GPR (14),
+  FT_CR_GPR (15), FT_CR_GPR (16), FT_CR_GPR (17),
+  FT_CR_GPR (18), FT_CR_GPR (19), FT_CR_GPR (20),
+  FT_CR_GPR (21), FT_CR_GPR (22), FT_CR_GPR (23),
+  FT_CR_GPR (24), FT_CR_GPR (25), FT_CR_GPR (26),
+  FT_CR_GPR (27), FT_CR_GPR (28), FT_CR_GPR (29),
+  FT_CR_GPR (30), FT_CR_GPR (31),
+  /* FPRs - not collected.  */
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  -1, -1, -1, -1, -1, -1, -1, -1,
+  FT_CR_PC, /* PC */
+  -1, /* MSR */
+  FT_CR_CR, /* CR */
+  FT_CR_LR, /* LR */
+  FT_CR_CTR, /* CTR */
+  FT_CR_XER, /* XER */
+  -1, /* FPSCR */
+};
+
+#define PPC_NUM_FT_COLLECT_GREGS \
+  (sizeof (ppc_ft_collect_regmap) / sizeof(ppc_ft_collect_regmap[0]))
+
+/* Supply registers collected by the fast tracepoint jump pad.
+   BUF is the second argument we pass to gdb_collect in jump pad.  */
+
+void
+supply_fast_tracepoint_registers (struct regcache *regcache,
+				  const unsigned char *buf)
+{
+  int i;
+
+  for (i = 0; i < PPC_NUM_FT_COLLECT_GREGS; i++)
+    {
+      if (ppc_ft_collect_regmap[i] == -1)
+	continue;
+      supply_register (regcache, i,
+		       ((char *) buf)
+			+ ppc_ft_collect_regmap[i] * REGSZ);
+    }
+}
+
+/* Return the value of register REGNUM.  RAW_REGS is collected buffer
+   by jump pad.  This function is called by emit_reg.  */
+
+IP_AGENT_EXPORT_FUNC ULONGEST
+gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
+{
+  if (regnum >= PPC_NUM_FT_COLLECT_GREGS)
+    return 0;
+  if (ppc_ft_collect_regmap[regnum] == -1)
+    return 0;
+
+  return *(ULONGEST *) (raw_regs
+			+ ppc_ft_collect_regmap[regnum] * REGSZ);
+}
+
+/* Initialize ipa_tdesc and others.  */
+
+void
+initialize_low_tracepoint (void)
+{
+#if defined __PPC64__
+  init_registers_powerpc_64l ();
+  ipa_tdesc = tdesc_powerpc_64l;
+#else
+  init_registers_powerpc_32l ();
+  ipa_tdesc = tdesc_powerpc_32l;
+#endif
+}
diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 41ec281..064f508 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -24,6 +24,19 @@
 #include <asm/ptrace.h>
 
 #include "nat/ppc-linux.h"
+#include "ax.h"
+#include "tracepoint.h"
+
+#define PPC_FIELD(value, from, len) \
+	(((value) >> (32 - (from) - (len))) & ((1 << (len)) - 1))
+#define PPC_SEXT(v, bs) \
+	((((CORE_ADDR) (v) & (((CORE_ADDR) 1 << (bs)) - 1)) \
+	  ^ ((CORE_ADDR) 1 << ((bs) - 1))) \
+	 - ((CORE_ADDR) 1 << ((bs) - 1)))
+#define PPC_OP6(insn)	PPC_FIELD (insn, 0, 6)
+#define PPC_BO(insn)	PPC_FIELD (insn, 6, 5)
+#define PPC_LI(insn)	(PPC_SEXT (PPC_FIELD (insn, 6, 24), 24) << 2)
+#define PPC_BD(insn)	(PPC_SEXT (PPC_FIELD (insn, 16, 14), 14) << 2)
 
 static unsigned long ppc_hwcap;
 
@@ -575,6 +588,1377 @@ ppc_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
     }
 }
 
+/* Generate a ds-form instruction in BUF and return the number of bytes written
+
+   0      6     11   16          30 32
+   | OPCD | RST | RA |     DS    |XO|  */
+
+__attribute__((unused)) /* Maybe unused due to conditional compilation.  */
+static int
+gen_ds_form (uint32_t *buf, int opcd, int rst, int ra, int ds, int xo)
+{
+  uint32_t insn;
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+  gdb_assert ((rst & ~0x1f) == 0);
+  gdb_assert ((ra & ~0x1f) == 0);
+  gdb_assert ((xo & ~0x3) == 0);
+
+  insn = (rst << 21) | (ra << 16) | (ds & 0xfffc) | (xo & 0x3);
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* Followings are frequently used ds-form instructions.  */
+
+#define GEN_STD(buf, rs, ra, offset)	gen_ds_form (buf, 62, rs, ra, offset, 0)
+#define GEN_STDU(buf, rs, ra, offset)	gen_ds_form (buf, 62, rs, ra, offset, 1)
+#define GEN_LD(buf, rt, ra, offset)	gen_ds_form (buf, 58, rt, ra, offset, 0)
+#define GEN_LDU(buf, rt, ra, offset)	gen_ds_form (buf, 58, rt, ra, offset, 1)
+
+/* Generate a d-form instruction in BUF.
+
+   0      6     11   16             32
+   | OPCD | RST | RA |       D      |  */
+
+static int
+gen_d_form (uint32_t *buf, int opcd, int rst, int ra, int si)
+{
+  uint32_t insn;
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+  gdb_assert ((rst & ~0x1f) == 0);
+  gdb_assert ((ra & ~0x1f) == 0);
+
+  insn = (rst << 21) | (ra << 16) | (si & 0xffff);
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* Followings are frequently used d-form instructions.  */
+
+#define GEN_ADDI(buf, rt, ra, si)	gen_d_form (buf, 14, rt, ra, si)
+#define GEN_ADDIS(buf, rt, ra, si)	gen_d_form (buf, 15, rt, ra, si)
+#define GEN_LI(buf, rt, si)		GEN_ADDI (buf, rt, 0, si)
+#define GEN_LIS(buf, rt, si)		GEN_ADDIS (buf, rt, 0, si)
+#define GEN_ORI(buf, rt, ra, si)	gen_d_form (buf, 24, rt, ra, si)
+#define GEN_ORIS(buf, rt, ra, si)	gen_d_form (buf, 25, rt, ra, si)
+#define GEN_LWZ(buf, rt, ra, si)	gen_d_form (buf, 32, rt, ra, si)
+#define GEN_STW(buf, rt, ra, si)	gen_d_form (buf, 36, rt, ra, si)
+
+/* Generate a xfx-form instruction in BUF and return the number of bytes
+   written.
+
+   0      6     11         21        31 32
+   | OPCD | RST |    RI    |    XO   |/|  */
+
+static int
+gen_xfx_form (uint32_t *buf, int opcd, int rst, int ri, int xo)
+{
+  uint32_t insn;
+  unsigned int n = ((ri & 0x1f) << 5) | ((ri >> 5) & 0x1f);
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+  gdb_assert ((rst & ~0x1f) == 0);
+  gdb_assert ((xo & ~0x3ff) == 0);
+
+  insn = (rst << 21) | (n << 11) | (xo << 1);
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* Followings are frequently used xfx-form instructions.  */
+
+#define GEN_MFSPR(buf, rt, spr)		gen_xfx_form (buf, 31, rt, spr, 339)
+#define GEN_MTSPR(buf, rt, spr)		gen_xfx_form (buf, 31, rt, spr, 467)
+#define GEN_MFCR(buf, rt)		gen_xfx_form (buf, 31, rt, 0, 19)
+#define GEN_MTCR(buf, rt)		gen_xfx_form (buf, 31, rt, 0x3cf, 144)
+#define GEN_SYNC(buf, L, E)             gen_xfx_form (buf, 31, L & 0x3, \
+						      E & 0xf, 598)
+#define GEN_LWSYNC(buf)			GEN_SYNC (buf, 1, 0)
+
+
+/* Generate a x-form instruction in BUF and return the number of bytes written.
+
+   0      6     11   16   21       31 32
+   | OPCD | RST | RA | RB |   XO   |RC|  */
+
+static int
+gen_x_form (uint32_t *buf, int opcd, int rst, int ra, int rb, int xo, int rc)
+{
+  uint32_t insn;
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+  gdb_assert ((rst & ~0x1f) == 0);
+  gdb_assert ((ra & ~0x1f) == 0);
+  gdb_assert ((rb & ~0x1f) == 0);
+  gdb_assert ((xo & ~0x3ff) == 0);
+  gdb_assert ((rc & ~1) == 0);
+
+  insn = (rst << 21) | (ra << 16) | (rb << 11) | (xo << 1) | rc;
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* Followings are frequently used x-form instructions.  */
+
+#define GEN_OR(buf, ra, rs, rb)		gen_x_form (buf, 31, rs, ra, rb, 444, 0)
+#define GEN_MR(buf, ra, rs)		GEN_OR (buf, ra, rs, rs)
+#define GEN_LWARX(buf, rt, ra, rb)	gen_x_form (buf, 31, rt, ra, rb, 20, 0)
+#define GEN_STWCX(buf, rs, ra, rb)	gen_x_form (buf, 31, rs, ra, rb, 150, 1)
+/* Assume bf = cr7.  */
+#define GEN_CMPW(buf, ra, rb)    gen_x_form (buf, 31, 28, ra, rb, 0, 0)
+
+/* Generate a md-form instruction in BUF and return the number of bytes written.
+
+   0      6    11   16   21   27   30 31 32
+   | OPCD | RS | RA | sh | mb | XO |sh|Rc|  */
+
+static int
+gen_md_form (uint32_t *buf, int opcd, int rs, int ra, int sh, int mb,
+	     int xo, int rc)
+{
+  uint32_t insn;
+  unsigned int n = ((mb & 0x1f) << 1) | ((mb >> 5) & 0x1);
+  unsigned int sh0_4 = sh & 0x1f;
+  unsigned int sh5 = (sh >> 5) & 1;
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+  gdb_assert ((rs & ~0x1f) == 0);
+  gdb_assert ((ra & ~0x1f) == 0);
+  gdb_assert ((sh & ~0x3f) == 0);
+  gdb_assert ((mb & ~0x3f) == 0);
+  gdb_assert ((xo & ~0x7) == 0);
+  gdb_assert ((rc & ~0x1) == 0);
+
+  insn = (rs << 21) | (ra << 16) | (sh0_4 << 11) | (n << 5)
+	 | (sh5 << 1) | (xo << 2) | (rc & 1);
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* The following are frequently used md-form instructions.  */
+
+#define GEN_RLDICR(buf, ra, rs ,sh, mb) \
+				gen_md_form (buf, 30, rs, ra, sh, mb, 1, 0)
+
+/* Generate a i-form instruction in BUF and return the number of bytes written.
+
+   0      6                          30 31 32
+   | OPCD |            LI            |AA|LK|  */
+
+static int
+gen_i_form (uint32_t *buf, int opcd, int li, int aa, int lk)
+{
+  uint32_t insn;
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+
+  insn = (li & 0x3fffffc) | (aa & 1) | (lk & 1);
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* The following are frequently used i-form instructions.  */
+
+#define GEN_B(buf, li)		gen_i_form (buf, 18, li, 0, 0)
+#define GEN_BL(buf, li)		gen_i_form (buf, 18, li, 0, 1)
+
+/* Generate a b-form instruction in BUF and return the number of bytes written.
+
+   0      6    11   16               30 31 32
+   | OPCD | BO | BI |      BD        |AA|LK|  */
+
+static int
+gen_b_form (uint32_t *buf, int opcd, int bo, int bi, int bd,
+	    int aa, int lk)
+{
+  uint32_t insn;
+
+  gdb_assert ((opcd & ~0x3f) == 0);
+  gdb_assert ((bo & ~0x1f) == 0);
+  gdb_assert ((bi & ~0x1f) == 0);
+
+  insn = (bo << 21) | (bi << 16) | (bd & 0xfffc) | (aa & 1) | (lk & 1);
+  *buf = (opcd << 26) | insn;
+  return 1;
+}
+
+/* The following are frequently used b-form instructions.  */
+/* Assume bi = cr7.  */
+#define GEN_BNE(buf, bd)  gen_b_form (buf, 16, 0x4, (7 << 2) | 2, bd, 0 ,0)
+
+/* GEN_LOAD and GEN_STORE generate 64- or 32-bit load/store for ppc64 or ppc32
+   respectively.  They are primary used for save/restore GPRs in jump-pad,
+   not used for bytecode compiling.  */
+
+#if defined __PPC64__
+#define GEN_LOAD(buf, rt, ra, si)	GEN_LD (buf, rt, ra, si)
+#define GEN_STORE(buf, rt, ra, si)	GEN_STD (buf, rt, ra, si)
+#else
+#define GEN_LOAD(buf, rt, ra, si)	GEN_LWZ (buf, rt, ra, si)
+#define GEN_STORE(buf, rt, ra, si)	GEN_STW (buf, rt, ra, si)
+#endif
+
+/* Generate a sequence of instructions to load IMM in the register REG.
+   Write the instructions in BUF and return the number of bytes written.  */
+
+static int
+gen_limm (uint32_t *buf, int reg, uint64_t imm)
+{
+  uint32_t *p = buf;
+
+  if ((imm + 32768) < 65536)
+    {
+      /* li	reg, imm[7:0] */
+      p += GEN_LI (p, reg, imm);
+    }
+  else if ((imm >> 16) == 0)
+    {
+      /* li	reg, 0
+	 ori	reg, reg, imm[15:0] */
+      p += GEN_LI (p, reg, 0);
+      p += GEN_ORI (p, reg, reg, imm);
+    }
+  else if ((imm >> 32) == 0)
+    {
+      /* lis	reg, imm[31:16]
+	 ori	reg, reg, imm[15:0] */
+      p += GEN_LIS (p, reg, (imm >> 16) & 0xffff);
+      p += GEN_ORI (p, reg, reg, imm & 0xffff);
+    }
+  else
+    {
+      /* lis    reg, <imm[63:48]>
+	 ori    reg, reg, <imm[48:32]>
+	 rldicr reg, reg, 32, 31
+	 oris   reg, reg, <imm[31:16]>
+	 ori    reg, reg, <imm[15:0]> */
+      p += GEN_LIS (p, reg, ((imm >> 48) & 0xffff));
+      p += GEN_ORI (p, reg, reg, ((imm >> 32) & 0xffff));
+      p += GEN_RLDICR (p, reg, reg, 32, 31);
+      p += GEN_ORIS (p, reg, reg, ((imm >> 16) & 0xffff));
+      p += GEN_ORI (p, reg, reg, (imm & 0xffff));
+    }
+
+  return p - buf;
+}
+
+/* Generate a sequence for atomically exchange at location LOCK.
+   This code sequence clobbers r6, r7, r8.  LOCK is the location for
+   the atomic-xchg, OLD_VALUE is expected old value stored in the
+   location, and R_NEW is a register for the new value.  */
+
+static int
+gen_atomic_xchg (uint32_t *buf, CORE_ADDR lock, int old_value, int r_new)
+{
+  const int r_lock = 6;
+  const int r_old = 7;
+  const int r_tmp = 8;
+  uint32_t *p = buf;
+
+  /*
+  1: lwsync
+  2: lwarx   TMP, 0, LOCK
+     cmpwi   TMP, OLD
+     bne     1b
+     stwcx.  NEW, 0, LOCK
+     bne     2b */
+
+  p += gen_limm (p, r_lock, lock);
+  p += gen_limm (p, r_old, old_value);
+
+  p += GEN_LWSYNC (p);
+  p += GEN_LWARX (p, r_tmp, 0, r_lock);
+  p += GEN_CMPW (p, r_tmp, r_old);
+  p += GEN_BNE (p, -12);
+  p += GEN_STWCX (p, r_new, 0, r_lock);
+  p += GEN_BNE (p, -16);
+
+  return p - buf;
+}
+
+/* Generate a sequence of instructions for calling a function
+   at address of FN.  Return the number of bytes are written in BUF.
+
+   FIXME: For ppc64be, FN should be the address to the function
+   descriptor, so we should load 8(FN) to R2, 16(FN) to R11
+   and then call the function-entry at 0(FN).  However, current GDB
+   implicitly convert the address from function descriptor to the actual
+   function address. See qSymbol handling in remote.c.  Although it
+   seems we can successfully call however, things go wrong when callee
+   trying to access global variable.  */
+
+static int
+gen_call (uint32_t *buf, CORE_ADDR fn)
+{
+  uint32_t *p = buf;
+
+  /* Must be called by r12 for caller to calculate TOC address. */
+  p += gen_limm (p, 12, fn);
+  p += GEN_MTSPR (p, 12, 9);		/* mtctr  r12 */
+  *p++ = 0x4e800421;			/* bctrl */
+
+  return p - buf;
+}
+
+/* Implement supports_tracepoints hook of target_ops.
+   Always return true.  */
+
+static int
+ppc_supports_tracepoints (void)
+{
+#if defined (__PPC64__) && _CALL_ELF == 2
+  return 1;
+#else
+  return 0;
+#endif
+}
+
+/* Get the thread area address.  This is used to recognize which
+   thread is which when tracing with the in-process agent library.  We
+   don't read anything from the address, and treat it as opaque; it's
+   the address itself that we assume is unique per-thread.  */
+
+static int
+ppc_get_thread_area (int lwpid, CORE_ADDR *addr)
+{
+  struct lwp_info *lwp = find_lwp_pid (pid_to_ptid (lwpid));
+  struct thread_info *thr = get_lwp_thread (lwp);
+  struct regcache *regcache = get_thread_regcache (thr, 1);
+  ULONGEST tp = 0;
+
+#if __PPC64__
+  collect_register_by_name (regcache, "r13", &tp);
+#else
+  collect_register_by_name (regcache, "r2", &tp);
+#endif
+
+  *addr = tp;
+  return 0;
+}
+
+/* Copy the instruction from OLDLOC to *TO, and update *TO to *TO + size
+   of instruction.  This function is used to adjust pc-relative instructions
+   when copying.  */
+
+static void
+ppc_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
+{
+  uint32_t insn, op6;
+  long rel, newrel;
+
+  read_inferior_memory (oldloc, (unsigned char *) &insn, 4);
+  op6 = PPC_OP6 (insn);
+
+  if (op6 == 18 && (insn & 2) == 0)
+    {
+      /* branch && AA = 0 */
+      rel = PPC_LI (insn);
+      newrel = (oldloc - *to) + rel;
+
+      /* Out of range. Cannot relocate instruction.  */
+      if (newrel >= (1 << 25) || newrel < -(1 << 25))
+	return;
+
+      insn = (insn & ~0x3fffffc) | (newrel & 0x3fffffc);
+    }
+  else if (op6 == 16 && (insn & 2) == 0)
+    {
+      /* conditional branch && AA = 0 */
+
+      /* If the new relocation is too big for even a 26-bit unconditional
+	 branch, there is nothing we can do.  Just abort.
+
+	 Otherwise, if it can be fit in 16-bit conditional branch, just
+	 copy the instruction and relocate the address.
+
+	 If the it's  big for conditional-branch (16-bit), try to invert the
+	 condition and jump with 26-bit branch.  For example,
+
+	 beq  .Lgoto
+	 INSN1
+
+	 =>
+
+	 bne  1f (+8)
+	 b    .Lgoto
+       1:INSN1
+
+	 After this transform, we are actually jump from *TO+4 instead of *TO,
+	 so check the relocation again because it will be 1-insn farther then
+	 before if *TO is after OLDLOC.
+
+
+	 For BDNZT (or so) is transformed from
+
+	 bdnzt  eq, .Lgoto
+	 INSN1
+
+	 =>
+
+	 bdz    1f (+12)
+	 bf     eq, 1f (+8)
+	 b      .Lgoto
+       1:INSN1
+
+	 See also "BO field encodings".  */
+
+      rel = PPC_BD (insn);
+      newrel = (oldloc - *to) + rel;
+
+      if (newrel < (1 << 15) && newrel >= -(1 << 15))
+	insn = (insn & ~0xfffc) | (newrel & 0xfffc);
+      else if ((PPC_BO (insn) & 0x14) == 0x4 || (PPC_BO (insn) & 0x14) == 0x10)
+	{
+	  newrel -= 4;
+
+	  /* Out of range. Cannot relocate instruction.  */
+	  if (newrel >= (1 << 25) || newrel < -(1 << 25))
+	    return;
+
+	  if ((PPC_BO (insn) & 0x14) == 0x4)
+	    insn ^= (1 << 24);
+	  else if ((PPC_BO (insn) & 0x14) == 0x10)
+	    insn ^= (1 << 22);
+
+	  /* Jump over the unconditional branch.  */
+	  insn = (insn & ~0xfffc) | 0x8;
+	  write_inferior_memory (*to, (unsigned char *) &insn, 4);
+	  *to += 4;
+
+	  /* Build a unconditional branch and copy LK bit.  */
+	  insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
+	  write_inferior_memory (*to, (unsigned char *) &insn, 4);
+	  *to += 4;
+
+	  return;
+	}
+      else
+	{
+	  uint32_t bdnz_insn = (16 << 26) | (0x10 << 21) | 12;
+	  uint32_t bf_insn = (16 << 26) | (0x4 << 21) | 8;
+
+	  newrel -= 12;
+
+	  /* Out of range. Cannot relocate instruction.  */
+	  if (newrel >= (1 << 25) || newrel < -(1 << 25))
+	    return;
+
+	  /* Copy BI field.  */
+	  bf_insn |= (insn & 0x1f0000);
+
+	  /* Invert condition.  */
+	  bdnz_insn |= (insn ^ (1 << 22)) & (1 << 22);
+	  bf_insn |= (insn ^ (1 << 24)) & (1 << 24);
+
+	  write_inferior_memory (*to, (unsigned char *) &bdnz_insn, 4);
+	  *to += 4;
+	  write_inferior_memory (*to, (unsigned char *) &bf_insn, 4);
+	  *to += 4;
+
+	  /* Build a unconditional branch and copy LK bit.  */
+	  insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
+	  write_inferior_memory (*to, (unsigned char *) &insn, 4);
+	  *to += 4;
+
+	  return;
+	}
+    }
+
+  write_inferior_memory (*to, (unsigned char *) &insn, 4);
+  *to += 4;
+}
+
+/* Implement install_fast_tracepoint_jump_pad of target_ops.
+   See target.h for details.  */
+
+static int
+ppc_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
+				      CORE_ADDR collector,
+				      CORE_ADDR lockaddr,
+				      ULONGEST orig_size,
+				      CORE_ADDR *jump_entry,
+				      CORE_ADDR *trampoline,
+				      ULONGEST *trampoline_size,
+				      unsigned char *jjump_pad_insn,
+				      ULONGEST *jjump_pad_insn_size,
+				      CORE_ADDR *adjusted_insn_addr,
+				      CORE_ADDR *adjusted_insn_addr_end,
+				      char *err)
+{
+  uint32_t buf[256];
+  uint32_t *p = buf;
+  int j, offset;
+  CORE_ADDR buildaddr = *jump_entry;
+  const CORE_ADDR entryaddr = *jump_entry;
+#if __PPC64__
+  /* Minimum frame size is 32 bytes for ELFv2, and 112 bytes for ELFv1.  */
+  const int rsz = 8;
+  const int min_frame = 112;
+  const int frame_size = (40 * rsz) + min_frame;
+  const int tp_reg = 13;
+#else
+  const int rsz = 4;
+  const int min_frame = 16;
+  const int frame_size = (40 * rsz) + min_frame;
+  const int tp_reg = 2;
+#endif
+
+  /* Stack frame layout for this jump pad,
+
+     High	thread_area (r13/r2)    |
+		tpoint			- collecting_t obj
+		PC/<tpaddr>		| +36
+		CTR			| +35
+		LR			| +34
+		XER			| +33
+		CR			| +32
+		R31			|
+		R29			|
+		...			|
+		R1			| +1
+		R0			- collected registers
+		...			|
+		...			|
+     Low	Back-chain		-
+
+
+     The code flow of this jump pad,
+
+     1. Adjust SP
+     2. Save GPR and SPR
+     3. Prepare argument
+     4. Call gdb_collector
+     5. Restore GPR and SPR
+     6. Restore SP
+     7. Build a jump for back to the program
+     8. Copy/relocate original instruction
+     9. Build a jump for replacing orignal instruction.  */
+
+  /* Adjust stack pointer.  */
+  p += GEN_STDU (p, 1, 1, -frame_size);		/* stdu   r1,-frame_size(r1) */
+
+  /* Store GPRs.  Save R1 later, because it had just been modified, but
+     we want the original value.  */
+  for (j = 2; j < 32; j++)
+    p += GEN_STORE (p, j, 1, min_frame + j * rsz);
+  p += GEN_STORE (p, 0, 1, min_frame + 0 * rsz);
+  /* Set r0 to the original value of r1 before adjusting stack frame,
+     and then save it.  */
+  p += GEN_ADDI (p, 0, 1, frame_size);
+  p += GEN_STORE (p, 0, 1, min_frame + 1 * rsz);
+
+  /* Save CR, XER, LR, and CTR.  */
+  p += GEN_MFCR (p, 3);					/* mfcr   r3 */
+  p += GEN_MFSPR (p, 4, 1);				/* mfxer  r4 */
+  p += GEN_MFSPR (p, 5, 8);				/* mflr   r5 */
+  p += GEN_MFSPR (p, 6, 9);				/* mfctr  r6 */
+  p += GEN_STORE (p, 3, 1, min_frame + 32 * rsz);	/* std    r3, 32(r1) */
+  p += GEN_STORE (p, 4, 1, min_frame + 33 * rsz);	/* std    r4, 33(r1) */
+  p += GEN_STORE (p, 5, 1, min_frame + 34 * rsz);	/* std    r5, 34(r1) */
+  p += GEN_STORE (p, 6, 1, min_frame + 35 * rsz);	/* std    r6, 35(r1) */
+
+  /* Save PC<tpaddr>  */
+  p += gen_limm (p, 3, tpaddr);
+  p += GEN_STORE (p, 3, 1, min_frame + 36 * rsz);
+
+
+  /* Setup arguments to collector.  */
+  /* Set r4 to collected registers.  */
+  p += GEN_ADDI (p, 4, 1, min_frame);
+  /* Set r3 to TPOINT.  */
+  p += gen_limm (p, 3, tpoint);
+
+  /* Prepare collecting_t object for lock.  */
+  p += GEN_STORE (p, 3, 1, min_frame + 37 * rsz);
+  p += GEN_STORE (p, tp_reg, 1, min_frame + 38 *rsz);
+  /* Set R5 to collecting object.  */
+  p += GEN_ADDI (p, 5, 1, 37 * rsz);
+
+  p += gen_atomic_xchg (p, lockaddr, 0, 5);
+
+  /* Call to collector.  */
+  p += gen_call (p, collector);
+
+  /* Simply write 0 to release the lock.  */
+  p += gen_limm (p, 3, lockaddr);
+  p += gen_limm (p, 4, 0);
+  p += GEN_LWSYNC (p);
+  p += GEN_STORE (p, 4, 3, 0);
+
+  /* Restore stack and registers.  */
+  p += GEN_LOAD (p, 3, 1, min_frame + 32 * rsz);	/* ld	r3, 32(r1) */
+  p += GEN_LOAD (p, 4, 1, min_frame + 33 * rsz);	/* ld	r4, 33(r1) */
+  p += GEN_LOAD (p, 5, 1, min_frame + 34 * rsz);	/* ld	r5, 34(r1) */
+  p += GEN_LOAD (p, 6, 1, min_frame + 35 * rsz);	/* ld	r6, 35(r1) */
+  p += GEN_MTCR (p, 3);					/* mtcr	  r3 */
+  p += GEN_MTSPR (p, 4, 1);				/* mtxer  r4 */
+  p += GEN_MTSPR (p, 5, 8);				/* mtlr   r5 */
+  p += GEN_MTSPR (p, 6, 9);				/* mtctr  r6 */
+
+  /* Restore GPRs.  */
+  for (j = 2; j < 32; j++)
+    p += GEN_LOAD (p, j, 1, min_frame + j * rsz);
+  p += GEN_LOAD (p, 0, 1, min_frame + 0 * rsz);
+  /* Restore SP.  */
+  p += GEN_ADDI (p, 1, 1, frame_size);
+
+  /* Flush instructions to inferior memory.  */
+  write_inferior_memory (buildaddr, (unsigned char *) buf, (p - buf) * 4);
+
+  /* Now, insert the original instruction to execute in the jump pad.  */
+  *adjusted_insn_addr = buildaddr + (p - buf) * 4;
+  *adjusted_insn_addr_end = *adjusted_insn_addr;
+  ppc_relocate_instruction (adjusted_insn_addr_end, tpaddr);
+
+  /* Verify the relocation size.  If should be 4 for normal copy,
+     8 or 12 for some conditional branch.  */
+  if ((*adjusted_insn_addr_end - *adjusted_insn_addr == 0)
+      || (*adjusted_insn_addr_end - *adjusted_insn_addr > 12))
+    {
+      sprintf (err, "E.Unexpected instruction length = %d"
+		    "when relocate instruction.",
+		    (int) (*adjusted_insn_addr_end - *adjusted_insn_addr));
+      return 1;
+    }
+
+  buildaddr = *adjusted_insn_addr_end;
+  p = buf;
+  /* Finally, write a jump back to the program.  */
+  offset = (tpaddr + 4) - buildaddr;
+  if (offset >= (1 << 25) || offset < -(1 << 25))
+    {
+      sprintf (err, "E.Jump back from jump pad too far from tracepoint "
+		    "(offset 0x%x > 26-bit).", offset);
+      return 1;
+    }
+  /* b <tpaddr+4> */
+  p += GEN_B (p, offset);
+  write_inferior_memory (buildaddr, (unsigned char *) buf, (p - buf) * 4);
+  *jump_entry = buildaddr + (p - buf) * 4;
+
+  /* The jump pad is now built.  Wire in a jump to our jump pad.  This
+     is always done last (by our caller actually), so that we can
+     install fast tracepoints with threads running.  This relies on
+     the agent's atomic write support.  */
+  offset = entryaddr - tpaddr;
+  if (offset >= (1 << 25) || offset < -(1 << 25))
+    {
+      sprintf (err, "E.Jump back from jump pad too far from tracepoint "
+		    "(offset 0x%x > 26-bit).", offset);
+      return 1;
+    }
+  /* b <jentry> */
+  GEN_B ((uint32_t *) jjump_pad_insn, offset);
+  *jjump_pad_insn_size = 4;
+
+  return 0;
+}
+
+/* Returns the minimum instruction length for installing a tracepoint.  */
+
+static int
+ppc_get_min_fast_tracepoint_insn_len ()
+{
+  return 4;
+}
+
+#if __PPC64__
+
+static void
+emit_insns (uint32_t *buf, int n)
+{
+  n = n * sizeof (uint32_t);
+  write_inferior_memory (current_insn_ptr, (unsigned char *) buf, n);
+  current_insn_ptr += n;
+}
+
+#define __EMIT_ASM(NAME, INSNS)					\
+  do								\
+    {								\
+      extern uint32_t start_bcax_ ## NAME [];			\
+      extern uint32_t end_bcax_ ## NAME [];			\
+      emit_insns (start_bcax_ ## NAME,				\
+		  end_bcax_ ## NAME - start_bcax_ ## NAME);	\
+      __asm__ (".section .text.__ppcbcax\n\t"			\
+	       "start_bcax_" #NAME ":\n\t"			\
+	       INSNS "\n\t"					\
+	       "end_bcax_" #NAME ":\n\t"			\
+	       ".previous\n\t");				\
+    } while (0)
+
+#define _EMIT_ASM(NAME, INSNS)		__EMIT_ASM (NAME, INSNS)
+#define EMIT_ASM(INSNS)			_EMIT_ASM (__LINE__, INSNS)
+
+/*
+
+  Bytecode execution stack frame
+
+	|  LR save area           (SP + 16)
+	|  CR save area           (SP + 8)
+ SP' -> +- Back chain             (SP + 0)
+	|  Save r31   for access saved arguments
+	|  Save r30   for bytecode stack pointer
+	|  Save r4    for incoming argument *value
+	|  Save r3    for incoming argument regs
+ r30 -> +- Bytecode execution stack
+	|
+	|  64-byte (8 doublewords) at initial.
+	|  Expand stack as needed.
+	|
+	+-
+        |  Some padding for minimum stack frame.
+        |  112 for ELFv1.
+ SP     +- Back-chain (SP')
+
+  initial frame size
+  = 112 + (4 * 8) + 64
+  = 208
+
+   r30 is the stack-pointer for bytecode machine.
+       It should point to next-empty, so we can use LDU for pop.
+   r3  is used for cache of TOP value.
+       It was the first argument, pointer to regs.
+   r4  is the second argument, pointer to the result.
+       We should set *result = TOP after leaving this function.
+
+ Note:
+ * To restore stack at epilogue
+   => sp = r31 + 208
+ * To check stack is big enough for bytecode execution.
+   => r30 - 8 > SP + 112
+ * To return execution result.
+   => 0(r4) = TOP
+
+ */
+
+/* Emit prologue in inferior memory.  See above comments.  */
+
+static void
+ppc64_emit_prologue (void)
+{
+  EMIT_ASM (/* Save return address.  */
+	    "mflr  0		\n"
+	    "std   0, 16(1)	\n"
+	    /* Save r30 and incoming arguments.  */
+	    "std   31, -8(1)	\n"
+	    "std   30, -16(1)	\n"
+	    "std   4, -24(1)	\n"
+	    "std   3, -32(1)	\n"
+	    /* Point r31 to current r1 for access arguments.  */
+	    "mr    31, 1	\n"
+	    /* Adjust SP.  208 is the initial frame size.  */
+	    "stdu  1, -208(1)	\n"
+	    /* Set r30 to pointing stack-top.  */
+	    "addi  30, 1, 168	\n"
+	    /* Initial r3/TOP to 0.  */
+	    "li	   3, 0		\n");
+}
+
+/* Emit epilogue in inferior memory.  See above comments.  */
+
+static void
+ppc64_emit_epilogue (void)
+{
+  EMIT_ASM (/* Restore SP.  */
+	    "ld    1, 0(1)      \n"
+	    /* *result = TOP */
+	    "ld    4, -24(1)	\n"
+	    "std   3, 0(4)	\n"
+	    /* Restore registers.  */
+	    "ld    31, -8(1)	\n"
+	    "ld    30, -16(1)	\n"
+            /* Restore LR.  */
+	    "ld    0, 16(1)	\n"
+	    /* Return 0 for no-error.  */
+	    "li    3, 0		\n"
+	    "mtlr  0		\n"
+	    "blr		\n");
+}
+
+/* TOP = stack[--sp] + TOP  */
+
+static void
+ppc64_emit_add (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "add  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] - TOP  */
+
+static void
+ppc64_emit_sub (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "sub  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] * TOP  */
+
+static void
+ppc64_emit_mul (void)
+{
+  EMIT_ASM ("ldu    4, 8(30)	\n"
+	    "mulld  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] << TOP  */
+
+static void
+ppc64_emit_lsh (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "sld  3, 4, 3	\n");
+}
+
+/* Top = stack[--sp] >> TOP
+   (Arithmetic shift right)  */
+
+static void
+ppc64_emit_rsh_signed (void)
+{
+  EMIT_ASM ("ldu   4, 8(30)	\n"
+	    "srad  3, 4, 3	\n");
+}
+
+/* Top = stack[--sp] >> TOP
+   (Logical shift right)  */
+
+static void
+ppc64_emit_rsh_unsigned (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "srd  3, 4, 3	\n");
+}
+
+/* Emit code for signed-extension specified by ARG.  */
+
+static void
+ppc64_emit_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM ("extsb  3, 3");
+      break;
+    case 16:
+      EMIT_ASM ("extsh  3, 3");
+      break;
+    case 32:
+      EMIT_ASM ("extsw  3, 3");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* Emit code for zero-extension specified by ARG.  */
+
+static void
+ppc64_emit_zero_ext (int arg)
+{
+  switch (arg)
+    {
+    case 8:
+      EMIT_ASM ("rldicl 3,3,0,56");
+      break;
+    case 16:
+      EMIT_ASM ("rldicl 3,3,0,48");
+      break;
+    case 32:
+      EMIT_ASM ("rldicl 3,3,0,32");
+      break;
+    default:
+      emit_error = 1;
+    }
+}
+
+/* TOP = !TOP
+   i.e., TOP = (TOP == 0) ? 1 : 0;  */
+
+static void
+ppc64_emit_log_not (void)
+{
+  EMIT_ASM ("cntlzd  3, 3	\n"
+	    "srdi    3, 3, 6	\n");
+}
+
+/* TOP = stack[--sp] & TOP  */
+
+static void
+ppc64_emit_bit_and (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "and  3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] | TOP  */
+
+static void
+ppc64_emit_bit_or (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "or   3, 4, 3	\n");
+}
+
+/* TOP = stack[--sp] ^ TOP  */
+
+static void
+ppc64_emit_bit_xor (void)
+{
+  EMIT_ASM ("ldu  4, 8(30)	\n"
+	    "xor  3, 4, 3	\n");
+}
+
+/* TOP = ~TOP
+   i.e., TOP = ~(TOP | TOP)  */
+
+static void
+ppc64_emit_bit_not (void)
+{
+  EMIT_ASM ("nor  3, 3, 3	\n");
+}
+
+/* TOP = stack[--sp] == TOP  */
+
+static void
+ppc64_emit_equal (void)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "xor     3, 3, 4	\n"
+	    "cntlzd  3, 3	\n"
+	    "srdi    3, 3, 6	\n");
+}
+
+/* TOP = stack[--sp] < TOP
+   (Signed comparison)  */
+
+static void
+ppc64_emit_less_signed (void)
+{
+  EMIT_ASM ("ldu     4, 8(30)		\n"
+	    "cmpd    7, 4, 3		\n"
+	    "mfocrf  3, 1		\n"
+	    "rlwinm  3, 3, 29, 31, 31	\n");
+}
+
+/* TOP = stack[--sp] < TOP
+   (Unsigned comparison)  */
+
+static void
+ppc64_emit_less_unsigned (void)
+{
+  EMIT_ASM ("ldu     4, 8(30)		\n"
+	    "cmpld   7, 4, 3		\n"
+	    "mfocrf  3, 1		\n"
+	    "rlwinm  3, 3, 29, 31, 31	\n");
+}
+
+/* Access the memory address in TOP in size of SIZE.
+   Zero-extend the read value.  */
+
+static void
+ppc64_emit_ref (int size)
+{
+  switch (size)
+    {
+    case 1:
+      EMIT_ASM ("lbz   3, 0(3)");
+      break;
+    case 2:
+      EMIT_ASM ("lhz   3, 0(3)");
+      break;
+    case 4:
+      EMIT_ASM ("lwz   3, 0(3)");
+      break;
+    case 8:
+      EMIT_ASM ("ld    3, 0(3)");
+      break;
+    }
+}
+
+/* TOP = NUM  */
+
+static void
+ppc64_emit_const (LONGEST num)
+{
+  uint32_t buf[5];
+  uint32_t *p = buf;
+
+  p += gen_limm (p, 3, num);
+
+  emit_insns (buf, p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* Set TOP to the value of register REG by calling get_raw_reg function
+   with two argument, collected buffer and register number.  */
+
+static void
+ppc64_emit_reg (int reg)
+{
+  uint32_t buf[10];
+  uint32_t *p = buf;
+
+  /* fctx->regs is passed in r3 and then saved in 176(1).  */
+  p += GEN_LOAD (p, 3, 31, -32);
+  p += GEN_LI (p, 4, reg);	/* li	r4, reg */
+  p += gen_call (p, get_raw_reg_func_addr ());
+
+  emit_insns (buf, p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* TOP = stack[--sp] */
+
+static void
+ppc64_emit_pop (void)
+{
+  EMIT_ASM ("ldu  3, 8(30)");
+}
+
+/* stack[sp++] = TOP
+
+   Because we may use up bytecode stack, expand 8 doublewords more
+   if needed.  */
+
+static void
+ppc64_emit_stack_flush (void)
+{
+  /* Make sure bytecode stack is big enough before push.
+     Otherwise, expand 64-byte more.  */
+
+  EMIT_ASM ("  std   3, 0(30)		\n"
+	    "  addi  4, 30, -(112 + 8)	\n"
+	    "  cmpd  7, 4, 1		\n"
+	    "  bgt   7, 1f		\n"
+	    "  ld    4, 0(1)		\n"
+	    "  stdu  4, -64(1)		\n"
+	    "1:addi  30, 30, -8		\n");
+}
+
+/* Swap TOP and stack[sp-1]  */
+
+static void
+ppc64_emit_swap (void)
+{
+  EMIT_ASM ("ld   4, 8(30)	\n"
+	    "std  3, 8(30)	\n"
+	    "mr   3, 4		\n");
+}
+
+/* Discard N elements in the stack.  */
+
+static void
+ppc64_emit_stack_adjust (int n)
+{
+  uint32_t buf[4];
+  uint32_t *p = buf;
+
+  n = n << 3;
+  if ((n >> 7) != 0)
+    {
+      emit_error = 1;
+      return;
+    }
+
+  p += GEN_ADDI (p, 30, 30, n);
+
+  emit_insns (buf, p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* Call function FN.  */
+
+static void
+ppc64_emit_call (CORE_ADDR fn)
+{
+  uint32_t buf[8];
+  uint32_t *p = buf;
+
+  p += gen_call (p, fn);
+
+  emit_insns (buf, p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* FN's prototype is `LONGEST(*fn)(int)'.
+   TOP = fn (arg1)
+  */
+
+static void
+ppc64_emit_int_call_1 (CORE_ADDR fn, int arg1)
+{
+  uint32_t buf[8];
+  uint32_t *p = buf;
+
+  /* Setup argument.  arg1 is a 16-bit value.  */
+  p += gen_limm (p, 3, arg1);
+  p += gen_call (p, fn);
+
+  emit_insns (buf, p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* FN's prototype is `void(*fn)(int,LONGEST)'.
+   fn (arg1, TOP)
+
+   TOP should be preserved/restored before/after the call.  */
+
+static void
+ppc64_emit_void_call_2 (CORE_ADDR fn, int arg1)
+{
+  uint32_t buf[12];
+  uint32_t *p = buf;
+
+  /* Save TOP.  0(30) is next-empty.  */
+  p += GEN_STORE (p, 3, 30, 0);
+
+  /* Setup argument.  arg1 is a 16-bit value.  */
+  p += GEN_MR (p, 4, 3);		/* mr	r4, r3 */
+  p += gen_limm (p, 3, arg1);
+  p += gen_call (p, fn);
+
+  /* Restore TOP */
+  p += GEN_LOAD (p, 3, 30, 0);
+
+  emit_insns (buf, p - buf);
+  gdb_assert ((p - buf) <= sizeof (buf));
+}
+
+/* Note in the following goto ops:
+
+   When emitting goto, the target address is later relocated by
+   write_goto_address.  OFFSET_P is the offset of the branch instruction
+   in the code sequence, and SIZE_P is how to relocate the instruction,
+   recognized by ppc_write_goto_address.  In current implementation,
+   SIZE can be either 24 or 14 for branch of conditional-branch instruction.
+ */
+
+/* If TOP is true, goto somewhere.  Otherwise, just fall-through.  */
+
+static void
+ppc64_emit_if_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("cmpdi  7, 3, 0	\n"
+	    "ldu    3, 8(30)	\n"
+	    "1:bne  7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Unconditional goto.  */
+
+static void
+ppc64_emit_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("1:b	1b");
+
+  if (offset_p)
+    *offset_p = 0;
+  if (size_p)
+    *size_p = 24;
+}
+
+/* Goto if stack[--sp] == TOP  */
+
+static void
+ppc64_emit_eq_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:beq   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] != TOP  */
+
+static void
+ppc64_emit_ne_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:bne   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] < TOP  */
+
+static void
+ppc64_emit_lt_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:blt   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] <= TOP  */
+
+static void
+ppc64_emit_le_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:ble   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] > TOP  */
+
+static void
+ppc64_emit_gt_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:bgt   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Goto if stack[--sp] >= TOP  */
+
+static void
+ppc64_emit_ge_goto (int *offset_p, int *size_p)
+{
+  EMIT_ASM ("ldu     4, 8(30)	\n"
+	    "cmpd    7, 4, 3	\n"
+	    "ldu     3, 8(30)	\n"
+	    "1:bge   7, 1b	\n");
+
+  if (offset_p)
+    *offset_p = 12;
+  if (size_p)
+    *size_p = 14;
+}
+
+/* Relocate previous emitted branch instruction.  FROM is the address
+   of the branch instruction, TO is the goto target address, and SIZE
+   if the value we set by *SIZE_P before.  Currently, it is either
+   24 or 14 of branch and conditional-branch instruction.  */
+
+static void
+ppc_write_goto_address (CORE_ADDR from, CORE_ADDR to, int size)
+{
+  int rel = to - from;
+  uint32_t insn;
+  int opcd;
+
+  read_inferior_memory (from, (unsigned char *) &insn, 4);
+  opcd = (insn >> 26) & 0x3f;
+
+  switch (size)
+    {
+    case 14:
+      if (opcd != 16
+	  || (rel >= (1 << 15) || rel < -(1 << 15)))
+	emit_error = 1;
+      insn = (insn & ~0xfffc) | (rel & 0xfffc);
+      break;
+    case 24:
+      if (opcd != 18
+	  || (rel >= (1 << 25) || rel < -(1 << 25)))
+	emit_error = 1;
+      insn = (insn & ~0x3fffffc) | (rel & 0x3fffffc);
+      break;
+    default:
+      emit_error = 1;
+    }
+
+  if (!emit_error)
+    write_inferior_memory (from, (unsigned char *) &insn, 4);
+}
+
+/* Vector of emit ops for PowerPC64.  */
+
+static struct emit_ops ppc64_emit_ops_vector =
+{
+  ppc64_emit_prologue,
+  ppc64_emit_epilogue,
+  ppc64_emit_add,
+  ppc64_emit_sub,
+  ppc64_emit_mul,
+  ppc64_emit_lsh,
+  ppc64_emit_rsh_signed,
+  ppc64_emit_rsh_unsigned,
+  ppc64_emit_ext,
+  ppc64_emit_log_not,
+  ppc64_emit_bit_and,
+  ppc64_emit_bit_or,
+  ppc64_emit_bit_xor,
+  ppc64_emit_bit_not,
+  ppc64_emit_equal,
+  ppc64_emit_less_signed,
+  ppc64_emit_less_unsigned,
+  ppc64_emit_ref,
+  ppc64_emit_if_goto,
+  ppc64_emit_goto,
+  ppc_write_goto_address,
+  ppc64_emit_const,
+  ppc64_emit_call,
+  ppc64_emit_reg,
+  ppc64_emit_pop,
+  ppc64_emit_stack_flush,
+  ppc64_emit_zero_ext,
+  ppc64_emit_swap,
+  ppc64_emit_stack_adjust,
+  ppc64_emit_int_call_1,
+  ppc64_emit_void_call_2,
+  ppc64_emit_eq_goto,
+  ppc64_emit_ne_goto,
+  ppc64_emit_lt_goto,
+  ppc64_emit_le_goto,
+  ppc64_emit_gt_goto,
+  ppc64_emit_ge_goto
+};
+
+/*  Implementation of emit_ops target ops.   */
+
+__attribute__ ((unused))
+static struct emit_ops *
+ppc_emit_ops (void)
+{
+  return &ppc64_emit_ops_vector;
+}
+#endif
+
+/* Returns true for supporting range-stepping.  */
+
+static int
+ppc_supports_range_stepping (void)
+{
+  return 1;
+}
+
 /* Provide only a fill function for the general register set.  ps_lgetregs
    will use this for NPTL support.  */
 
@@ -750,16 +2134,32 @@ struct linux_target_ops the_low_target = {
   ppc_set_pc,
   (const unsigned char *) &ppc_breakpoint,
   ppc_breakpoint_len,
-  NULL,
-  0,
+  NULL, /* breakpoint_reinsert_addr */
+  0, /* decr_pc_after_break */
   ppc_breakpoint_at,
   ppc_supports_z_point_type,
   ppc_insert_point,
   ppc_remove_point,
-  NULL,
-  NULL,
+  NULL, /* stopped_by_watchpoint */
+  NULL, /* stopped_data_address */
   ppc_collect_ptrace_register,
   ppc_supply_ptrace_register,
+  NULL, /* siginfo_fixup */
+  NULL, /* linux_new_process */
+  NULL, /* linux_new_thread */
+  NULL, /* linux_new_fork */
+  NULL, /* linux_prepare_to_resume */
+  NULL, /* linux_process_qsupported */
+  ppc_supports_tracepoints,
+  ppc_get_thread_area,
+  ppc_install_fast_tracepoint_jump_pad,
+#if __PPC64__
+  ppc_emit_ops,
+#else
+  NULL, /* Use interpreter for ppc32.  */
+#endif
+  ppc_get_min_fast_tracepoint_insn_len,
+  ppc_supports_range_stepping,
 };
 
 void
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index d947879..7924227 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -83,6 +83,9 @@
 #include "features/rs6000/powerpc-e500.c"
 #include "features/rs6000/rs6000.c"
 
+#include "ax.h"
+#include "ax-gdb.h"
+
 /* Determine if regnum is an SPE pseudo-register.  */
 #define IS_SPE_PSEUDOREG(tdep, regnum) ((tdep)->ppc_ev0_regnum >= 0 \
     && (regnum) >= (tdep)->ppc_ev0_regnum \
@@ -966,6 +969,53 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
     return little_breakpoint;
 }
 
+/* Return true if ADDR is a valid address for tracepoint.  Set *ISZIE
+   to the number of bytes the target should copy elsewhere for the
+   tracepoint.  */
+
+static int
+ppc_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
+			      CORE_ADDR addr, int *isize, char **msg)
+{
+  CORE_ADDR base, pagesz;
+  const int SCRATCH_BUFFER_NPAGES = 20;
+  int isValid = 1;
+
+  if (isize)
+    *isize = gdbarch_max_insn_length (gdbarch);
+
+  /* If we can figure out where is the jump-pad, check whether
+     the address for tracepoint is too far away.  Otherwise,
+     assume it is valid.  */
+  if (target_auxv_search (&current_target, AT_PHDR, &base) > 0
+      && target_auxv_search (&current_target, AT_PAGESZ, &pagesz) > 0)
+    {
+      /* The jump-pad is supposed to be mapped here.
+	 See gdbserver/linux-ppc-ipa.c and gdbserver/tracepoint.c.  */
+      long dist;
+      CORE_ADDR jpad_base
+	= (base & ~(pagesz - 1)) - SCRATCH_BUFFER_NPAGES * pagesz;
+
+      dist = jpad_base - addr;
+      if (dist >= (1 << 25) || dist < -(1 << 25))
+	isValid = 0;
+    }
+
+  if (isValid)
+    {
+      if (msg)
+	*msg = NULL;
+    }
+  else
+    {
+      if (msg)
+	*msg = xstrdup (_("The address is too far for "
+			  "inserting fast tracepoint."));
+    }
+
+  return isValid;
+}
+
 /* Instruction masks for displaced stepping.  */
 #define BRANCH_MASK 0xfc000000
 #define BP_MASK 0xFC0007FE
@@ -3709,6 +3759,8 @@ bfd_uses_spe_extensions (bfd *abfd)
 #define PPC_LK(insn)	PPC_BIT (insn, 31)
 #define PPC_TX(insn)	PPC_BIT (insn, 31)
 #define PPC_LEV(insn)	PPC_FIELD (insn, 20, 7)
+#define PPC_LI(insn)	(PPC_SEXT (PPC_FIELD (insn, 6, 24), 24) << 2)
+#define PPC_BD(insn)	(PPC_SEXT (PPC_FIELD (insn, 16, 14), 14) << 2)
 
 #define PPC_XT(insn)	((PPC_TX (insn) << 5) | PPC_T (insn))
 #define PPC_XER_NB(xer)	(xer & 0x7f)
@@ -5362,6 +5414,68 @@ UNKNOWN_OP:
   return 0;
 }
 
+/* Implement gdbarch_gen_return_address.  Generate a bytecode expression
+   to get the value of the saved PC.  SCOPE is the address we want to
+   get return address for.  SCOPE maybe in the middle of a function.  */
+
+static void
+ppc_gen_return_address (struct gdbarch *gdbarch,
+			struct agent_expr *ax, struct axs_value *value,
+			CORE_ADDR scope)
+{
+  struct rs6000_framedata frame;
+  CORE_ADDR func_addr;
+
+  /* Try to find the start of the function and analyze the prologue.  */
+  if (find_pc_partial_function (scope, NULL, &func_addr, NULL))
+    {
+      skip_prologue (gdbarch, func_addr, scope, &frame);
+
+      if (frame.lr_offset == 0)
+	{
+	  value->type = register_type (gdbarch, PPC_LR_REGNUM);
+	  value->kind = axs_lvalue_register;
+	  value->u.reg = PPC_LR_REGNUM;
+	  return;
+	}
+    }
+  else
+    {
+      /* If we don't know where the function starts, we cannot analyze it.
+	 Assuming it's not a leaf function, not frameless, and LR is
+	 saved at back-chain +16 (or +4 for 32-bit ABI).  */
+
+      frame.frameless = 0;
+#if __PPC64__
+      frame.lr_offset = 16;
+#else
+      frame.lr_offset = 4;
+#endif
+    }
+
+  /* if (frameless)
+       load 16(SP)
+     else
+       BC = 0(SP)
+       load 16(BC) */
+
+  ax_reg (ax, gdbarch_sp_regnum (gdbarch));
+
+  /* Load back-chain.  */
+  if (!frame.frameless)
+    {
+      if (register_size (gdbarch, PPC_LR_REGNUM) == 8)
+	ax_simple (ax, aop_ref64);
+      else
+	ax_simple (ax, aop_ref32);
+    }
+
+  ax_const_l (ax, frame.lr_offset);
+  ax_simple (ax, aop_add);
+  value->type = register_type (gdbarch, PPC_LR_REGNUM);
+  value->kind = axs_lvalue_memory;
+}
+
 /* Initialize the current architecture based on INFO.  If possible, re-use an
    architecture from ARCHES, which is a list of architectures already created
    during this debugging session.
@@ -5922,6 +6036,7 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
 
   set_gdbarch_inner_than (gdbarch, core_addr_lessthan);
   set_gdbarch_breakpoint_from_pc (gdbarch, rs6000_breakpoint_from_pc);
+  set_gdbarch_fast_tracepoint_valid_at (gdbarch, ppc_fast_tracepoint_valid_at);
 
   /* The value of symbols of type N_SO and N_FUN maybe null when
      it shouldn't be.  */
@@ -5959,6 +6074,8 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_displaced_step_location (gdbarch,
 				       displaced_step_at_entry_point);
 
+  set_gdbarch_gen_return_address (gdbarch, ppc_gen_return_address);
+
   set_gdbarch_max_insn_length (gdbarch, PPC_INSN_SIZE);
 
   /* Hook in ABI-specific overrides, if they have been registered.  */
diff --git a/gdb/testsuite/gdb.trace/actions.c b/gdb/testsuite/gdb.trace/actions.c
index 4b7b887..f4ec871 100644
--- a/gdb/testsuite/gdb.trace/actions.c
+++ b/gdb/testsuite/gdb.trace/actions.c
@@ -46,6 +46,11 @@ static union GDB_UNION_TEST
 } gdb_union1_test;
 
 void gdb_recursion_test (int, int, int, int,  int,  int,  int);
+/* This function pointer is used to force the function called via
+   global entry instead of local entry; otherwise, breakpoints set
+   at the global entry (i.e., '*foo') will not be hit.  */
+typedef void (*gdb_recursion_test_fp) (int, int, int, int,  int,  int,  int);
+gdb_recursion_test_fp gdb_recursion_test_ptr = gdb_recursion_test;
 
 void gdb_recursion_test (int depth, 
 			 int q1, 
@@ -64,7 +69,7 @@ void gdb_recursion_test (int depth,
   q5 = q6;						/* gdbtestline 6 */
   q6 = q;						/* gdbtestline 7 */
   if (depth--)						/* gdbtestline 8 */
-    gdb_recursion_test (depth, q1, q2, q3, q4, q5, q6);	/* gdbtestline 9 */
+    gdb_recursion_test_ptr (depth, q1, q2, q3, q4, q5, q6);	/* gdbtestline 9 */
 }
 
 
@@ -103,7 +108,7 @@ unsigned long   gdb_c_test( unsigned long *parm )
    gdb_structp_test      = &gdb_struct1_test;
    gdb_structpp_test     = &gdb_structp_test;
 
-   gdb_recursion_test (3, (long) parm[1], (long) parm[2], (long) parm[3],
+   gdb_recursion_test_ptr (3, (long) parm[1], (long) parm[2], (long) parm[3],
 		       (long) parm[4], (long) parm[5], (long) parm[6]);
 
    gdb_char_test = gdb_short_test = gdb_long_test = 0;
diff --git a/gdb/testsuite/gdb.trace/backtrace.exp b/gdb/testsuite/gdb.trace/backtrace.exp
index 045778e..3094074 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 [istarget "powerpc*-*-*"] {
+    set fpreg "\$r31"
+    set spreg "\$r1"
 } else {
     set fpreg "\$fp"
     set spreg "\$sp"
diff --git a/gdb/testsuite/gdb.trace/change-loc.h b/gdb/testsuite/gdb.trace/change-loc.h
index e8e2e86..070a137 100644
--- a/gdb/testsuite/gdb.trace/change-loc.h
+++ b/gdb/testsuite/gdb.trace/change-loc.h
@@ -36,6 +36,8 @@ func4 (void)
        SYMBOL(set_tracepoint) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(func5) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 
diff --git a/gdb/testsuite/gdb.trace/collection.exp b/gdb/testsuite/gdb.trace/collection.exp
index bd42cfa..ed562c9 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 [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
diff --git a/gdb/testsuite/gdb.trace/entry-values.exp b/gdb/testsuite/gdb.trace/entry-values.exp
index 0cf5615..7295a1f 100644
--- a/gdb/testsuite/gdb.trace/entry-values.exp
+++ b/gdb/testsuite/gdb.trace/entry-values.exp
@@ -42,7 +42,7 @@ if { [istarget "arm*-*-*"] || [istarget "aarch64*-*-*"] } {
 } elseif { [istarget "s390*-*-*"] } {
     set call_insn "brasl"
 } elseif { [istarget "powerpc*-*-*"] } {
-    set call_insn "bl"
+    set call_insn {bl\y}
 } elseif { [istarget "mips*-*-*"] } {
     # Skip the delay slot after the instruction used to make a call
     # (which can be a jump or a branch) if it has one.
@@ -218,6 +218,8 @@ if [is_amd64_regs_target] {
     set spreg "\$rsp"
 } elseif [is_x86_like_target] {
     set spreg "\$esp"
+} elseif [istarget "powerpc*-*-*"] {
+    set spreg "\$r1"
 } else {
     set spreg "\$sp"
 }
diff --git a/gdb/testsuite/gdb.trace/ftrace.c b/gdb/testsuite/gdb.trace/ftrace.c
index f522e6f..dc727d2 100644
--- a/gdb/testsuite/gdb.trace/ftrace.c
+++ b/gdb/testsuite/gdb.trace/ftrace.c
@@ -42,6 +42,8 @@ marker (int anarg)
        SYMBOL(set_point) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(func) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 
@@ -53,6 +55,8 @@ marker (int anarg)
        SYMBOL(four_byter) ":\n"
 #if (defined __i386__)
        "    cmpl $0x1,0x8(%ebp) \n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index a8eb515..328c1d1 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -84,7 +84,8 @@ proc test_fast_tracepoints {} {
 
     gdb_test "print gdb_agent_gdb_trampoline_buffer_error" ".*" ""
 
-    if { [istarget "x86_64-*-*"] || [istarget "i\[34567\]86-*-*"] } {
+    if { [istarget "x86_64-*-*"] || [istarget "i\[34567\]86-*-*"] \
+	 || [istarget "powerpc*-*-*"] } {
 
 	gdb_test "ftrace set_point" "Fast tracepoint .*" \
 	    "fast tracepoint at a long insn"
@@ -243,6 +244,10 @@ if [is_amd64_regs_target] {
     set arg0exp "\$rdi"
 } elseif [is_x86_like_target] {
     set arg0exp "*(int *) (\$ebp + 8)"
+} elseif [istarget "powerpc*-*-*"] {
+    set arg0exp "\$r3"
+} elseif [istarget "aarch64*"] {
+    set arg0exp "\$x0"
 } else {
     set arg0exp ""
 }
diff --git a/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp b/gdb/testsuite/gdb.trace/mi-trace-frame-collected.exp
index 51ed479..1df4d65 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 [istarget "powerpc*-*-*"] {
+    set pcreg "pc"
 } else {
     # Other ports that support tracepoints should set the name of pc
     # register here.
diff --git a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
index 6b97d9d..1e6e541 100644
--- a/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
+++ b/gdb/testsuite/gdb.trace/mi-trace-unavailable.exp
@@ -135,6 +135,8 @@ proc test_trace_unavailable { data_source } {
 	    set pcnum 16
 	} elseif [is_x86_like_target] {
 	    set pcnum 8
+	} elseif [istarget "powerpc*-*-*"] {
+	    set pcnum 64
 	} else {
 	    # Other ports support tracepoint should define the number
 	    # of its own pc register.
diff --git a/gdb/testsuite/gdb.trace/pending.exp b/gdb/testsuite/gdb.trace/pending.exp
index 0399807..ed36cac 100644
--- a/gdb/testsuite/gdb.trace/pending.exp
+++ b/gdb/testsuite/gdb.trace/pending.exp
@@ -441,6 +441,8 @@ proc pending_tracepoint_with_action_resolved { trace_type } \
 	set pcreg "rip"
     } elseif [is_x86_like_target] {
 	set pcreg "eip"
+    } elseif [istarget "powerpc*-*-*"] {
+	set pcreg "pc"
     }
 
     gdb_trace_setactions "set action for pending tracepoint" "" \
diff --git a/gdb/testsuite/gdb.trace/pendshr1.c b/gdb/testsuite/gdb.trace/pendshr1.c
index d3b5463..5ab3fbe 100644
--- a/gdb/testsuite/gdb.trace/pendshr1.c
+++ b/gdb/testsuite/gdb.trace/pendshr1.c
@@ -38,6 +38,8 @@ pendfunc (int x)
        SYMBOL(set_point1) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(pendfunc1) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/pendshr2.c b/gdb/testsuite/gdb.trace/pendshr2.c
index b8a51a5..8b21e75 100644
--- a/gdb/testsuite/gdb.trace/pendshr2.c
+++ b/gdb/testsuite/gdb.trace/pendshr2.c
@@ -35,6 +35,8 @@ pendfunc2 (int x)
        SYMBOL(set_point2) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(foo) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/range-stepping.c b/gdb/testsuite/gdb.trace/range-stepping.c
index 113f0e2..f87464c 100644
--- a/gdb/testsuite/gdb.trace/range-stepping.c
+++ b/gdb/testsuite/gdb.trace/range-stepping.c
@@ -26,6 +26,8 @@
    tracepoint jump.  */
 #if (defined __x86_64__ || defined __i386__)
 #  define NOP "   .byte 0xe9,0x00,0x00,0x00,0x00\n" /* jmp $+5 (5-byte nop) */
+#elif (defined __powerpc64__ || defined __powerpc__)
+#  define NOP "    nop\n"
 #else
 #  define NOP "" /* port me */
 #endif
diff --git a/gdb/testsuite/gdb.trace/report.exp b/gdb/testsuite/gdb.trace/report.exp
index 2fa676b..e0160f7 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 [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
diff --git a/gdb/testsuite/gdb.trace/trace-break.c b/gdb/testsuite/gdb.trace/trace-break.c
index f381ec6..43174cc 100644
--- a/gdb/testsuite/gdb.trace/trace-break.c
+++ b/gdb/testsuite/gdb.trace/trace-break.c
@@ -41,6 +41,8 @@ marker (void)
        SYMBOL(set_point) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(func) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 
@@ -48,6 +50,8 @@ marker (void)
        SYMBOL(after_set_point) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(func) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/trace-break.exp b/gdb/testsuite/gdb.trace/trace-break.exp
index 4283ca6..9d6551a 100644
--- a/gdb/testsuite/gdb.trace/trace-break.exp
+++ b/gdb/testsuite/gdb.trace/trace-break.exp
@@ -49,6 +49,10 @@ if [is_amd64_regs_target] {
     set fpreg "ebp"
     set spreg "esp"
     set pcreg "eip"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
 }
 
 # Set breakpoint and tracepoint at the same address.
diff --git a/gdb/testsuite/gdb.trace/trace-mt.c b/gdb/testsuite/gdb.trace/trace-mt.c
index 38aeff5..0441a89 100644
--- a/gdb/testsuite/gdb.trace/trace-mt.c
+++ b/gdb/testsuite/gdb.trace/trace-mt.c
@@ -37,6 +37,8 @@ thread_function(void *arg)
        SYMBOL(set_point1) ":\n"
 #if (defined __x86_64__ || defined __i386__)
        "    call " SYMBOL(func) "\n"
+#elif (defined __powerpc64__ || defined __powerpc__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/unavailable.exp b/gdb/testsuite/gdb.trace/unavailable.exp
index 5be9704..ad62e75 100644
--- a/gdb/testsuite/gdb.trace/unavailable.exp
+++ b/gdb/testsuite/gdb.trace/unavailable.exp
@@ -34,6 +34,10 @@ if [is_amd64_regs_target] {
     set fpreg "ebp"
     set spreg "esp"
     set pcreg "eip"
+} elseif [istarget "powerpc*-*-*"] {
+    set fpreg "r31"
+    set spreg "r1"
+    set pcreg "pc"
 } else {
     set fpreg "fp"
     set spreg "sp"
diff --git a/gdb/testsuite/gdb.trace/while-dyn.exp b/gdb/testsuite/gdb.trace/while-dyn.exp
index 198421e..ef92b2d 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 [istarget "powerpc*-*-*"] {
+    set fpreg "\$r31"
 } else {
     set fpreg "\$fp"
 }
-- 
1.9.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver.
  2015-06-27 16:21 [PATCH 1/5 v4] Remove tracepoint_action ops Wei-cheng Wang
  2015-06-27 16:22 ` [PATCH 5/5 v4] Allow target to decide where to map jump-pad Wei-cheng Wang
  2015-06-27 16:22 ` [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition Wei-cheng Wang
@ 2015-06-27 16:22 ` Wei-cheng Wang
  2015-07-03 15:17   ` Ulrich Weigand
  2016-02-24 12:05   ` Marcin Kościelnicki
  2015-06-27 16:22 ` [PATCH 4/5 v4] Tracepoint for ppc64 Wei-cheng Wang
  2015-06-30  9:57 ` [PATCH 1/5 v4] Remove tracepoint_action ops Pedro Alves
  4 siblings, 2 replies; 17+ messages in thread
From: Wei-cheng Wang @ 2015-06-27 16:22 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

Hi,

Ulrich Weigand wrote:
> Well, if we add a function that returns true on supports_z_point_type
> for Z_PACKET_SW_BP, then we also need to provide functions that
> actually do insert/remove such breakpoints.  (I know that you have
> that in the next patch, but each patch in a series should be
> functionally correct on its own, so they really should be here.)

Merge ppc_insert_point and ppc_insert_point to this patch.

Thanks,
Wei-cheng


---

Support z-point, so tracepoints and breakpoints can be inserted at the same
location.

gdb/gdbserver/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* linux-ppc-low.c (ppc_supports_z_point_type): New function:
	(ppc_insert_point, ppc_remove_point): Insert/remove z-packet breakpoints.
	(ppc64_emit_ops_vector): Add target ops - ppc_supports_z_point_type,
	ppc_insert_point, ppc_remove_point.
---
 gdb/gdbserver/linux-ppc-low.c | 69 +++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 66 insertions(+), 3 deletions(-)

diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 188fac0..41ec281 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -512,6 +512,69 @@ ppc_breakpoint_at (CORE_ADDR where)
   return 0;
 }
 
+/* Implement supports_z_point_type target-ops.
+   Returns true if type Z_TYPE breakpoint is supported.
+
+   Handling software breakpoint at server side, so tracepoints
+   and breakpoints can be inserted at the same location.  */
+
+static int
+ppc_supports_z_point_type (char z_type)
+{
+  switch (z_type)
+    {
+    case Z_PACKET_SW_BP:
+      return 1;
+    case Z_PACKET_HW_BP:
+    case Z_PACKET_WRITE_WP:
+    case Z_PACKET_ACCESS_WP:
+    default:
+      return 0;
+    }
+}
+
+/* Implement insert_point target-ops.
+   Returns 0 on success, -1 on failure and 1 on unsupported.  */
+
+static int
+ppc_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
+		  int size, struct raw_breakpoint *bp)
+{
+  switch (type)
+    {
+    case raw_bkpt_type_sw:
+      return insert_memory_breakpoint (bp);
+
+    case raw_bkpt_type_hw:
+    case raw_bkpt_type_write_wp:
+    case raw_bkpt_type_access_wp:
+    default:
+      /* Unsupported.  */
+      return 1;
+    }
+}
+
+/* Implement remove_point target-ops.
+   Returns 0 on success, -1 on failure and 1 on unsupported.  */
+
+static int
+ppc_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
+		  int size, struct raw_breakpoint *bp)
+{
+  switch (type)
+    {
+    case raw_bkpt_type_sw:
+      return remove_memory_breakpoint (bp);
+
+    case raw_bkpt_type_hw:
+    case raw_bkpt_type_write_wp:
+    case raw_bkpt_type_access_wp:
+    default:
+      /* Unsupported.  */
+      return 1;
+    }
+}
+
 /* Provide only a fill function for the general register set.  ps_lgetregs
    will use this for NPTL support.  */
 
@@ -690,9 +753,9 @@ struct linux_target_ops the_low_target = {
   NULL,
   0,
   ppc_breakpoint_at,
-  NULL, /* supports_z_point_type */
-  NULL,
-  NULL,
+  ppc_supports_z_point_type,
+  ppc_insert_point,
+  ppc_remove_point,
   NULL,
   NULL,
   ppc_collect_ptrace_register,
-- 
1.9.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition.
  2015-06-27 16:21 [PATCH 1/5 v4] Remove tracepoint_action ops Wei-cheng Wang
  2015-06-27 16:22 ` [PATCH 5/5 v4] Allow target to decide where to map jump-pad Wei-cheng Wang
@ 2015-06-27 16:22 ` Wei-cheng Wang
  2015-06-30  9:57   ` Pedro Alves
                     ` (2 more replies)
  2015-06-27 16:22 ` [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver Wei-cheng Wang
                   ` (2 subsequent siblings)
  4 siblings, 3 replies; 17+ messages in thread
From: Wei-cheng Wang @ 2015-06-27 16:22 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

Hi,

Ulrich Weigand wrote:
> Ah, when I said to add new test cases in a separate patch, what I meant was:
> - use a separate patch (applied *first*) that adds the *new tests* (to be
>   run on existing platforms), i.e. test_ftrace_condition
> - as part of the patch that actually adds powerpc support, add all the small
>   test case snippets that specifically enable the test cases for powerpc
> This is again so that each set in a series is meaningful in itself (and
> does not introduce testsuite regressions when applied alone).
...
> Wei-cheng Wang wrote:
> >if (tpoint->compiled_cond)
> >   err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
> >
> >I think probably either we could pass ctx->regs to compiled_cond instead,
> >or move the declarations of fast_tracepoint_ctx (and others) to tracepoint.h,
> >so we can use "offsetof (fast_tracepoint_ctx, regs)" instead.
> >Any suggestion?
> FWIW, passing the regs buffer directly to the compiled routine seems
> more straightforward to me ...

Some of the new cases are used to testing emit-reg, and emit-reg for x86
doesn't work due to the incorrect argument to compiled_cond - "regs" buffer
is expected, but tracepoint context is passed

This case also includes the fix for complied_cond in order for x86 to
pass testing for emit-reg op.

Testing result on my x86_64 Ubuntu 14.04.2 TLS

               before   w/ new cases only  w/ the fix
  PASS         2625     2759               2765
  FAIL           33       39                 33
  XFAIL          16       16                 16
  KFAIL           2        2                  2
  UNTESTED        1        1                  1
  UNSUPPORTED     3        3                  3

Thanks,
Wei-cheng

---

* Fix generating emit-reg op by passing register buffer to compiled_cond.
* Add a new function for testing compiled-cond by checking whether
  based on a given CONDEXP, a list of expected values should be collected.

---

gdb/gdbserver/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* tracepoint.c (eval_result_type): Change prototype.
	(condition_true_at_tracepoint): Fix argument to compiled_cond.

gdb/testsuite/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* gdb.trace/ftrace.exp: (test_ftrace_condition) New function
	for testing bytecode compilation.
---
 gdb/gdbserver/tracepoint.c         |  7 +++--
 gdb/testsuite/gdb.trace/ftrace.exp | 64 ++++++++++++++++++++++++++++++++++++++
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 57b329d9..fdec7db 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -697,7 +697,7 @@ enum tracepoint_type
 
 struct tracepoint_hit_ctx;
 
-typedef enum eval_result_type (*condfn) (struct tracepoint_hit_ctx *,
+typedef enum eval_result_type (*condfn) (unsigned char *,
 					 ULONGEST *);
 
 /* The definition of a tracepoint.  */
@@ -4903,7 +4903,10 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
      used.  */
 #ifdef IN_PROCESS_AGENT
   if (tpoint->compiled_cond)
-    err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
+    {
+      struct fast_tracepoint_ctx *fctx = (struct fast_tracepoint_ctx *) ctx;
+      err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (fctx->regs, &value);
+    }
   else
 #endif
     {
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index f2d8002..a8eb515 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -178,6 +178,42 @@ proc test_fast_tracepoints {} {
     }
 }
 
+# Test compiled-condition
+# CONDEXP is the condition expression to be compiled.
+# VAR is the variable to be collected for testing.
+# LIST is a list of expected values of VAR should be collected
+# based on the CONDEXP.
+proc test_ftrace_condition { condexp var list } \
+{ with_test_prefix "ond $condexp" \
+{
+    global executable
+    global hex
+
+    clean_restart ${executable}
+    if ![runto_main] {
+	fail "Can't run to main to check for trace support"
+	return -1
+    }
+
+    gdb_test "break end" ".*" ""
+    gdb_test "tvariable \$tsv = 0"
+    gdb_test "ftrace set_point if $condexp" "Fast tracepoint .*"
+    gdb_trace_setactions "set action for tracepoint .*" "" \
+	"collect $var" "^$"
+
+    gdb_test_no_output "tstart" ""
+    gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" ""
+    gdb_test_no_output "tstop" ""
+
+    set i 0
+    foreach expval $list {
+	gdb_test "tfind" "Found trace frame $i, tracepoint .*" "tfind frame $i"
+	gdb_test "print $var" "\\$\[0-9\]+ = $expval\[\r\n\]" "expect $expval"
+	set i [expr $i + 1]
+    }
+    gdb_test "tfind" "Target failed to find requested trace frame\."
+}}
+
 gdb_reinitialize_dir $srcdir/$subdir
 
 if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
@@ -186,3 +222,31 @@ if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
 }
 
 test_fast_tracepoints
+
+# Test conditional goto and simple expression.
+test_ftrace_condition "globvar > 7" "globvar" { 8 9 10 }
+test_ftrace_condition "globvar < 4" "globvar" { 1 2 3 }
+test_ftrace_condition "globvar >= 7" "globvar" { 7 8 9 10 }
+test_ftrace_condition "globvar <= 4" "globvar" { 1 2 3 4 }
+test_ftrace_condition "globvar == 5" "globvar" { 5 }
+test_ftrace_condition "globvar != 5" "globvar" { 1 2 3 4 6 7 8 9 10 }
+test_ftrace_condition "globvar > 3 && globvar < 7" "globvar" { 4 5 6 }
+test_ftrace_condition "globvar < 3 || globvar > 7" "globvar" { 1 2 8 9 10 }
+test_ftrace_condition "(globvar << 2) + 1 == 29" "globvar" { 7 }
+test_ftrace_condition "(globvar >> 2) == 2" "globvar" { 8 9 10 }
+
+# Test emit_call by accessing trace state variables.
+test_ftrace_condition "(\$tsv = \$tsv + 2) > 10" "globvar" { 6 7 8 9 10 }
+
+# This expression is used for testing emit_reg.
+if [is_amd64_regs_target] {
+    set arg0exp "\$rdi"
+} elseif [is_x86_like_target] {
+    set arg0exp "*(int *) (\$ebp + 8)"
+} else {
+    set arg0exp ""
+}
+
+if { "$arg0exp" != "" } {
+    test_ftrace_condition "($arg0exp > 500)" "globvar" { 6 7 8 9 10 }
+}
-- 
1.9.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* [PATCH 5/5 v4] Allow target to decide where to map jump-pad.
  2015-06-27 16:21 [PATCH 1/5 v4] Remove tracepoint_action ops Wei-cheng Wang
@ 2015-06-27 16:22 ` Wei-cheng Wang
  2015-07-03 16:38   ` Ulrich Weigand
  2015-06-27 16:22 ` [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition Wei-cheng Wang
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 17+ messages in thread
From: Wei-cheng Wang @ 2015-06-27 16:22 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

Ulrich Weigand wrote:
> Looks OK to me.  Note that getauxval was only introduced with
> a relatively recent glibc release, so might warrant a configure
> check to avoid breaking the build on older releases ...

Current configure.ac had alreadly check getauxval,

  AC_CHECK_FUNCS(getauxval pread pwrite pread64 setns)

so I simply add the old-fashioned-way getauxval fallback if it's not there.

Thanks,
Wei-cheng

---

This patch adds an IPA function, jump_pad_area_hint, for giving a hint
where to map jump pad buffer.  For some targets, addr = page-size is
too far to reach from executable.

gdb/gdbserver/ChangeLog

2015-06-27  Wei-cheng Wang  <cole945@gmail.com>

	* tracepoint.c (initialize_tracepoint): Call jump_pad_area_hint
        to get where to map gdb_jump_pad_buffer.  Remove MAP_FIXED.
	* tracepoint.h (jump_pad_area_hint): Add declaration.
	* linux-amd64-ipa.c (jump_pad_area_hint): New function.
	* linux-i386-ipa.c (jump_pad_area_hint): New function.
	* linux-ppc-ipa.c (jump_pad_area_hint): New function.
	(getauxvl): New function.
---
 gdb/gdbserver/linux-amd64-ipa.c | 10 ++++++++
 gdb/gdbserver/linux-i386-ipa.c  | 10 ++++++++
 gdb/gdbserver/linux-ppc-ipa.c   | 51 +++++++++++++++++++++++++++++++++++++++++
 gdb/gdbserver/tracepoint.c      |  7 +++---
 gdb/gdbserver/tracepoint.h      |  3 +++
 5 files changed, 77 insertions(+), 4 deletions(-)

diff --git a/gdb/gdbserver/linux-amd64-ipa.c b/gdb/gdbserver/linux-amd64-ipa.c
index a6dfb03..65cd748 100644
--- a/gdb/gdbserver/linux-amd64-ipa.c
+++ b/gdb/gdbserver/linux-amd64-ipa.c
@@ -77,6 +77,16 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
   return *(ULONGEST *) (raw_regs + x86_64_ft_collect_regmap[regnum]);
 }
 
+/* See tracepoint.h.  */
+
+uintptr_t
+jump_pad_area_hint (void)
+{
+  /* Allocate scratch buffer aligned on a page boundary, at a low
+     address (close to the main executable's code).  */
+  return sysconf (_SC_PAGE_SIZE);
+}
+
 #ifdef HAVE_UST
 
 #include <ust/processor.h>
diff --git a/gdb/gdbserver/linux-i386-ipa.c b/gdb/gdbserver/linux-i386-ipa.c
index eb30dcd..dc0dfaf 100644
--- a/gdb/gdbserver/linux-i386-ipa.c
+++ b/gdb/gdbserver/linux-i386-ipa.c
@@ -114,6 +114,16 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
     return *(int *) (raw_regs + i386_ft_collect_regmap[regnum]);
 }
 
+/* See tracepoint.h.  */
+
+uintptr_t
+jump_pad_area_hint (void)
+{
+  /* Allocate scratch buffer aligned on a page boundary, at a low
+     address (close to the main executable's code).  */
+  return sysconf (_SC_PAGE_SIZE);
+}
+
 #ifdef HAVE_UST
 
 #include <ust/processor.h>
diff --git a/gdb/gdbserver/linux-ppc-ipa.c b/gdb/gdbserver/linux-ppc-ipa.c
index 73d8899..ddb2174 100644
--- a/gdb/gdbserver/linux-ppc-ipa.c
+++ b/gdb/gdbserver/linux-ppc-ipa.c
@@ -21,6 +21,8 @@
 #include "server.h"
 #include "tracepoint.h"
 
+#include <sys/auxv.h>
+
 #if defined __PPC64__
 void init_registers_powerpc_64l (void);
 extern const struct target_desc *tdesc_powerpc_64l;
@@ -105,6 +107,55 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
 			+ ppc_ft_collect_regmap[regnum] * REGSZ);
 }
 
+#ifndef HAVE_GETAUXVAL
+/* Retrieve the value of TYPE from the auxiliary vector.  If TYPE is not
+   found, 0 is returned.  This function is provided if glibc is too old.  */
+
+static unsigned long
+getauxval (unsigned long type)
+{
+  unsigned long data[2];
+  FILE *f = fopen ("/proc/self/auxv", "r");
+  unsigned long value = 0;
+
+  if (f == NULL)
+    return 0;
+
+  while (fread (data, sizeof (data), 1, f) > 0)
+    {
+      if (data[0] == AT_HWCAP)
+	{
+	  value = data[1];
+	  break;
+	}
+    }
+
+  fclose (f);
+  return value;
+}
+#endif
+
+/* See tracepoint.h.  */
+
+uintptr_t
+jump_pad_area_hint (void)
+{
+  /* Use AT_PHDR address to guess where the main executable is mapped,
+     and try to map the jump pad before it.  The jump pad should be
+     closed enough to the executable for unconditional branch (+/- 32MB). */
+
+  const int SCRATCH_BUFFER_NPAGES = 20;
+  uintptr_t base = getauxval (AT_PHDR);
+  uintptr_t pagesz = sysconf (_SC_PAGE_SIZE);
+  uintptr_t hint = (base & ~(pagesz - 1)) - SCRATCH_BUFFER_NPAGES * pagesz;
+
+  /* Return the lowest possible value if wrap-around.  */
+  if (hint > base)
+    hint = pagesz;
+
+  return hint;
+}
+
 /* Initialize ipa_tdesc and others.  */
 
 void
diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index fdec7db..d1c03cf 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -7355,13 +7355,12 @@ initialize_tracepoint (void)
 
 #define SCRATCH_BUFFER_NPAGES 20
 
-    /* Allocate scratch buffer aligned on a page boundary, at a low
-       address (close to the main executable's code).  */
-    for (addr = pagesize; addr != 0; addr += pagesize)
+    addr = jump_pad_area_hint ();
+    for (; addr != 0; addr += pagesize)
       {
 	gdb_jump_pad_buffer = mmap ((void *) addr, pagesize * SCRATCH_BUFFER_NPAGES,
 				    PROT_READ | PROT_WRITE | PROT_EXEC,
-				    MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
+				    MAP_PRIVATE | MAP_ANONYMOUS,
 				    -1, 0);
 	if (gdb_jump_pad_buffer != MAP_FAILED)
 	  break;
diff --git a/gdb/gdbserver/tracepoint.h b/gdb/gdbserver/tracepoint.h
index 30d0b58..139894f 100644
--- a/gdb/gdbserver/tracepoint.h
+++ b/gdb/gdbserver/tracepoint.h
@@ -131,6 +131,9 @@ void supply_static_tracepoint_registers (struct regcache *regcache,
 					 CORE_ADDR pc);
 void set_trampoline_buffer_space (CORE_ADDR begin, CORE_ADDR end,
 				  char *errmsg);
+/* Return the address for where to allocate buffer for jump pad.
+   The buffer should be close enough for tracepoints.  */
+uintptr_t jump_pad_area_hint (void);
 
 extern const struct target_desc *ipa_tdesc;
 
-- 
1.9.1

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/5 v4] Tracepoint for ppc64.
  2015-06-27 16:22 ` [PATCH 4/5 v4] Tracepoint for ppc64 Wei-cheng Wang
@ 2015-06-28  6:21   ` Wei-cheng Wang
  2015-06-29 15:54   ` Pierre Langlois
  2015-07-03 16:37   ` Ulrich Weigand
  2 siblings, 0 replies; 17+ messages in thread
From: Wei-cheng Wang @ 2015-06-28  6:21 UTC (permalink / raw)
  To: Ulrich Weigand, gdb-patches

Hi,

I forgot to mention two more things.

A new function (gdbserver target op), ppc_get_thread_area, is implemented
used for the jump pad lock object (collecting_t). Please have a look.

Changing timeout in tspeed.exp is reverted in this patch.  Recently I
tested the patch on gcc112 server and timeout should be 540 instead of 360
in order to pass tspeed.exp.  I am not sure what's the proper value for timeout.
Maybe someone will test it in another environment, and 540 is not enough again.

Thanks,
Wei-cheng

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/5 v4] Tracepoint for ppc64.
  2015-06-27 16:22 ` [PATCH 4/5 v4] Tracepoint for ppc64 Wei-cheng Wang
  2015-06-28  6:21   ` Wei-cheng Wang
@ 2015-06-29 15:54   ` Pierre Langlois
  2015-07-03 16:37   ` Ulrich Weigand
  2 siblings, 0 replies; 17+ messages in thread
From: Pierre Langlois @ 2015-06-29 15:54 UTC (permalink / raw)
  To: gdb-patches, Wei-cheng Wang

On 27/06/15 17:21, Wei-cheng Wang wrote:
> Ulrich Weigand wrote:
>> Wei-cheng Wang wrote:
>>> Ulrich Weigand wrote:
>>>> Wei-cheng Wang wrote:
>>>>> +static int
>>>>> +ppc_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
>>>>> +                        CORE_ADDR addr, int *isize, char **msg)
>>>>> +{
>>>>> +  if (isize)
>>>>> +    *isize = gdbarch_max_insn_length (gdbarch);
>>>>> +  if (msg)
>>>>> +    *msg = NULL;
>>>>> +  return 1;
>>>>> +}
>>>>
>>>> Should/can we check here where the jump to the jump pad will be in
>>>> range?  Might be better to detect this early ...
>>>
>>> Client has no idea about where the jump pad will be installed.
>>> If it's out of range, gdbserver will report it right after user
>>> entered 'tstart' command
>> Well, but we know the logic the stub uses.  For example, we know that
>> we certainly cannot install a fast tracepoint in any shared library code,
>> since the jump pad will definitely be too far away.  We can check for
>> this condition here.  (We could also check for tracepoints in executables
>> that have a text section larger than 32 MB ...)
> 
> Now in this path, ppc_fast_tracepoint_valid_at will check the distance
> and return 0 (invalid) if ADDR is too far from jumppad.
> 
> However, if a tracepoint was pending and later found it's not valid,
> it will cause an internal-error.  See remote.c
> 
>   if (gdbarch_fast_tracepoint_valid_at (target_gdbarch (),
>                                         tpaddr, &isize, NULL))
>     xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":F%x",
>                isize);
>   else
>     /* If it passed validation at definition but fails now,
>        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>        something is very wrong.  */
>     internal_error (__FILE__, __LINE__, _("Fast tracepoint not "
>                                           "valid during download"));
> 
> If the tracepoint is pending at definition, it won't be checked at all.
> 
>   /* Fast tracepoints may have additional restrictions on location.  */
>   if (!pending && type_wanted == bp_fast_tracepoint)
>       ^^^^^^^^
>     {
>       for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
>         check_fast_tracepoint_sals (gdbarch, &iter->sals);
>     }
> 
> Maybe we use "error" instead of "internal_error"?

Hi Wei-cheng,

Is it OK for GDB to guess where the jump pad is based assumptions on how/where
GDBServer installs it?  I'm thinking one could implement another stub supporting
fast tracepoints differently (?).

Maybe we could extend/add a tracepoint packet in order for GDB to ask the stub
what the jump pad address is.  Or change the fast_tracepoint_valid_at gdbarch
method into a target method, leaving GDBServer to decide if a fast tracepoint is
valid early on.

Any thoughts?

Thanks,
Pierre

> diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
> index d947879..7924227 100644
> --- a/gdb/rs6000-tdep.c
> +++ b/gdb/rs6000-tdep.c
> @@ -83,6 +83,9 @@
>  #include "features/rs6000/powerpc-e500.c"
>  #include "features/rs6000/rs6000.c"
> 
> +#include "ax.h"
> +#include "ax-gdb.h"
> +
>  /* Determine if regnum is an SPE pseudo-register.  */
>  #define IS_SPE_PSEUDOREG(tdep, regnum) ((tdep)->ppc_ev0_regnum >= 0 \
>      && (regnum) >= (tdep)->ppc_ev0_regnum \
> @@ -966,6 +969,53 @@ rs6000_breakpoint_from_pc (struct gdbarch *gdbarch, CORE_ADDR *bp_addr,
>      return little_breakpoint;
>  }
> 
> +/* Return true if ADDR is a valid address for tracepoint.  Set *ISZIE
> +   to the number of bytes the target should copy elsewhere for the
> +   tracepoint.  */
> +
> +static int
> +ppc_fast_tracepoint_valid_at (struct gdbarch *gdbarch,
> +                             CORE_ADDR addr, int *isize, char **msg)
> +{
> +  CORE_ADDR base, pagesz;
> +  const int SCRATCH_BUFFER_NPAGES = 20;
> +  int isValid = 1;
> +
> +  if (isize)
> +    *isize = gdbarch_max_insn_length (gdbarch);
> +
> +  /* If we can figure out where is the jump-pad, check whether
> +     the address for tracepoint is too far away.  Otherwise,
> +     assume it is valid.  */
> +  if (target_auxv_search (&current_target, AT_PHDR, &base) > 0
> +      && target_auxv_search (&current_target, AT_PAGESZ, &pagesz) > 0)
> +    {
> +      /* The jump-pad is supposed to be mapped here.
> +        See gdbserver/linux-ppc-ipa.c and gdbserver/tracepoint.c.  */
> +      long dist;
> +      CORE_ADDR jpad_base
> +       = (base & ~(pagesz - 1)) - SCRATCH_BUFFER_NPAGES * pagesz;
> +
> +      dist = jpad_base - addr;
> +      if (dist >= (1 << 25) || dist < -(1 << 25))
> +       isValid = 0;
> +    }
> +
> +  if (isValid)
> +    {
> +      if (msg)
> +       *msg = NULL;
> +    }
> +  else
> +    {
> +      if (msg)
> +       *msg = xstrdup (_("The address is too far for "
> +                         "inserting fast tracepoint."));
> +    }
> +
> +  return isValid;
> +}
> +
>  /* Instruction masks for displaced stepping.  */
>  #define BRANCH_MASK 0xfc000000
>  #define BP_MASK 0xFC0007FE

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition.
  2015-06-27 16:22 ` [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition Wei-cheng Wang
@ 2015-06-30  9:57   ` Pedro Alves
  2015-09-14 14:04   ` Pierre Langlois
  2015-09-16 16:15   ` Yao Qi
  2 siblings, 0 replies; 17+ messages in thread
From: Pedro Alves @ 2015-06-30  9:57 UTC (permalink / raw)
  To: Wei-cheng Wang, uweigand, gdb-patches

On 06/27/2015 05:21 PM, Wei-cheng Wang wrote:
> Hi,
> 
> Ulrich Weigand wrote:
>> > Ah, when I said to add new test cases in a separate patch, what I meant was:
>> > - use a separate patch (applied *first*) that adds the *new tests* (to be
>> >   run on existing platforms), i.e. test_ftrace_condition
>> > - as part of the patch that actually adds powerpc support, add all the small
>> >   test case snippets that specifically enable the test cases for powerpc
>> > This is again so that each set in a series is meaningful in itself (and
>> > does not introduce testsuite regressions when applied alone).
> ...
>> > Wei-cheng Wang wrote:
>>> > >if (tpoint->compiled_cond)
>>> > >   err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
>>> > >
>>> > >I think probably either we could pass ctx->regs to compiled_cond instead,
>>> > >or move the declarations of fast_tracepoint_ctx (and others) to tracepoint.h,
>>> > >so we can use "offsetof (fast_tracepoint_ctx, regs)" instead.
>>> > >Any suggestion?
>> > FWIW, passing the regs buffer directly to the compiled routine seems
>> > more straightforward to me ...
> Some of the new cases are used to testing emit-reg, and emit-reg for x86
> doesn't work due to the incorrect argument to compiled_cond - "regs" buffer
> is expected, but tracepoint context is passed
> 
> This case also includes the fix for complied_cond in order for x86 to
> pass testing for emit-reg op.
> 
> Testing result on my x86_64 Ubuntu 14.04.2 TLS
> 
>                before   w/ new cases only  w/ the fix
>   PASS         2625     2759               2765
>   FAIL           33       39                 33
>   XFAIL          16       16                 16
>   KFAIL           2        2                  2
>   UNTESTED        1        1                  1
>   UNSUPPORTED     3        3                  3
> 
> Thanks,
> Wei-cheng
> 
> ---
> 
> * Fix generating emit-reg op by passing register buffer to compiled_cond.
> * Add a new function for testing compiled-cond by checking whether
>   based on a given CONDEXP, a list of expected values should be collected.
> 
> ---

FWIW, looks good to me too.  Thanks for the new tests!

Thanks,
Pedro Alves

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 1/5 v4] Remove tracepoint_action ops.
  2015-06-27 16:21 [PATCH 1/5 v4] Remove tracepoint_action ops Wei-cheng Wang
                   ` (3 preceding siblings ...)
  2015-06-27 16:22 ` [PATCH 4/5 v4] Tracepoint for ppc64 Wei-cheng Wang
@ 2015-06-30  9:57 ` Pedro Alves
  4 siblings, 0 replies; 17+ messages in thread
From: Pedro Alves @ 2015-06-30  9:57 UTC (permalink / raw)
  To: Wei-cheng Wang, uweigand, gdb-patches

On 06/27/2015 05:21 PM, Wei-cheng Wang wrote:

> This patch removes 'ops' in tracepoint, and uses helper functions to
> call action handler instead.
> 
> The object layout of tracepoint_action may differ in gdbserver and
> inferior depend on the alignment rule of target ABI, so gdbserver cannot
> simply copy the object from its memory to inferior memory.
> 
> For example,
> 
>   struct collect_memory_action
>   {
>     struct tracepoint_action base;
>     {
>       #ifndef IN_PROCESS_AGENT
>       const struct tracepoint_action_ops *ops;
>       #if
>   -   char type;
>   | }
>   | ULONGEST addr;
>   | ULONGEST len;
>   - int32_t basereg;
>   };
> 
> and on PowerPC,
> 
>      Wihtout ops           with ops
>       0   1   2   3         0   1   2   3
>    0 |type| PADDING...    0 |ops-------------|
>    4 .................    4 |type|PADDING....|
>    8 |addr------------    8 |addr-------------
>    c ----------------|    c -----------------|
>   10 |len-------------   10 |len--------------
>   14 ----------------|   14 -----------------|
>   18 |basereg--------|   18 |basereg---------|
> 
> so we cannot directly copy the object.
> 
> In this patch, 'ops' is removed in order to make the objects identical.
> 
> gdbserver/ChangeLog
> 
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* tracepoint.c (struct tracepoint_action): Remove ops.
> 	(m_tracepoint_action_download, r_tracepoint_action_download,
> 	x_tracepoint_action_download, l_tracepoint_action_download): Adjust
> 	size and offset accordingly.
> 	(m_tracepoint_action_ops, r_tracepoint_action_ops,
> 	x_tracepoint_action_ops, l_tracepoint_action_ops): Delete
> 	(tracepoint_action_send, tracepoint_action_download): New functions.
> 	Helpers for tracetion action handlers.
> 	(add_tracepoint_action): Remove setup actions ops.
> 	(download_tracepoint_1, tracepoint_send_agent): Call helper functions.
> ---

FAOD, this looks fine to me.

Thanks,
-- 
Pedro Alves

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver.
  2015-06-27 16:22 ` [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver Wei-cheng Wang
@ 2015-07-03 15:17   ` Ulrich Weigand
  2016-02-24 12:05   ` Marcin Kościelnicki
  1 sibling, 0 replies; 17+ messages in thread
From: Ulrich Weigand @ 2015-07-03 15:17 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> Support z-point, so tracepoints and breakpoints can be inserted at the same
> location.
> 
> gdb/gdbserver/ChangeLog
> 
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* linux-ppc-low.c (ppc_supports_z_point_type): New function:
> 	(ppc_insert_point, ppc_remove_point): Insert/remove z-packet breakpoints.
> 	(ppc64_emit_ops_vector): Add target ops - ppc_supports_z_point_type,
> 	ppc_insert_point, ppc_remove_point.

This is OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 4/5 v4] Tracepoint for ppc64.
  2015-06-27 16:22 ` [PATCH 4/5 v4] Tracepoint for ppc64 Wei-cheng Wang
  2015-06-28  6:21   ` Wei-cheng Wang
  2015-06-29 15:54   ` Pierre Langlois
@ 2015-07-03 16:37   ` Ulrich Weigand
  2 siblings, 0 replies; 17+ messages in thread
From: Ulrich Weigand @ 2015-07-03 16:37 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> Ulrich Weigand wrote:
> > Well, but we know the logic the stub uses.  For example, we know that
> > we certainly cannot install a fast tracepoint in any shared library code,
> > since the jump pad will definitely be too far away.  We can check for
> > this condition here.  (We could also check for tracepoints in executables
> > that have a text section larger than 32 MB ...)
> 
> Now in this path, ppc_fast_tracepoint_valid_at will check the distance
> and return 0 (invalid) if ADDR is too far from jumppad.
> 
> However, if a tracepoint was pending and later found it's not valid,
> it will cause an internal-error.  See remote.c
> 
>   if (gdbarch_fast_tracepoint_valid_at (target_gdbarch (),
> 					tpaddr, &isize, NULL))
>     xsnprintf (buf + strlen (buf), BUF_SIZE - strlen (buf), ":F%x",
> 	       isize);
>   else
>     /* If it passed validation at definition but fails now,
>        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
>        something is very wrong.  */
>     internal_error (__FILE__, __LINE__, _("Fast tracepoint not "
> 					  "valid during download"));
> 
> If the tracepoint is pending at definition, it won't be checked at all.
> 
>   /* Fast tracepoints may have additional restrictions on location.  */
>   if (!pending && type_wanted == bp_fast_tracepoint)
>       ^^^^^^^^
>     {
>       for (ix = 0; VEC_iterate (linespec_sals, canonical.sals, ix, iter); ++ix)
> 	check_fast_tracepoint_sals (gdbarch, &iter->sals);
>     }
> 
> Maybe we use "error" instead of "internal_error"?

Huh.  Shouldn't the location be re-checked in breakpoint.c once the
tracepoint is re-set from "pending" to active?  It seems there's a
call to gdbarch_fast_tracepoint_valid_at missing at that point.
(If the gdbarch_fast_tracepoint_valid_at fails then, we probably
should emit an error and either leave the tracepoint pending or
else convert it to a regular tracepoint at that point.)

> A new function (gdbserver target op), ppc_get_thread_area, is implemented
> used for the jump pad lock object (collecting_t). Please have a look.

This looks fine to me.

> Changing timeout in tspeed.exp is reverted in this patch.  Recently I
> tested the patch on gcc112 server and timeout should be 540 instead of 360
> in order to pass tspeed.exp.  I am not sure what's the proper value for timeout.
> Maybe someone will test it in another environment, and 540 is not enough again.

OK.  Do we know why the test case is taking so long?  Is this simply to be
expected, or is the slowness due to some hidden issue that should be fixed?  

> BTW, in this patch, unlock is implemented by simply writing 0 instead
> of a full atomic-swap.  It that ok?
> 
>   /* Prepare collecting_t object for lock.  */
>   p += GEN_STORE (p, 3, 1, min_frame + 37 * rsz);
>   p += GEN_STORE (p, tp_reg, 1, min_frame + 38 *rsz);
>   /* Set R5 to collecting object.  */
>   p += GEN_ADDI (p, 5, 1, 37 * rsz);
> 
>   p += gen_atomic_xchg (p, lockaddr, 0, 5);
> 
>   /* Call to collector.  */
>   p += gen_call (p, collector);
> 
>   /* Simply write 0 to release the lock.  */
>   p += gen_limm (p, 3, lockaddr);
>   p += gen_limm (p, 4, 0);
>   p += GEN_LWSYNC (p);
>   p += GEN_STORE (p, 4, 3, 0);

This should be OK.  However, we need to take care to use appropriate
syncs when taking the lock as well.

> +  /*
> +  1: lwsync
> +  2: lwarx   TMP, 0, LOCK
> +     cmpwi   TMP, OLD
> +     bne     1b
> +     stwcx.  NEW, 0, LOCK
> +     bne     2b */

In particular, in order to guarantee proper aqcuire semantics, there
needs to be an lwsync (or isync) *after* the loop here.

On the other hand, you do not need to loop back to the lwsync at the
beginning.  In fact, for a normal lock-acquire sequence you would not
need the lwsync before the loop at all.

However, in this specific case, since the lock value is itself a
pointer to a data structure, you *do* want to have a lwsync between
storing that data structure and taking the lock.

It's probably best to move the lwsync out of this subroutine and
place the two lwsyncs in the caller.


Also, a couple of comments from an earlier review still apply:

> +#if __PPC64__

Please use #ifdef __powerpc64__ throughout.

> +static int
> +gen_limm (uint32_t *buf, int reg, uint64_t imm)
> +{
> +  uint32_t *p = buf;
> +
> +  if ((imm + 32768) < 65536)
> +    {
> +      /* li	reg, imm[7:0] */
> +      p += GEN_LI (p, reg, imm);
> +    }
> +  else if ((imm >> 16) == 0)
> +    {
> +      /* li	reg, 0
> +	 ori	reg, reg, imm[15:0] */
> +      p += GEN_LI (p, reg, 0);
> +      p += GEN_ORI (p, reg, reg, imm);
> +    }
> +  else if ((imm >> 32) == 0)
> +    {
> +      /* lis	reg, imm[31:16]
> +	 ori	reg, reg, imm[15:0] */
> +      p += GEN_LIS (p, reg, (imm >> 16) & 0xffff);
> +      p += GEN_ORI (p, reg, reg, imm & 0xffff);

This is still incorrect if bit 31 of imm is set.
(The lis will fill the 32 high bits of the register
with 1 instead 0 in that case.)

> +static void
> +ppc_relocate_instruction (CORE_ADDR *to, CORE_ADDR oldloc)
> +{
[...]
> +      else if ((PPC_BO (insn) & 0x14) == 0x4 || (PPC_BO (insn) & 0x14) == 0x10)
> +	{
> +	  newrel -= 4;
> +
> +	  /* Out of range. Cannot relocate instruction.  */
> +	  if (newrel >= (1 << 25) || newrel < -(1 << 25))
> +	    return;
> +
> +	  if ((PPC_BO (insn) & 0x14) == 0x4)
> +	    insn ^= (1 << 24);
> +	  else if ((PPC_BO (insn) & 0x14) == 0x10)
> +	    insn ^= (1 << 22);
> +
> +	  /* Jump over the unconditional branch.  */
> +	  insn = (insn & ~0xfffc) | 0x8;
> +	  write_inferior_memory (*to, (unsigned char *) &insn, 4);
> +	  *to += 4;
> +
> +	  /* Build a unconditional branch and copy LK bit.  */
> +	  insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
> +	  write_inferior_memory (*to, (unsigned char *) &insn, 4);
> +	  *to += 4;
> +
> +	  return;
> +	}
> +      else

This should check for (PPC_BO (insn) & 0x14) == 0.
Note that (PPC_BO (insn) & 0x14) == 0x14 is the "branch always"
case, which should be replaced simply by an unconditional branch.

> +	{
> +	  uint32_t bdnz_insn = (16 << 26) | (0x10 << 21) | 12;
> +	  uint32_t bf_insn = (16 << 26) | (0x4 << 21) | 8;
> +
> +	  newrel -= 12;

That should be -= 8, shouldn't it?

> +static void
> +ppc64_emit_stack_adjust (int n)
> +{
> +  uint32_t buf[4];
> +  uint32_t *p = buf;
> +
> +  n = n << 3;
> +  if ((n >> 7) != 0)
> +    {
> +      emit_error = 1;
> +      return;
> +    }
> +
> +  p += GEN_ADDI (p, 30, 30, n);

ADDI supports up to 15-bit unsigned operands,
so this seems overly strict.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 5/5 v4] Allow target to decide where to map jump-pad.
  2015-06-27 16:22 ` [PATCH 5/5 v4] Allow target to decide where to map jump-pad Wei-cheng Wang
@ 2015-07-03 16:38   ` Ulrich Weigand
  0 siblings, 0 replies; 17+ messages in thread
From: Ulrich Weigand @ 2015-07-03 16:38 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* tracepoint.c (initialize_tracepoint): Call jump_pad_area_hint
>         to get where to map gdb_jump_pad_buffer.  Remove MAP_FIXED.
> 	* tracepoint.h (jump_pad_area_hint): Add declaration.
> 	* linux-amd64-ipa.c (jump_pad_area_hint): New function.
> 	* linux-i386-ipa.c (jump_pad_area_hint): New function.
> 	* linux-ppc-ipa.c (jump_pad_area_hint): New function.
> 	(getauxvl): New function.
Typo: getauxval.

This is OK.

Bye,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition.
  2015-06-27 16:22 ` [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition Wei-cheng Wang
  2015-06-30  9:57   ` Pedro Alves
@ 2015-09-14 14:04   ` Pierre Langlois
  2015-09-16 16:15   ` Yao Qi
  2 siblings, 0 replies; 17+ messages in thread
From: Pierre Langlois @ 2015-09-14 14:04 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: uweigand, gdb-patches, pierre.langlois, Pedro Alves

Hi Wei-cheng,

On 27/06/15 17:21, Wei-cheng Wang wrote:
> Hi,
> 
> Ulrich Weigand wrote:
>> Ah, when I said to add new test cases in a separate patch, what I meant was:
>> - use a separate patch (applied *first*) that adds the *new tests* (to be
>>   run on existing platforms), i.e. test_ftrace_condition
>> - as part of the patch that actually adds powerpc support, add all the small
>>   test case snippets that specifically enable the test cases for powerpc
>> This is again so that each set in a series is meaningful in itself (and
>> does not introduce testsuite regressions when applied alone).
> ...
>> Wei-cheng Wang wrote:
>>> if (tpoint->compiled_cond)
>>>   err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
>>>
>>> I think probably either we could pass ctx->regs to compiled_cond instead,
>>> or move the declarations of fast_tracepoint_ctx (and others) to tracepoint.h,
>>> so we can use "offsetof (fast_tracepoint_ctx, regs)" instead.
>>> Any suggestion?
>> FWIW, passing the regs buffer directly to the compiled routine seems
>> more straightforward to me ...
> 

I'm afraid I missed this patch before and just posted a patch fixing the
very same issue!  I'm sorry about that.

gdb-patches: https://sourceware.org/ml/gdb-patches/2015-09/msg00240.html
bugzilla: https://sourceware.org/bugzilla/show_bug.cgi?id=18955

However, I went down another route when fixing it.  Instead of modifying
`condition_true_at_tracepoint' to take the raw registers as argument, I
modified `gdb_agent_get_raw_reg' to take the fast tracepoint context.  And
since this context contains the regcache already, we can collect registers
in an architecture independent manner.

Any thoughts?

> Some of the new cases are used to testing emit-reg, and emit-reg for x86
> doesn't work due to the incorrect argument to compiled_cond - "regs" buffer
> is expected, but tracepoint context is passed
> 
> This case also includes the fix for complied_cond in order for x86 to
> pass testing for emit-reg op.
> 
> Testing result on my x86_64 Ubuntu 14.04.2 TLS
> 
>                before   w/ new cases only  w/ the fix
>   PASS         2625     2759               2765
>   FAIL           33       39                 33
>   XFAIL          16       16                 16
>   KFAIL           2        2                  2
>   UNTESTED        1        1                  1
>   UNSUPPORTED     3        3                  3
> 
> Thanks,
> Wei-cheng
> 
> ---
> 
> * Fix generating emit-reg op by passing register buffer to compiled_cond.
> * Add a new function for testing compiled-cond by checking whether
>   based on a given CONDEXP, a list of expected values should be collected.
> 
> ---
> 
> gdb/gdbserver/ChangeLog
> 
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* tracepoint.c (eval_result_type): Change prototype.
> 	(condition_true_at_tracepoint): Fix argument to compiled_cond.
> 
> gdb/testsuite/ChangeLog
> 
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* gdb.trace/ftrace.exp: (test_ftrace_condition) New function
> 	for testing bytecode compilation.
> ---
>  gdb/gdbserver/tracepoint.c         |  7 +++--
>  gdb/testsuite/gdb.trace/ftrace.exp | 64 ++++++++++++++++++++++++++++++++++++++
>  2 files changed, 69 insertions(+), 2 deletions(-)
> 
> diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
> index 57b329d9..fdec7db 100644
> --- a/gdb/gdbserver/tracepoint.c
> +++ b/gdb/gdbserver/tracepoint.c
> @@ -697,7 +697,7 @@ enum tracepoint_type
>  
>  struct tracepoint_hit_ctx;
>  
> -typedef enum eval_result_type (*condfn) (struct tracepoint_hit_ctx *,
> +typedef enum eval_result_type (*condfn) (unsigned char *,
>  					 ULONGEST *);
>  
>  /* The definition of a tracepoint.  */
> @@ -4903,7 +4903,10 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
>       used.  */
>  #ifdef IN_PROCESS_AGENT
>    if (tpoint->compiled_cond)
> -    err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
> +    {
> +      struct fast_tracepoint_ctx *fctx = (struct fast_tracepoint_ctx *) ctx;
> +      err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (fctx->regs, &value);
> +    }
>    else
>  #endif
>      {
> diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
> index f2d8002..a8eb515 100644
> --- a/gdb/testsuite/gdb.trace/ftrace.exp
> +++ b/gdb/testsuite/gdb.trace/ftrace.exp
> @@ -178,6 +178,42 @@ proc test_fast_tracepoints {} {
>      }
>  }
>  
> +# Test compiled-condition
> +# CONDEXP is the condition expression to be compiled.
> +# VAR is the variable to be collected for testing.
> +# LIST is a list of expected values of VAR should be collected
> +# based on the CONDEXP.
> +proc test_ftrace_condition { condexp var list } \
> +{ with_test_prefix "ond $condexp" \
> +{
> +    global executable
> +    global hex
> +
> +    clean_restart ${executable}
> +    if ![runto_main] {
> +	fail "Can't run to main to check for trace support"
> +	return -1
> +    }
> +
> +    gdb_test "break end" ".*" ""
> +    gdb_test "tvariable \$tsv = 0"
> +    gdb_test "ftrace set_point if $condexp" "Fast tracepoint .*"
> +    gdb_trace_setactions "set action for tracepoint .*" "" \
> +	"collect $var" "^$"
> +
> +    gdb_test_no_output "tstart" ""
> +    gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" ""
> +    gdb_test_no_output "tstop" ""
> +
> +    set i 0
> +    foreach expval $list {
> +	gdb_test "tfind" "Found trace frame $i, tracepoint .*" "tfind frame $i"
> +	gdb_test "print $var" "\\$\[0-9\]+ = $expval\[\r\n\]" "expect $expval"
> +	set i [expr $i + 1]
> +    }
> +    gdb_test "tfind" "Target failed to find requested trace frame\."
> +}}
> +
>  gdb_reinitialize_dir $srcdir/$subdir
>  
>  if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
> @@ -186,3 +222,31 @@ if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
>  }
>  
>  test_fast_tracepoints
> +
> +# Test conditional goto and simple expression.
> +test_ftrace_condition "globvar > 7" "globvar" { 8 9 10 }
> +test_ftrace_condition "globvar < 4" "globvar" { 1 2 3 }
> +test_ftrace_condition "globvar >= 7" "globvar" { 7 8 9 10 }
> +test_ftrace_condition "globvar <= 4" "globvar" { 1 2 3 4 }
> +test_ftrace_condition "globvar == 5" "globvar" { 5 }
> +test_ftrace_condition "globvar != 5" "globvar" { 1 2 3 4 6 7 8 9 10 }
> +test_ftrace_condition "globvar > 3 && globvar < 7" "globvar" { 4 5 6 }
> +test_ftrace_condition "globvar < 3 || globvar > 7" "globvar" { 1 2 8 9 10 }
> +test_ftrace_condition "(globvar << 2) + 1 == 29" "globvar" { 7 }
> +test_ftrace_condition "(globvar >> 2) == 2" "globvar" { 8 9 10 }
> +
> +# Test emit_call by accessing trace state variables.
> +test_ftrace_condition "(\$tsv = \$tsv + 2) > 10" "globvar" { 6 7 8 9 10 }

I also posted a very similar test case here:
https://sourceware.org/ml/gdb-patches/2015-09/msg00241.html.  It might be
good to merge them, what do you think?  I realize this test case is more
precise by checking the trace frame numbers explicitly with `tfind'.  The
test case I posted only just checks the number of trace frames is as
expected.

However, I'd be more in favour of moving these tests to their own files, and
checking conditions with both the `trace' and `ftrace' commands.

Sorry again for the duplication of work.

Thanks,
Pierre

> +
> +# This expression is used for testing emit_reg.
> +if [is_amd64_regs_target] {
> +    set arg0exp "\$rdi"
> +} elseif [is_x86_like_target] {
> +    set arg0exp "*(int *) (\$ebp + 8)"
> +} else {
> +    set arg0exp ""
> +}
> +
> +if { "$arg0exp" != "" } {
> +    test_ftrace_condition "($arg0exp > 500)" "globvar" { 6 7 8 9 10 }
> +}
> 

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition.
  2015-06-27 16:22 ` [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition Wei-cheng Wang
  2015-06-30  9:57   ` Pedro Alves
  2015-09-14 14:04   ` Pierre Langlois
@ 2015-09-16 16:15   ` Yao Qi
  2 siblings, 0 replies; 17+ messages in thread
From: Yao Qi @ 2015-09-16 16:15 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: uweigand, gdb-patches

Wei-cheng Wang <cole945@gmail.com> writes:

> * Fix generating emit-reg op by passing register buffer to compiled_cond.
> * Add a new function for testing compiled-cond by checking whether
>   based on a given CONDEXP, a list of expected values should be collected.
>
> ---
>
> gdb/gdbserver/ChangeLog
>
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
>
> 	* tracepoint.c (eval_result_type): Change prototype.
> 	(condition_true_at_tracepoint): Fix argument to compiled_cond.
>
> gdb/testsuite/ChangeLog
>
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
>
> 	* gdb.trace/ftrace.exp: (test_ftrace_condition) New function
> 	for testing bytecode compilation.

It was approved by Pedro, and I test this patch again on x86_64-linux,
no regressions.  Wei-cheng Wang has already had copyright assignment.  I'll
push this patch in as below.

-- 
Yao (齐尧)

From 93f470eba920b53d6bc1d46f855aec4398c1b8b7 Mon Sep 17 00:00:00 2001
From: Wei-cheng Wang <cole945@gmail.com>
Date: Wed, 16 Sep 2015 16:20:51 +0100
Subject: [PATCH] Fix argument to compiled_cond, and add cases for
 compiled-condition.

This patch fixes the argument passed to compiled_cond.  It should be
regs buffer instead of tracepoint_hit_ctx.  Test case is added as
well for testing compiled-cond.

gdb/gdbserver/ChangeLog

2015-09-16  Wei-cheng Wang  <cole945@gmail.com>

	* tracepoint.c (eval_result_type): Change prototype.
	(condition_true_at_tracepoint): Fix argument to compiled_cond.

gdb/testsuite/ChangeLog

2015-09-16  Wei-cheng Wang  <cole945@gmail.com>

	* gdb.trace/ftrace.exp: (test_ftrace_condition) New function
	for testing bytecode compilation.

diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index fd010ae..5e34eba 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -695,7 +695,7 @@ enum tracepoint_type
 
 struct tracepoint_hit_ctx;
 
-typedef enum eval_result_type (*condfn) (struct tracepoint_hit_ctx *,
+typedef enum eval_result_type (*condfn) (unsigned char *,
 					 ULONGEST *);
 
 /* The definition of a tracepoint.  */
@@ -4907,7 +4907,10 @@ condition_true_at_tracepoint (struct tracepoint_hit_ctx *ctx,
      used.  */
 #ifdef IN_PROCESS_AGENT
   if (tpoint->compiled_cond)
-    err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (ctx, &value);
+    {
+      struct fast_tracepoint_ctx *fctx = (struct fast_tracepoint_ctx *) ctx;
+      err = ((condfn) (uintptr_t) (tpoint->compiled_cond)) (fctx->regs, &value);
+    }
   else
 #endif
     {
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index f2d8002..a8eb515 100644
--- a/gdb/testsuite/gdb.trace/ftrace.exp
+++ b/gdb/testsuite/gdb.trace/ftrace.exp
@@ -178,6 +178,42 @@ proc test_fast_tracepoints {} {
     }
 }
 
+# Test compiled-condition
+# CONDEXP is the condition expression to be compiled.
+# VAR is the variable to be collected for testing.
+# LIST is a list of expected values of VAR should be collected
+# based on the CONDEXP.
+proc test_ftrace_condition { condexp var list } \
+{ with_test_prefix "ond $condexp" \
+{
+    global executable
+    global hex
+
+    clean_restart ${executable}
+    if ![runto_main] {
+	fail "Can't run to main to check for trace support"
+	return -1
+    }
+
+    gdb_test "break end" ".*" ""
+    gdb_test "tvariable \$tsv = 0"
+    gdb_test "ftrace set_point if $condexp" "Fast tracepoint .*"
+    gdb_trace_setactions "set action for tracepoint .*" "" \
+	"collect $var" "^$"
+
+    gdb_test_no_output "tstart" ""
+    gdb_test "continue" "Continuing\\.\[ \r\n\]+Breakpoint.*" ""
+    gdb_test_no_output "tstop" ""
+
+    set i 0
+    foreach expval $list {
+	gdb_test "tfind" "Found trace frame $i, tracepoint .*" "tfind frame $i"
+	gdb_test "print $var" "\\$\[0-9\]+ = $expval\[\r\n\]" "expect $expval"
+	set i [expr $i + 1]
+    }
+    gdb_test "tfind" "Target failed to find requested trace frame\."
+}}
+
 gdb_reinitialize_dir $srcdir/$subdir
 
 if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
@@ -186,3 +222,31 @@ if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
 }
 
 test_fast_tracepoints
+
+# Test conditional goto and simple expression.
+test_ftrace_condition "globvar > 7" "globvar" { 8 9 10 }
+test_ftrace_condition "globvar < 4" "globvar" { 1 2 3 }
+test_ftrace_condition "globvar >= 7" "globvar" { 7 8 9 10 }
+test_ftrace_condition "globvar <= 4" "globvar" { 1 2 3 4 }
+test_ftrace_condition "globvar == 5" "globvar" { 5 }
+test_ftrace_condition "globvar != 5" "globvar" { 1 2 3 4 6 7 8 9 10 }
+test_ftrace_condition "globvar > 3 && globvar < 7" "globvar" { 4 5 6 }
+test_ftrace_condition "globvar < 3 || globvar > 7" "globvar" { 1 2 8 9 10 }
+test_ftrace_condition "(globvar << 2) + 1 == 29" "globvar" { 7 }
+test_ftrace_condition "(globvar >> 2) == 2" "globvar" { 8 9 10 }
+
+# Test emit_call by accessing trace state variables.
+test_ftrace_condition "(\$tsv = \$tsv + 2) > 10" "globvar" { 6 7 8 9 10 }
+
+# This expression is used for testing emit_reg.
+if [is_amd64_regs_target] {
+    set arg0exp "\$rdi"
+} elseif [is_x86_like_target] {
+    set arg0exp "*(int *) (\$ebp + 8)"
+} else {
+    set arg0exp ""
+}
+
+if { "$arg0exp" != "" } {
+    test_ftrace_condition "($arg0exp > 500)" "globvar" { 6 7 8 9 10 }
+}

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver.
  2015-06-27 16:22 ` [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver Wei-cheng Wang
  2015-07-03 15:17   ` Ulrich Weigand
@ 2016-02-24 12:05   ` Marcin Kościelnicki
  2016-02-24 17:37     ` Ulrich Weigand
  1 sibling, 1 reply; 17+ messages in thread
From: Marcin Kościelnicki @ 2016-02-24 12:05 UTC (permalink / raw)
  To: Wei-cheng Wang, uweigand, gdb-patches

Another old approved patch that I'd like to push.  Testing on 
ppc+ppc64+ppc64le:

gdb.base/dprintf.exp: agent: 1st dprintf UNSUPPORTED -> PASS×3
gdb.base/jit.exp: PIE: one_jit_test-1: set var libname = 
"SHLIBDIR/jit-solib.so" PASS -> FAIL, on ppc64 only (I don't consider 
that one a problem, since jit.exp already has lots of similiar FAILs for 
this arch, nothing really new is broken here)
gdb.mi/mi-dprintf.exp: mi expect stop FAIL×5 -> PASS×4
gdb.threads/forking-threads-plus-breakpoint.exp: cond_bp_target=1: 
detach_on_fork=on: displaced=off FAIL -> PASS×3
gdb.threads/process-dies-while-handling-bp.exp: non_stop=on: 
cond_bp_target=1: KFAIL (memory error) -> KFAIL (prompt)
gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: 
cond_bp_target=[01]: inferior 1 exited PASS×2 -> KFAIL (PRMS: gdb/18749)

Fixes a lot of gdb.trace tests if I enable tracepoints.

On 27/06/15 18:21, Wei-cheng Wang wrote:
> Support z-point, so tracepoints and breakpoints can be inserted at the same
> location.
>
> gdb/gdbserver/ChangeLog
>
> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
>
> 	* linux-ppc-low.c (ppc_supports_z_point_type): New function:
> 	(ppc_insert_point, ppc_remove_point): Insert/remove z-packet breakpoints.
> 	(ppc64_emit_ops_vector): Add target ops - ppc_supports_z_point_type,
> 	ppc_insert_point, ppc_remove_point.
> ---
>   gdb/gdbserver/linux-ppc-low.c | 69 +++++++++++++++++++++++++++++++++++++++++--
>   1 file changed, 66 insertions(+), 3 deletions(-)
>
> diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
> index 188fac0..41ec281 100644
> --- a/gdb/gdbserver/linux-ppc-low.c
> +++ b/gdb/gdbserver/linux-ppc-low.c
> @@ -512,6 +512,69 @@ ppc_breakpoint_at (CORE_ADDR where)
>     return 0;
>   }
>
> +/* Implement supports_z_point_type target-ops.
> +   Returns true if type Z_TYPE breakpoint is supported.
> +
> +   Handling software breakpoint at server side, so tracepoints
> +   and breakpoints can be inserted at the same location.  */
> +
> +static int
> +ppc_supports_z_point_type (char z_type)
> +{
> +  switch (z_type)
> +    {
> +    case Z_PACKET_SW_BP:
> +      return 1;
> +    case Z_PACKET_HW_BP:
> +    case Z_PACKET_WRITE_WP:
> +    case Z_PACKET_ACCESS_WP:
> +    default:
> +      return 0;
> +    }
> +}
> +
> +/* Implement insert_point target-ops.
> +   Returns 0 on success, -1 on failure and 1 on unsupported.  */
> +
> +static int
> +ppc_insert_point (enum raw_bkpt_type type, CORE_ADDR addr,
> +		  int size, struct raw_breakpoint *bp)
> +{
> +  switch (type)
> +    {
> +    case raw_bkpt_type_sw:
> +      return insert_memory_breakpoint (bp);
> +
> +    case raw_bkpt_type_hw:
> +    case raw_bkpt_type_write_wp:
> +    case raw_bkpt_type_access_wp:
> +    default:
> +      /* Unsupported.  */
> +      return 1;
> +    }
> +}
> +
> +/* Implement remove_point target-ops.
> +   Returns 0 on success, -1 on failure and 1 on unsupported.  */
> +
> +static int
> +ppc_remove_point (enum raw_bkpt_type type, CORE_ADDR addr,
> +		  int size, struct raw_breakpoint *bp)
> +{
> +  switch (type)
> +    {
> +    case raw_bkpt_type_sw:
> +      return remove_memory_breakpoint (bp);
> +
> +    case raw_bkpt_type_hw:
> +    case raw_bkpt_type_write_wp:
> +    case raw_bkpt_type_access_wp:
> +    default:
> +      /* Unsupported.  */
> +      return 1;
> +    }
> +}
> +
>   /* Provide only a fill function for the general register set.  ps_lgetregs
>      will use this for NPTL support.  */
>
> @@ -690,9 +753,9 @@ struct linux_target_ops the_low_target = {
>     NULL,
>     0,
>     ppc_breakpoint_at,
> -  NULL, /* supports_z_point_type */
> -  NULL,
> -  NULL,
> +  ppc_supports_z_point_type,
> +  ppc_insert_point,
> +  ppc_remove_point,
>     NULL,
>     NULL,
>     ppc_collect_ptrace_register,
>

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver.
  2016-02-24 12:05   ` Marcin Kościelnicki
@ 2016-02-24 17:37     ` Ulrich Weigand
  2016-02-24 17:39       ` Marcin Kościelnicki
  0 siblings, 1 reply; 17+ messages in thread
From: Ulrich Weigand @ 2016-02-24 17:37 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: Wei-cheng Wang, gdb-patches

> Another old approved patch that I'd like to push.  Testing on 
> ppc+ppc64+ppc64le:
> 
> gdb.base/dprintf.exp: agent: 1st dprintf UNSUPPORTED -> PASS×3
> gdb.base/jit.exp: PIE: one_jit_test-1: set var libname = 
> "SHLIBDIR/jit-solib.so" PASS -> FAIL, on ppc64 only (I don't consider 
> that one a problem, since jit.exp already has lots of similiar FAILs for 
> this arch, nothing really new is broken here)
> gdb.mi/mi-dprintf.exp: mi expect stop FAIL×5 -> PASS×4
> gdb.threads/forking-threads-plus-breakpoint.exp: cond_bp_target=1: 
> detach_on_fork=on: displaced=off FAIL -> PASS×3
> gdb.threads/process-dies-while-handling-bp.exp: non_stop=on: 
> cond_bp_target=1: KFAIL (memory error) -> KFAIL (prompt)
> gdb.threads/process-dies-while-handling-bp.exp: non_stop=off: 
> cond_bp_target=[01]: inferior 1 exited PASS×2 -> KFAIL (PRMS: gdb/18749)
> 
> Fixes a lot of gdb.trace tests if I enable tracepoints.
> 
> On 27/06/15 18:21, Wei-cheng Wang wrote:
> > Support z-point, so tracepoints and breakpoints can be inserted at the same
> > location.
> >
> > gdb/gdbserver/ChangeLog
> >
> > 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
> >
> > 	* linux-ppc-low.c (ppc_supports_z_point_type): New function:
> > 	(ppc_insert_point, ppc_remove_point): Insert/remove z-packet breakpoints.
> > 	(ppc64_emit_ops_vector): Add target ops - ppc_supports_z_point_type,
> > 	ppc_insert_point, ppc_remove_point.

Yes, this is also still OK.

Thanks,
Ulrich

-- 
  Dr. Ulrich Weigand
  GNU/Linux compilers and toolchain
  Ulrich.Weigand@de.ibm.com

^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver.
  2016-02-24 17:37     ` Ulrich Weigand
@ 2016-02-24 17:39       ` Marcin Kościelnicki
  0 siblings, 0 replies; 17+ messages in thread
From: Marcin Kościelnicki @ 2016-02-24 17:39 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Wei-cheng Wang, gdb-patches

On 24/02/16 18:36, Ulrich Weigand wrote:
>> Another old approved patch that I'd like to push.  Testing on
>> ppc+ppc64+ppc64le:
>>
>> gdb.base/dprintf.exp: agent: 1st dprintf UNSUPPORTED -> PASS×3
>> gdb.base/jit.exp: PIE: one_jit_test-1: set var libname =
>> "SHLIBDIR/jit-solib.so" PASS -> FAIL, on ppc64 only (I don't consider
>> that one a problem, since jit.exp already has lots of similiar FAILs for
>> this arch, nothing really new is broken here)
>> gdb.mi/mi-dprintf.exp: mi expect stop FAIL×5 -> PASS×4
>> gdb.threads/forking-threads-plus-breakpoint.exp: cond_bp_target=1:
>> detach_on_fork=on: displaced=off FAIL -> PASS×3
>> gdb.threads/process-dies-while-handling-bp.exp: non_stop=on:
>> cond_bp_target=1: KFAIL (memory error) -> KFAIL (prompt)
>> gdb.threads/process-dies-while-handling-bp.exp: non_stop=off:
>> cond_bp_target=[01]: inferior 1 exited PASS×2 -> KFAIL (PRMS: gdb/18749)
>>
>> Fixes a lot of gdb.trace tests if I enable tracepoints.
>>
>> On 27/06/15 18:21, Wei-cheng Wang wrote:
>>> Support z-point, so tracepoints and breakpoints can be inserted at the same
>>> location.
>>>
>>> gdb/gdbserver/ChangeLog
>>>
>>> 2015-06-27  Wei-cheng Wang  <cole945@gmail.com>
>>>
>>> 	* linux-ppc-low.c (ppc_supports_z_point_type): New function:
>>> 	(ppc_insert_point, ppc_remove_point): Insert/remove z-packet breakpoints.
>>> 	(ppc64_emit_ops_vector): Add target ops - ppc_supports_z_point_type,
>>> 	ppc_insert_point, ppc_remove_point.
>
> Yes, this is also still OK.
>
> Thanks,
> Ulrich
>

Thanks, pushed.

^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~2016-02-24 17:39 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-06-27 16:21 [PATCH 1/5 v4] Remove tracepoint_action ops Wei-cheng Wang
2015-06-27 16:22 ` [PATCH 5/5 v4] Allow target to decide where to map jump-pad Wei-cheng Wang
2015-07-03 16:38   ` Ulrich Weigand
2015-06-27 16:22 ` [PATCH 3/5 v4] Fix argument to compiled_cond, and add cases for compiled-condition Wei-cheng Wang
2015-06-30  9:57   ` Pedro Alves
2015-09-14 14:04   ` Pierre Langlois
2015-09-16 16:15   ` Yao Qi
2015-06-27 16:22 ` [PATCH 2/5 v4] powerpc: Support z-point type in gdbserver Wei-cheng Wang
2015-07-03 15:17   ` Ulrich Weigand
2016-02-24 12:05   ` Marcin Kościelnicki
2016-02-24 17:37     ` Ulrich Weigand
2016-02-24 17:39       ` Marcin Kościelnicki
2015-06-27 16:22 ` [PATCH 4/5 v4] Tracepoint for ppc64 Wei-cheng Wang
2015-06-28  6:21   ` Wei-cheng Wang
2015-06-29 15:54   ` Pierre Langlois
2015-07-03 16:37   ` Ulrich Weigand
2015-06-30  9:57 ` [PATCH 1/5 v4] Remove tracepoint_action ops Pedro Alves

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).