public inbox for gdb-patches@sourceware.org
 help / color / mirror / Atom feed
* [PATCH 3/7 v3] Add testcases for ppc64 tracepoint.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
  2015-03-30 16:31 ` [PATCH 7/7 v3] Remove tracepoint_action ops Wei-cheng Wang
@ 2015-03-30 16:31 ` Wei-cheng Wang
  2015-04-08 17:02   ` Ulrich Weigand
  2015-03-30 16:31 ` [PATCH 4/7 v3] Allow target to decide where to map jump-pad Wei-cheng Wang
                   ` (4 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

One more case in added for testing emit_reg in this version.

gdb/testsuite/ChangeLog

2015-03-30  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*-*-*.
	(test_ftrace_condition) New function for testing bytecode compilation.
---
 gdb/testsuite/gdb.trace/actions.c                  |  6 +-
 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                 | 66 +++++++++++++++++++++-
 .../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/tspeed.exp                 |  2 +-
 gdb/testsuite/gdb.trace/unavailable.exp            |  4 ++
 gdb/testsuite/gdb.trace/while-dyn.exp              |  2 +
 20 files changed, 118 insertions(+), 5 deletions(-)

diff --git a/gdb/testsuite/gdb.trace/actions.c b/gdb/testsuite/gdb.trace/actions.c
index 4b7b887..d8538e4 100644
--- a/gdb/testsuite/gdb.trace/actions.c
+++ b/gdb/testsuite/gdb.trace/actions.c
@@ -46,6 +46,8 @@ static union GDB_UNION_TEST
 } gdb_union1_test;
 
 void gdb_recursion_test (int, int, int, int,  int,  int,  int);
+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 +66,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 +105,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..8efe12d 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 __PPC64__ || defined __PPC__)
+       "    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..e509c7b 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 __PPC64__ || defined __PPC__)
+       "    nop\n"
 #endif
        );
 
@@ -53,6 +55,8 @@ marker (int anarg)
        SYMBOL(four_byter) ":\n"
 #if (defined __i386__)
        "    cmpl $0x1,0x8(%ebp) \n"
+#elif (defined __PPC64__ || defined __PPC__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/ftrace.exp b/gdb/testsuite/gdb.trace/ftrace.exp
index f2d8002..d459ac9 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"
@@ -178,6 +179,37 @@ proc test_fast_tracepoints {} {
     }
 }
 
+proc test_ftrace_condition { condexp 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 globvar" "^$"
+
+    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 globvar" "\\$\[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 +218,35 @@ if { [gdb_test "info sharedlibrary" ".*${libipa}.*" "IPA loaded"] != 0 } {
 }
 
 test_fast_tracepoints
+
+# Test conditional goto and simple expression.
+test_ftrace_condition "globvar > 7" { 8 9 10 }
+test_ftrace_condition "globvar < 4" { 1 2 3 }
+test_ftrace_condition "globvar >= 7" { 7 8 9 10 }
+test_ftrace_condition "globvar <= 4" { 1 2 3 4 }
+test_ftrace_condition "globvar == 5" { 5 }
+test_ftrace_condition "globvar != 5" { 1 2 3 4 6 7 8 9 10 }
+test_ftrace_condition "globvar > 3 && globvar < 7" { 4 5 6 }
+test_ftrace_condition "globvar < 3 || globvar > 7" { 1 2 8 9 10 }
+test_ftrace_condition "(globvar << 2) + 1 == 29" { 7 }
+test_ftrace_condition "(globvar >> 2) == 2" { 8 9 10 }
+
+# Test emit_call by accessing trace state variables.
+test_ftrace_condition "(\$tsv = \$tsv + 2) > 10" { 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)"
+} elseif [istarget "powerpc*-*-*"] {
+    set arg0exp "\$r3"
+} elseif [istarget "aarch64*"] {
+    set arg0exp "\$x0"
+} else {
+    set arg0exp ""
+}
+
+if { "$arg0exp" != "" } {
+    test_ftrace_condition "($arg0exp > 500)" { 6 7 8 9 10 }
+}
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..2fd0fba 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 __PPC64__ || defined __PPC__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/pendshr2.c b/gdb/testsuite/gdb.trace/pendshr2.c
index b8a51a5..3f40c76 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 __PPC64__ || defined __PPC__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/range-stepping.c b/gdb/testsuite/gdb.trace/range-stepping.c
index 113f0e2..606db25 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 __PPC64__ || defined __PPC__)
+#  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..ced0e92 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 __PPC64__ || defined __PPC__)
+       "    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 __PPC64__ || defined __PPC__)
+       "    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..855de54 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 __PPC64__ || defined __PPC__)
+       "    nop\n"
 #endif
        );
 }
diff --git a/gdb/testsuite/gdb.trace/tspeed.exp b/gdb/testsuite/gdb.trace/tspeed.exp
index d44eba9..209312c 100644
--- a/gdb/testsuite/gdb.trace/tspeed.exp
+++ b/gdb/testsuite/gdb.trace/tspeed.exp
@@ -27,7 +27,7 @@ if { [gdb_compile "$srcdir/$subdir/$srcfile" $binfile \
 }
 
 # Typically we need a little extra time for this test.
-set timeout 180
+set timeout 360
 
 set ws "\[\r\n\t \]+"
 set cr "\[\r\n\]+"
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] 21+ messages in thread

* [PATCH 4/7 v3] Allow target to decide where to map jump-pad.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
  2015-03-30 16:31 ` [PATCH 7/7 v3] Remove tracepoint_action ops Wei-cheng Wang
  2015-03-30 16:31 ` [PATCH 3/7 v3] Add testcases for ppc64 tracepoint Wei-cheng Wang
@ 2015-03-30 16:31 ` Wei-cheng Wang
  2015-04-08 17:04   ` Ulrich Weigand
  2015-03-30 16:31 ` [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint Wei-cheng Wang
                   ` (3 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

This patch adds an IPA function, jump_pad_area_hint, for giving a
hint where to map jump pad buffer, becaus

gdb/gdbserver/ChangeLog

2015-03-30  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.
---
 gdb/gdbserver/linux-amd64-ipa.c | 10 ++++++++++
 gdb/gdbserver/linux-i386-ipa.c  | 10 ++++++++++
 gdb/gdbserver/linux-ppc-ipa.c   | 22 ++++++++++++++++++++++
 gdb/gdbserver/tracepoint.c      |  7 +++----
 gdb/gdbserver/tracepoint.h      |  3 +++
 5 files changed, 48 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..b46fb3c 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,26 @@ gdb_agent_get_raw_reg (const unsigned char *raw_regs, int regnum)
 			+ ppc_ft_collect_regmap[regnum] * REGSZ);
 }
 
+/* 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). */
+
+  uintptr_t base = getauxval (AT_PHDR);
+  uintptr_t pagesz = sysconf (_SC_PAGE_SIZE);
+  uintptr_t hint = (base & ~(pagesz - 1)) - 30 * pagesz;
+
+  /* Is 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 3ce9580..39660c8 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -7370,13 +7370,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] 21+ messages in thread

* [PATCH 2/7 v3] Tracepoint for ppc64.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
                   ` (3 preceding siblings ...)
  2015-03-30 16:31 ` [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint Wei-cheng Wang
@ 2015-03-30 16:31 ` Wei-cheng Wang
  2015-04-08 16:57   ` Ulrich Weigand
  2015-03-30 16:31 ` [PATCH 5/7 v3] Replace write_inferior_data_ptr with write_inferior_data_pointer Wei-cheng Wang
  2015-04-08 16:56 ` [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Ulrich Weigand
  6 siblings, 1 reply; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang


Testing summary, on Ubuntu 14.04.1 LTS, gcc 4.9.3 (Advance-Toolchain-at8.0)

# of expected passes            2743
# of unexpected failures        37
# of expected failures          16
# of untested testcases         1
# of unsupported tests          3

Fail cases are:
  27 gdb-collection.sum
   2 gdb-ftrace.sum
   8 gdb-unavailable.sum

I was wrong about entry-values fail cases previously.  I should use {bl\y} for
matching 'bl' instructions instead of simply "bl".  The later pattern will also
match 'blr' instruction.  This is fixed now.

The fail cases in gdb-unavailable are caused by inaccessible vtable for object
For x86, such structures (_ZVTxxx) are put in .rodata section, so gdb can read
them in local file if not collected by tracepoint action, but for PowerpPC,
they are put in .rel.ro sections.  Technically they not read-only, so gdb won't
read them in file if not collected.


gdb/ChangeLog

2015-03-30  Wei-cheng Wang  <cole945@gmail.com>

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

gdb/gdbserver/ChangeLog

2015-03-30  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 (ppc_insert_point, ppc_remove_point, put_i32,
	get_i32, 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_insert_point, ppc_remove_point,
	ppc_supports_tracepoints, ppc_install_fast_tracepoint_jump_pad,
	ppc_emit_ops, ppc_get_min_fast_tracepoint_insn_len,
	ppc_supports_range_stepping.
---
 gdb/gdbserver/Makefile.in     |    9 +
 gdb/gdbserver/configure.srv   |    1 +
 gdb/gdbserver/linux-ppc-ipa.c |  120 ++++
 gdb/gdbserver/linux-ppc-low.c | 1253 ++++++++++++++++++++++++++++++++++++++++-
 gdb/rs6000-tdep.c             |  221 ++++++++
 5 files changed, 1598 insertions(+), 6 deletions(-)
 create mode 100644 gdb/gdbserver/linux-ppc-ipa.c

diff --git a/gdb/gdbserver/Makefile.in b/gdb/gdbserver/Makefile.in
index 9d698c6..e26c188 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 81dd235..c35afc3 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 8a0d5df..fcc6368 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -24,6 +24,8 @@
 #include <asm/ptrace.h>
 
 #include "nat/ppc-linux.h"
+#include "ax.h"
+#include "tracepoint.h"
 
 static unsigned long ppc_hwcap;
 
@@ -533,6 +535,1230 @@ ppc_supports_z_point_type (char z_type)
     }
 }
 
+/* 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;
+    }
+}
+
+/* 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)
+
+/* 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]
+	 rldicl	reg, reg, 0, 32 */
+      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, r9.  */
+
+static int
+gen_atomic_xchg (uint32_t *buf, CORE_ADDR lock, int old_value, int new_value)
+{
+  const int r_lock = 6;
+  const int r_old = 7;
+  const int r_new = 8;
+  const int r_tmp = 9;
+  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_new, new_value);
+  p += gen_limm (p, r_old, old_value);
+
+  *p++ = 0x7c2004ac;			/* lwsync */
+  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
+}
+
+/* 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__
+  const int rsz = 8;
+#else
+  const int rsz = 4;
+#endif
+  /* Minimum frame size is 32 bytes for ELFv2, and 112 bytes for ELFv1.  */
+  const int min_frame = 112;
+  const int frame_size = (((37 * rsz) + min_frame) + 0xf) & ~0xf;
+
+  /* Stack frame layout for this jump pad,
+
+     High	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.  */
+  for (j = 0; j < 32; j++)
+    p += GEN_STORE (p, j, 1, min_frame + j * 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);
+
+  p += gen_atomic_xchg (p, lockaddr, 0, 1);
+  /* Call to collector.  */
+  p += gen_call (p, collector);
+  p += gen_atomic_xchg (p, lockaddr, 1, 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);
+  p += GEN_LOAD (p, 1, 1, min_frame + 1 * rsz);
+
+  /* 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;
+  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 saving TOP during call
+	|  Save r30   for bytecode stack pointer
+	|  Save r29   for incoming CTX
+	|  Save r4    for incoming *value
+ r30 -> +- Bytecode execution stack
+	|
+	|  64-byte (8 doublewords) at initial.  Expand stack as needed.
+	|
+ r31 -> +-
+        |  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 CTX.
+   r4  is the second argument, pointer to the result.
+       We should set *result = TOP after leaving this function.
+   SP+24 is used for saving TOP during call.
+
+ 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
+
+ */
+
+enum { bc_framesz = 208 };
+
+/* Emit prologue in inferior memory.  See above comments.  */
+
+static void
+ppc64_emit_prologue (void)
+{
+  EMIT_ASM ("mflr  0		\n"
+	    "std   0, 16(1)	\n"
+	    "std   31, -8(1)	\n"
+	    "std   30, -16(1)	\n"
+	    "std   29, -24(1)	\n"
+	    "std   4, -32(1)	\n"
+	    "addi  30, 1, -40	\n"
+	    "mr    29, 3	\n"
+	    "li	   3, 0		\n"
+	    "stdu  1, -208(1)	\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, -32(1)	\n"
+	    "std   3, 0(4)	\n"
+	    /* Return 0 for no-erro.  */
+	    "li    3, 0		\n"
+	    "ld    0, 16(1)	\n"
+	    "ld    31, -8(1)	\n"
+	    "ld    30, -16(1)	\n"
+	    "ld    29, -24(1)	\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;
+
+  p += GEN_LD (p, 3, 29, 48);	/* offsetof (fast_tracepoint_ctx, regs) */
+  p += GEN_LI (p, 4, reg);	/* mr	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   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 */
+  p += GEN_MR (p, 31, 3);
+
+  /* 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_MR (p, 3, 31);
+
+  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.  */
 
@@ -708,16 +1934,31 @@ 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, /* supports_z_point_type */
-  NULL,
-  NULL,
-  NULL,
-  NULL,
+  ppc_insert_point,
+  ppc_remove_point,
+  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_prepare_to_resume */
+  NULL, /* linux_process_qsupported */
+  ppc_supports_tracepoints,
+  NULL, /* 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 a125000..68e22b3 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,21 @@ 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)
+{
+  if (isize)
+    *isize = gdbarch_max_insn_length (gdbarch);
+  if (msg)
+    *msg = NULL;
+  return 1;
+}
+
 /* Instruction masks for displaced stepping.  */
 #define BRANCH_MASK 0xfc000000
 #define BP_MASK 0xFC0007FE
@@ -3682,6 +3700,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)
@@ -5335,6 +5355,203 @@ UNKNOWN_OP:
   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 (struct gdbarch *gdbarch,
+			  CORE_ADDR *to, CORE_ADDR oldloc)
+{
+  struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+  enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+  uint32_t insn;
+  int op6, rel, newrel;
+
+  insn = read_memory_unsigned_integer (oldloc, 4, byte_order);
+  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_memory_unsigned_integer (*to, 4, byte_order, insn);
+	  *to += 4;
+
+	  /* Build a unconditional branch and copy LK bit.  */
+	  insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
+	  write_memory_unsigned_integer (*to, 4, byte_order, insn);
+	  *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_memory_unsigned_integer (*to, 4, byte_order, bdnz_insn);
+	  *to += 4;
+	  write_memory_unsigned_integer (*to, 4, byte_order, bf_insn);
+	  *to += 4;
+
+	  /* Build a unconditional branch and copy LK bit.  */
+	  insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
+	  write_memory_unsigned_integer (*to, 4, byte_order, insn);
+	  *to += 4;
+
+	  return;
+	}
+    }
+
+  write_memory_unsigned_integer (*to, 4, byte_order, insn);
+  *to += 4;
+}
+
+/* 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.
@@ -5895,6 +6112,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.  */
@@ -5932,6 +6150,9 @@ rs6000_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
   set_gdbarch_displaced_step_location (gdbarch,
 				       displaced_step_at_entry_point);
 
+  set_gdbarch_relocate_instruction (gdbarch, ppc_relocate_instruction);
+  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.  */
-- 
1.9.1

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

* [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
                   ` (2 preceding siblings ...)
  2015-03-30 16:31 ` [PATCH 4/7 v3] Allow target to decide where to map jump-pad Wei-cheng Wang
@ 2015-03-30 16:31 ` Wei-cheng Wang
  2015-04-08 17:07   ` Ulrich Weigand
  2016-02-22  5:28   ` Marcin Kościelnicki
  2015-03-30 16:31 ` [PATCH 2/7 v3] Tracepoint for ppc64 Wei-cheng Wang
                   ` (2 subsequent siblings)
  6 siblings, 2 replies; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

gdb/ChangeLog

2015-03-30  Wei-cheng Wang  <cole945@gmail.com>

	* rs6000-tdep.c (rs6000_frame_cache, rs6000_frame_this_id): Handle
	unavailable PC/SP to build unavailable frame.
---
 gdb/rs6000-tdep.c | 53 ++++++++++++++++++++++++++++++++++++++++-------------
 1 file changed, 40 insertions(+), 13 deletions(-)

diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index 68e22b3..7436073 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -3152,6 +3152,13 @@ struct rs6000_frame_cache
   CORE_ADDR base;
   CORE_ADDR initial_sp;
   struct trad_frame_saved_reg *saved_regs;
+
+  /* Set BASE_P to true if this frame cache is properly initialized.
+     Otherwise set to false because some registers or memory cannot
+     collected.  */
+  int base_p;
+  /* Cache PC for building unavailable frame.  */
+  CORE_ADDR pc;
 };
 
 static struct rs6000_frame_cache *
@@ -3169,21 +3176,33 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
     return (*this_cache);
   cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache);
   (*this_cache) = cache;
+  cache->pc = 0;
   cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
 
-  func = get_frame_func (this_frame);
-  pc = get_frame_pc (this_frame);
-  skip_prologue (gdbarch, func, pc, &fdata);
-
-  /* Figure out the parent's stack pointer.  */
-
-  /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
-     address of the current frame.  Things might be easier if the
-     ->frame pointed to the outer-most address of the frame.  In
-     the mean time, the address of the prev frame is used as the
-     base address of this frame.  */
-  cache->base = get_frame_register_unsigned
-		(this_frame, gdbarch_sp_regnum (gdbarch));
+  TRY
+    {
+      func = get_frame_func (this_frame);
+      cache->pc = func;
+      pc = get_frame_pc (this_frame);
+      skip_prologue (gdbarch, func, pc, &fdata);
+
+      /* Figure out the parent's stack pointer.  */
+
+      /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
+	 address of the current frame.  Things might be easier if the
+	 ->frame pointed to the outer-most address of the frame.  In
+	 the mean time, the address of the prev frame is used as the
+	 base address of this frame.  */
+      cache->base = get_frame_register_unsigned
+	(this_frame, gdbarch_sp_regnum (gdbarch));
+    }
+  CATCH (ex, RETURN_MASK_ERROR)
+    {
+      if (ex.error != NOT_AVAILABLE_ERROR)
+	throw_exception (ex);
+      return (*this_cache);
+    }
+  END_CATCH
 
   /* If the function appears to be frameless, check a couple of likely
      indicators that we have simply failed to find the frame setup.
@@ -3332,6 +3351,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
     cache->initial_sp
       = get_frame_register_unsigned (this_frame, fdata.alloca_reg);
 
+  cache->base_p = 1;
   return cache;
 }
 
@@ -3341,6 +3361,13 @@ rs6000_frame_this_id (struct frame_info *this_frame, void **this_cache,
 {
   struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
 							this_cache);
+
+  if (!info->base_p)
+    {
+      (*this_id) = frame_id_build_unavailable_stack (info->pc);
+      return;
+    }
+
   /* This marks the outermost frame.  */
   if (info->base == 0)
     return;
-- 
1.9.1

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

* [PATCH 7/7 v3] Remove tracepoint_action ops.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
@ 2015-03-30 16:31 ` Wei-cheng Wang
  2015-04-08 17:09   ` Ulrich Weigand
  2015-03-30 16:31 ` [PATCH 3/7 v3] Add testcases for ppc64 tracepoint Wei-cheng Wang
                   ` (5 subsequent siblings)
  6 siblings, 1 reply; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

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-03-30  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 | 94 ++++++++++++++++++++++------------------------
 1 file changed, 44 insertions(+), 50 deletions(-)

diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index ff66434..31c7fdf 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));
+  int size_in_ipa = (sizeof (struct collect_memory_action));
   CORE_ADDR ipa_action = target_malloc (size_in_ipa);
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			 size_in_ipa);
+  write_inferior_memory (ipa_action, (unsigned char *) action, size_in_ipa);
 
   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));
+  int size_in_ipa = (sizeof (struct collect_registers_action));
   CORE_ADDR ipa_action  = target_malloc (size_in_ipa);
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			size_in_ipa);
+  write_inferior_memory (ipa_action, (unsigned char *) action, size_in_ipa);
 
   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));
+  int size_in_ipa = (sizeof (struct eval_expr_action));
   CORE_ADDR ipa_action = target_malloc (size_in_ipa);
   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, size_in_ipa);
+  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,13 @@ 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));
+  int size_in_ipa = (sizeof (struct collect_static_trace_data_action));
   CORE_ADDR ipa_action = target_malloc (size_in_ipa);
 
-  write_inferior_memory (ipa_action, (unsigned char *) &action->type,
-			 size_in_ipa);
+  write_inferior_memory (ipa_action, (unsigned char *) action, size_in_ipa);
 
   return ipa_action;
 }
@@ -656,11 +626,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 +1942,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 +1967,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 +1982,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 +1998,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 +6040,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 +6090,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] 21+ messages in thread

* [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver.
@ 2015-03-30 16:31 Wei-cheng Wang
  2015-03-30 16:31 ` [PATCH 7/7 v3] Remove tracepoint_action ops Wei-cheng Wang
                   ` (6 more replies)
  0 siblings, 7 replies; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

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

gdb/gdbserver/ChangeLog

2015-03-30  Wei-cheng Wang  <cole945@gmail.com>

	* linux-ppc-low.c (ppc_supports_z_point_type): New function:
	(ppc64_emit_ops_vector): Add target ops - ppc_supports_z_point_type.
---
 gdb/gdbserver/linux-ppc-low.c | 23 ++++++++++++++++++++++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/gdb/gdbserver/linux-ppc-low.c b/gdb/gdbserver/linux-ppc-low.c
index 188fac0..8a0d5df 100644
--- a/gdb/gdbserver/linux-ppc-low.c
+++ b/gdb/gdbserver/linux-ppc-low.c
@@ -512,6 +512,27 @@ 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;
+    }
+}
+
 /* Provide only a fill function for the general register set.  ps_lgetregs
    will use this for NPTL support.  */
 
@@ -690,7 +711,7 @@ struct linux_target_ops the_low_target = {
   NULL,
   0,
   ppc_breakpoint_at,
-  NULL, /* supports_z_point_type */
+  ppc_supports_z_point_type, /* supports_z_point_type */
   NULL,
   NULL,
   NULL,
-- 
1.9.1

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

* [PATCH 5/7 v3] Replace write_inferior_data_ptr with write_inferior_data_pointer.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
                   ` (4 preceding siblings ...)
  2015-03-30 16:31 ` [PATCH 2/7 v3] Tracepoint for ppc64 Wei-cheng Wang
@ 2015-03-30 16:31 ` Wei-cheng Wang
  2015-04-08 17:06   ` Ulrich Weigand
  2015-04-08 16:56 ` [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Ulrich Weigand
  6 siblings, 1 reply; 21+ messages in thread
From: Wei-cheng Wang @ 2015-03-30 16:31 UTC (permalink / raw)
  To: uweigand, gdb-patches; +Cc: Wei-cheng Wang

gdb/gdbserver/ChangeLog

2015-03-30  Wei-cheng Wang  <cole945@gmail.com>

	* (write_inferior_data_ptr): Delete.
	(x_tracepoint_action_download, cmd_qtstart,
	compile_tracepoint_condition, download_agent_expr,
	download_tracepoint_1, download_tracepoint,
	download_trace_state_variables): Replace write_inferior_data_ptr
	with write_inferior_data_pointer.
---
 gdb/gdbserver/tracepoint.c | 87 ++++++++++++++++++++--------------------------
 1 file changed, 37 insertions(+), 50 deletions(-)

diff --git a/gdb/gdbserver/tracepoint.c b/gdb/gdbserver/tracepoint.c
index 39660c8..ff66434 100644
--- a/gdb/gdbserver/tracepoint.c
+++ b/gdb/gdbserver/tracepoint.c
@@ -455,7 +455,6 @@ write_inferior_uinteger (CORE_ADDR symaddr, unsigned int val)
 }
 
 static CORE_ADDR target_malloc (ULONGEST size);
-static int write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr);
 
 #define COPY_FIELD_TO_BUF(BUF, OBJ, FIELD)	\
   do {							\
@@ -592,9 +591,10 @@ x_tracepoint_action_download (const struct tracepoint_action *action)
   write_inferior_memory (ipa_action, (unsigned char *) &action->type,
 			 size_in_ipa);
   expr = download_agent_expr (((struct eval_expr_action *)action)->expr);
-  write_inferior_data_ptr (ipa_action + offsetof (struct eval_expr_action, expr)
-			   - offsetof (struct tracepoint_action, type),
-			   expr);
+  write_inferior_data_pointer (ipa_action
+			       + offsetof (struct eval_expr_action, expr)
+			       - offsetof (struct tracepoint_action, type),
+			       expr);
 
   return ipa_action;
 }
@@ -3228,7 +3228,7 @@ cmd_qtstart (char *packet)
 
   /* Start out empty.  */
   if (agent_loaded_p ())
-    write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, 0);
+    write_inferior_data_pointer (ipa_sym_addrs.addr_tracepoints, 0);
 
   /* Download and install tracepoints.  */
   for (tpoint = tracepoints; tpoint; tpoint = tpoint->next)
@@ -3324,11 +3324,11 @@ cmd_qtstart (char *packet)
 	  if (tpoint == tracepoints)
 	    /* First object in list, set the head pointer in the
 	       inferior.  */
-	    write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints, tpptr);
+	    write_inferior_data_pointer (ipa_sym_addrs.addr_tracepoints, tpptr);
 	  else
-	    write_inferior_data_ptr (prev_tpptr + offsetof (struct tracepoint,
-							    next),
-				     tpptr);
+	    write_inferior_data_pointer (prev_tpptr
+					 + offsetof (struct tracepoint, next),
+					 tpptr);
 	}
 
       /* Any failure in the inner loop is sufficient cause to give
@@ -5923,16 +5923,6 @@ compile_tracepoint_condition (struct tracepoint *tpoint,
   *jump_entry += 16;
 }
 
-/* We'll need to adjust these when we consider bi-arch setups, and big
-   endian machines.  */
-
-static int
-write_inferior_data_ptr (CORE_ADDR where, CORE_ADDR ptr)
-{
-  return write_inferior_memory (where,
-				(unsigned char *) &ptr, sizeof (void *));
-}
-
 /* The base pointer of the IPA's heap.  This is the only memory the
    IPA is allowed to use.  The IPA should _not_ call the inferior's
    `malloc' during operation.  That'd be slow, and, most importantly,
@@ -5978,8 +5968,8 @@ download_agent_expr (struct agent_expr *expr)
   write_inferior_memory (expr_addr, (unsigned char *) expr, sizeof (*expr));
 
   expr_bytes = target_malloc (expr->length);
-  write_inferior_data_ptr (expr_addr + offsetof (struct agent_expr, bytes),
-			   expr_bytes);
+  write_inferior_data_pointer (expr_addr + offsetof (struct agent_expr, bytes),
+			       expr_bytes);
   write_inferior_memory (expr_bytes, expr->bytes, expr->length);
 
   return expr_addr;
@@ -6037,9 +6027,8 @@ download_tracepoint_1 (struct tracepoint *tpoint)
 			 sizeof (target_tracepoint));
 
   if (tpoint->cond)
-    write_inferior_data_ptr (tpptr + offsetof (struct tracepoint,
-					       cond),
-			     download_agent_expr (tpoint->cond));
+    write_inferior_data_pointer (tpptr + offsetof (struct tracepoint, cond),
+				 download_agent_expr (tpoint->cond));
 
   if (tpoint->numactions)
     {
@@ -6049,9 +6038,9 @@ download_tracepoint_1 (struct tracepoint *tpoint)
       /* The pointers array.  */
       actions_array
 	= target_malloc (sizeof (*tpoint->actions) * tpoint->numactions);
-      write_inferior_data_ptr (tpptr + offsetof (struct tracepoint,
-						 actions),
-			       actions_array);
+      write_inferior_data_pointer (tpptr
+				   + offsetof (struct tracepoint, actions),
+				   actions_array);
 
       /* Now for each pointer, download the action.  */
       for (i = 0; i < tpoint->numactions; i++)
@@ -6060,7 +6049,7 @@ download_tracepoint_1 (struct tracepoint *tpoint)
 	  CORE_ADDR ipa_action = action->ops->download (action);
 
 	  if (ipa_action != 0)
-	    write_inferior_data_ptr
+	    write_inferior_data_pointer
 	      (actions_array + i * sizeof (*tpoint->actions),
 	       ipa_action);
 	}
@@ -6186,19 +6175,19 @@ download_tracepoint (struct tracepoint *tpoint)
 	}
 
       /* tpoint->next = tp_prev->next */
-      write_inferior_data_ptr (tpoint->obj_addr_on_target
-			       + offsetof (struct tracepoint, next),
-			       tp_prev_target_next_addr);
+      write_inferior_data_pointer (tpoint->obj_addr_on_target
+				   + offsetof (struct tracepoint, next),
+				   tp_prev_target_next_addr);
       /* tp_prev->next = tpoint */
-      write_inferior_data_ptr (tp_prev->obj_addr_on_target
-			       + offsetof (struct tracepoint, next),
-			       tpoint->obj_addr_on_target);
+      write_inferior_data_pointer (tp_prev->obj_addr_on_target
+				   + offsetof (struct tracepoint, next),
+				   tpoint->obj_addr_on_target);
     }
   else
     /* First object in list, set the head pointer in the
        inferior.  */
-    write_inferior_data_ptr (ipa_sym_addrs.addr_tracepoints,
-			     tpoint->obj_addr_on_target);
+    write_inferior_data_pointer (ipa_sym_addrs.addr_tracepoints,
+				 tpoint->obj_addr_on_target);
 
 }
 
@@ -6209,7 +6198,7 @@ download_trace_state_variables (void)
   struct trace_state_variable *tsv;
 
   /* Start out empty.  */
-  write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables, 0);
+  write_inferior_data_pointer (ipa_sym_addrs.addr_trace_state_variables, 0);
 
   for (tsv = trace_state_variables; tsv != NULL; tsv = tsv->next)
     {
@@ -6230,15 +6219,14 @@ download_trace_state_variables (void)
 	  /* First object in list, set the head pointer in the
 	     inferior.  */
 
-	  write_inferior_data_ptr (ipa_sym_addrs.addr_trace_state_variables,
-				   ptr);
+	  write_inferior_data_pointer (ipa_sym_addrs.addr_trace_state_variables,
+				       ptr);
 	}
       else
 	{
-	  write_inferior_data_ptr (prev_ptr
-				   + offsetof (struct trace_state_variable,
-					       next),
-				   ptr);
+	  write_inferior_data_pointer (prev_ptr
+				       + offsetof (struct trace_state_variable,
+						   next), ptr);
 	}
 
       /* Write the whole object.  We'll fix up its pointers in a bit.
@@ -6254,10 +6242,9 @@ download_trace_state_variables (void)
 	  CORE_ADDR name_addr = target_malloc (size);
 	  write_inferior_memory (name_addr,
 				 (unsigned char *) tsv->name, size);
-	  write_inferior_data_ptr (ptr
-				   + offsetof (struct trace_state_variable,
-					       name),
-				   name_addr);
+	  write_inferior_data_pointer (ptr
+				       + offsetof (struct trace_state_variable,
+						   name), name_addr);
 	}
 
       gdb_assert (tsv->getter == NULL);
@@ -6266,9 +6253,9 @@ download_trace_state_variables (void)
   if (prev_ptr != 0)
     {
       /* Fixup the next pointer in the last item in the list.  */
-      write_inferior_data_ptr (prev_ptr
-			       + offsetof (struct trace_state_variable,
-					   next), 0);
+      write_inferior_data_pointer (prev_ptr
+				   + offsetof (struct trace_state_variable,
+					       next), 0);
     }
 }
 
-- 
1.9.1

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

* Re: [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver.
  2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
                   ` (5 preceding siblings ...)
  2015-03-30 16:31 ` [PATCH 5/7 v3] Replace write_inferior_data_ptr with write_inferior_data_pointer Wei-cheng Wang
@ 2015-04-08 16:56 ` Ulrich Weigand
  6 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 16:56 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches

Wei-cheng Wang wrote:

> +/* 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;
> +    }
> +}

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.)

Otherwise looks good.

Thanks,
Ulrich

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

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

* Re: [PATCH 2/7 v3] Tracepoint for ppc64.
  2015-03-30 16:31 ` [PATCH 2/7 v3] Tracepoint for ppc64 Wei-cheng Wang
@ 2015-04-08 16:57   ` Ulrich Weigand
  2015-06-27 17:48     ` Wei-cheng Wang
  0 siblings, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 16:57 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches

Wei-cheng Wang wrote:

> The fail cases in gdb-unavailable are caused by inaccessible vtable for object
> For x86, such structures (_ZVTxxx) are put in .rodata section, so gdb can read
> them in local file if not collected by tracepoint action, but for PowerpPC,
> they are put in .rel.ro sections.  Technically they not read-only, so gdb won't
> read them in file if not collected.

Is this really a difference between Intel and PowerPC, or this is rather
a difference between different binutils levels?  I don't see off-hand
why this should be Power-specific ...  Do you have example assembler
code that shows the difference?

> +/* 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]
> +	 rldicl	reg, reg, 0, 32 */
> +      p += GEN_LIS (p, reg, (imm >> 16) & 0xffff);
> +      p += GEN_ORI (p, reg, reg, imm & 0xffff);

Ah, you just took that RLDICL out completely, that's also not correct.

You don't need the RLDICL if and only if the high bit of imm is zero.
The problem is that LIS will fill all the upper 32 bits of the target
register with copies of the high bit of the lower 32 bits.

(You could in theory also use the LIS/ORI pair to load up negative
values where all the high bits are *supposed* to be set, just like
you did for the LI case.)

> +/* 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__

The more usual check is
#ifdef __powerpc64__

(here and elsewhere)

> +  const int rsz = 8;
> +#else
> +  const int rsz = 4;
> +#endif
> +  /* Minimum frame size is 32 bytes for ELFv2, and 112 bytes for ELFv1.  */
> +  const int min_frame = 112;

Since this is known at compile time anyway, you might as well do
#ifdef __powerpc64__
#if _CALL_ELF == 2
 const int min_frame = 32;
#else
 const int min_frame = 112;
#endif
#else
 const int min_frame = 8;
#endif

> +  /* Adjust stack pointer.  */
> +  p += GEN_STDU (p, 1, 1, -frame_size);		/* stdu   r1,-frame_size(r1) */

OK, this fixes the ABI violation, but now it's valid only for 64-bit.
For 32-bit, you need to use STWU instead.

> +  p += gen_atomic_xchg (p, lockaddr, 0, 1);
> +  /* Call to collector.  */
> +  p += gen_call (p, collector);
> +  p += gen_atomic_xchg (p, lockaddr, 1, 0);

See other email thread about the lockaddr problem.

> +  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);
> +  p += GEN_LOAD (p, 1, 1, min_frame + 1 * rsz);

Ah, this is wrong now: note that above, you first decremented
the stack pointer, and *then* stored the *modified* value to
the stack.  So this final load is now a no-op.

Instead of attempting to restore, I'd simply use
  p += GEN_ADDI (p, 1, 1, frame_size);
*here* to get back to the original stack pointer value.

> +static void
> +ppc64_emit_stack_adjust (int n)
> +{
> +  uint32_t buf[4];
> +  uint32_t *p = buf;
> +
> +  n = n << 3;
> +  if ((n >> 7) != 0)

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


> +      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_memory_unsigned_integer (*to, 4, byte_order, insn);
> +	  *to += 4;
> +
> +	  /* Build a unconditional branch and copy LK bit.  */
> +	  insn = (18 << 26) | (0x3fffffc & newrel) | (insn & 0x3);
> +	  write_memory_unsigned_integer (*to, 4, byte_order, insn);
> +	  *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?

Bye,
Ulrich

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

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

* Re: [PATCH 3/7 v3] Add testcases for ppc64 tracepoint.
  2015-03-30 16:31 ` [PATCH 3/7 v3] Add testcases for ppc64 tracepoint Wei-cheng Wang
@ 2015-04-08 17:02   ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 17:02 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> 2015-03-30  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*-*-*.
> 	(test_ftrace_condition) New function for testing bytecode compilation.

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).

> diff --git a/gdb/testsuite/gdb.trace/actions.c b/gdb/testsuite/gdb.trace/actions.c
> index 4b7b887..d8538e4 100644
> --- a/gdb/testsuite/gdb.trace/actions.c
> +++ b/gdb/testsuite/gdb.trace/actions.c
> @@ -46,6 +46,8 @@ static union GDB_UNION_TEST
>  } gdb_union1_test;
>  
>  void gdb_recursion_test (int, int, int, int,  int,  int,  int);
> +typedef void (*gdb_recursion_test_fp) (int, int, int, int,  int,  int,  int);
> +gdb_recursion_test_fp gdb_recursion_test_ptr = gdb_recursion_test;

This is OK, but really needs a comment explaining why it is needed.

> +#elif (defined __PPC64__ || defined __PPC__)

Use __powerpc64__ and __powerpc__ everywhere.

Otherwise looks good.

Thanks,
Ulrich

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

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

* Re: [PATCH 4/7 v3] Allow target to decide where to map jump-pad.
  2015-03-30 16:31 ` [PATCH 4/7 v3] Allow target to decide where to map jump-pad Wei-cheng Wang
@ 2015-04-08 17:04   ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 17:04 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> 	* 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.

As I mentioned in another mail, we should have a configure check
for the availability of getauxval.  Otherwise looks good.

Thanks,
Ulrich

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

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

* Re: [PATCH 5/7 v3] Replace write_inferior_data_ptr with write_inferior_data_pointer.
  2015-03-30 16:31 ` [PATCH 5/7 v3] Replace write_inferior_data_ptr with write_inferior_data_pointer Wei-cheng Wang
@ 2015-04-08 17:06   ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 17:06 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> 2015-03-30  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* (write_inferior_data_ptr): Delete.
> 	(x_tracepoint_action_download, cmd_qtstart,
> 	compile_tracepoint_condition, download_agent_expr,
> 	download_tracepoint_1, download_tracepoint,
> 	download_trace_state_variables): Replace write_inferior_data_ptr
> 	with write_inferior_data_pointer.

This is OK.  (You may go ahead and check it in now, without waiting for
the other patches.  In fact, it is better to get this in before the main
powerpc patch.)

Thanks,
Ulrich

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

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

* Re: [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint.
  2015-03-30 16:31 ` [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint Wei-cheng Wang
@ 2015-04-08 17:07   ` Ulrich Weigand
  2016-02-22  5:28   ` Marcin Kościelnicki
  1 sibling, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 17:07 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> 2015-03-30  Wei-cheng Wang  <cole945@gmail.com>
> 
> 	* rs6000-tdep.c (rs6000_frame_cache, rs6000_frame_this_id): Handle
> 	unavailable PC/SP to build unavailable frame.

This is OK (and can go in right away).

Thanks,
Ulrich

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

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

* Re: [PATCH 7/7 v3] Remove tracepoint_action ops.
  2015-03-30 16:31 ` [PATCH 7/7 v3] Remove tracepoint_action ops Wei-cheng Wang
@ 2015-04-08 17:09   ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-04-08 17:09 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches, Wei-cheng Wang

Wei-cheng Wang wrote:

> 2015-03-30  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.

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

>  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));
> +  int size_in_ipa = (sizeof (struct collect_registers_action));

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.

Otherwise looks good.

Thanks,
Ulrich

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

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

* Re: [PATCH 2/7 v3] Tracepoint for ppc64.
  2015-04-08 16:57   ` Ulrich Weigand
@ 2015-06-27 17:48     ` Wei-cheng Wang
  2015-07-03 16:42       ` Ulrich Weigand
  0 siblings, 1 reply; 21+ messages in thread
From: Wei-cheng Wang @ 2015-06-27 17:48 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: gdb-patches

Hi,

On Thu, Apr 9, 2015 at 12:57 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> Wei-cheng Wang wrote:
>> The fail cases in gdb-unavailable are caused by inaccessible vtable for object
>> For x86, such structures (_ZVTxxx) are put in .rodata section, so gdb can read
>> them in local file if not collected by tracepoint action, but for PowerpPC,
>> they are put in .rel.ro sections.  Technically they not read-only, so gdb won't
>> read them in file if not collected.
>
> Is this really a difference between Intel and PowerPC, or this is rather
> a difference between different binutils levels?  I don't see off-hand
> why this should be Power-specific ...  Do you have example assembler
> code that shows the difference?

ppc64le:

        .weak   _ZTV7Derived
        .section
.data.rel.ro._ZTV7Derived,"awG",@progbits,_ZTV7Derived,comdat
                        ^^^^^^^^^^^^^              ^^^
        .align 3
        .type   _ZTV7Derived, @object
        .size   _ZTV7Derived, 56
_ZTV7Derived:
        .quad   28
        .quad   16
        .quad   0
        .quad   _ZTI7Derived
        .quad   12
        .quad   -16
        .quad   _ZTI7Derived
        .weak   _ZTT7Derived

x86_64:

        .section        .rodata._ZTV7Derived,"aG",@progbits,_ZTV7Derived,comdat
                        ^^^^^^^^              ^^^
        .align 32
        .type   _ZTV7Derived, @object
        .size   _ZTV7Derived, 56
_ZTV7Derived:
        .quad   28
        .quad   16
        .quad   0
        .quad   _ZTI7Derived
        .quad   12
        .quad   -16
        .quad   _ZTI7Derived
        .weak   _ZTT7Derived


The assembly code can be reproduced by compiling gdb.trace/unavailable.c

In this case, gdb wants to access (vtable for Derived + 32).
Because it's not collected, gdb tries to see if the address is read-only,
so it can access it from files.  See also remote_xfer_live_readonly_partial.

Thanks,
Wei-cheng

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

* Re: [PATCH 2/7 v3] Tracepoint for ppc64.
  2015-06-27 17:48     ` Wei-cheng Wang
@ 2015-07-03 16:42       ` Ulrich Weigand
  0 siblings, 0 replies; 21+ messages in thread
From: Ulrich Weigand @ 2015-07-03 16:42 UTC (permalink / raw)
  To: Wei-cheng Wang; +Cc: gdb-patches

Wei-cheng Wang wrote:
> On Thu, Apr 9, 2015 at 12:57 AM, Ulrich Weigand <uweigand@de.ibm.com> wrote:
> > Wei-cheng Wang wrote:
> >> The fail cases in gdb-unavailable are caused by inaccessible vtable for object
> >> For x86, such structures (_ZVTxxx) are put in .rodata section, so gdb can read
> >> them in local file if not collected by tracepoint action, but for PowerpPC,
> >> they are put in .rel.ro sections.  Technically they not read-only, so gdb won't
> >> read them in file if not collected.
> >
> > Is this really a difference between Intel and PowerPC, or this is rather
> > a difference between different binutils levels?  I don't see off-hand
> > why this should be Power-specific ...  Do you have example assembler
> > code that shows the difference?

Ah, I think I see.  The difference is that on PowerPC, *all* code (even in
the main executable) is built as position-independent.  For PIC code, the
vtable must be relocated and hence reside in a .data.rel.ro section; while
for non-PIC code the vtable can be in .rodata.

So the same problem would probably appear on Intel as well if we build the
testcase as PIC or PIE.

> In this case, gdb wants to access (vtable for Derived + 32).
> Because it's not collected, gdb tries to see if the address is read-only,
> so it can access it from files.  See also remote_xfer_live_readonly_partial.

Hmm.  I guess we could try to add support for using .data.rel.ro sections
from the executable file as well; the contents would have to be relocated
by GDB, but there's already support to do that in other cases ...

Bye,
Ulrich

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

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

* Re: [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint.
  2015-03-30 16:31 ` [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint Wei-cheng Wang
  2015-04-08 17:07   ` Ulrich Weigand
@ 2016-02-22  5:28   ` Marcin Kościelnicki
  2016-02-23 18:58     ` Ulrich Weigand
  1 sibling, 1 reply; 21+ messages in thread
From: Marcin Kościelnicki @ 2016-02-22  5:28 UTC (permalink / raw)
  To: Wei-cheng Wang, uweigand, gdb-patches

Hey, what about this patch?  Seems it got approval before.  I've just 
applied it on top of master and tested - no regressions on ppc, ppc64, 
ppc64le, and indeed fixes gdb.trace tests for all 3 if I enable 
tracepoints.  OK if I push it?

On 30/03/15 18:30, Wei-cheng Wang wrote:
> gdb/ChangeLog
>
> 2015-03-30  Wei-cheng Wang  <cole945@gmail.com>
>
> 	* rs6000-tdep.c (rs6000_frame_cache, rs6000_frame_this_id): Handle
> 	unavailable PC/SP to build unavailable frame.
> ---
>   gdb/rs6000-tdep.c | 53 ++++++++++++++++++++++++++++++++++++++++-------------
>   1 file changed, 40 insertions(+), 13 deletions(-)
>
> diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
> index 68e22b3..7436073 100644
> --- a/gdb/rs6000-tdep.c
> +++ b/gdb/rs6000-tdep.c
> @@ -3152,6 +3152,13 @@ struct rs6000_frame_cache
>     CORE_ADDR base;
>     CORE_ADDR initial_sp;
>     struct trad_frame_saved_reg *saved_regs;
> +
> +  /* Set BASE_P to true if this frame cache is properly initialized.
> +     Otherwise set to false because some registers or memory cannot
> +     collected.  */
> +  int base_p;
> +  /* Cache PC for building unavailable frame.  */
> +  CORE_ADDR pc;
>   };
>
>   static struct rs6000_frame_cache *
> @@ -3169,21 +3176,33 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
>       return (*this_cache);
>     cache = FRAME_OBSTACK_ZALLOC (struct rs6000_frame_cache);
>     (*this_cache) = cache;
> +  cache->pc = 0;
>     cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
>
> -  func = get_frame_func (this_frame);
> -  pc = get_frame_pc (this_frame);
> -  skip_prologue (gdbarch, func, pc, &fdata);
> -
> -  /* Figure out the parent's stack pointer.  */
> -
> -  /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
> -     address of the current frame.  Things might be easier if the
> -     ->frame pointed to the outer-most address of the frame.  In
> -     the mean time, the address of the prev frame is used as the
> -     base address of this frame.  */
> -  cache->base = get_frame_register_unsigned
> -		(this_frame, gdbarch_sp_regnum (gdbarch));
> +  TRY
> +    {
> +      func = get_frame_func (this_frame);
> +      cache->pc = func;
> +      pc = get_frame_pc (this_frame);
> +      skip_prologue (gdbarch, func, pc, &fdata);
> +
> +      /* Figure out the parent's stack pointer.  */
> +
> +      /* NOTE: cagney/2002-04-14: The ->frame points to the inner-most
> +	 address of the current frame.  Things might be easier if the
> +	 ->frame pointed to the outer-most address of the frame.  In
> +	 the mean time, the address of the prev frame is used as the
> +	 base address of this frame.  */
> +      cache->base = get_frame_register_unsigned
> +	(this_frame, gdbarch_sp_regnum (gdbarch));
> +    }
> +  CATCH (ex, RETURN_MASK_ERROR)
> +    {
> +      if (ex.error != NOT_AVAILABLE_ERROR)
> +	throw_exception (ex);
> +      return (*this_cache);
> +    }
> +  END_CATCH
>
>     /* If the function appears to be frameless, check a couple of likely
>        indicators that we have simply failed to find the frame setup.
> @@ -3332,6 +3351,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
>       cache->initial_sp
>         = get_frame_register_unsigned (this_frame, fdata.alloca_reg);
>
> +  cache->base_p = 1;
>     return cache;
>   }
>
> @@ -3341,6 +3361,13 @@ rs6000_frame_this_id (struct frame_info *this_frame, void **this_cache,
>   {
>     struct rs6000_frame_cache *info = rs6000_frame_cache (this_frame,
>   							this_cache);
> +
> +  if (!info->base_p)
> +    {
> +      (*this_id) = frame_id_build_unavailable_stack (info->pc);
> +      return;
> +    }
> +
>     /* This marks the outermost frame.  */
>     if (info->base == 0)
>       return;
>

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

* Re: [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint.
  2016-02-22  5:28   ` Marcin Kościelnicki
@ 2016-02-23 18:58     ` Ulrich Weigand
  2016-02-24  3:18       ` Marcin Kościelnicki
  0 siblings, 1 reply; 21+ messages in thread
From: Ulrich Weigand @ 2016-02-23 18:58 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: Wei-cheng Wang, gdb-patches

> Hey, what about this patch?  Seems it got approval before.  I've just 
> applied it on top of master and tested - no regressions on ppc, ppc64, 
> ppc64le, and indeed fixes gdb.trace tests for all 3 if I enable 
> tracepoints.  OK if I push it?
> 
> On 30/03/15 18:30, Wei-cheng Wang wrote:
> > gdb/ChangeLog
> >
> > 2015-03-30  Wei-cheng Wang  <cole945@gmail.com>
> >
> > 	* rs6000-tdep.c (rs6000_frame_cache, rs6000_frame_this_id): Handle
> > 	unavailable PC/SP to build unavailable frame.

Yes, this is still OK.

Thanks,
Ulrich

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

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

* Re: [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint.
  2016-02-23 18:58     ` Ulrich Weigand
@ 2016-02-24  3:18       ` Marcin Kościelnicki
  2016-02-24 20:44         ` Sergio Durigan Junior
  0 siblings, 1 reply; 21+ messages in thread
From: Marcin Kościelnicki @ 2016-02-24  3:18 UTC (permalink / raw)
  To: Ulrich Weigand; +Cc: Wei-cheng Wang, gdb-patches

On 22/02/16 20:37, Ulrich Weigand wrote:
>> Hey, what about this patch?  Seems it got approval before.  I've just
>> applied it on top of master and tested - no regressions on ppc, ppc64,
>> ppc64le, and indeed fixes gdb.trace tests for all 3 if I enable
>> tracepoints.  OK if I push it?
>>
>> On 30/03/15 18:30, Wei-cheng Wang wrote:
>>> gdb/ChangeLog
>>>
>>> 2015-03-30  Wei-cheng Wang  <cole945@gmail.com>
>>>
>>> 	* rs6000-tdep.c (rs6000_frame_cache, rs6000_frame_this_id): Handle
>>> 	unavailable PC/SP to build unavailable frame.
>
> Yes, this is still OK.
>
> Thanks,
> Ulrich
>

Thanks, pushed.

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

* Re: [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint.
  2016-02-24  3:18       ` Marcin Kościelnicki
@ 2016-02-24 20:44         ` Sergio Durigan Junior
  2016-02-24 21:06           ` [PATCH] [OBV] gdb/rs6000: Fix maybe-uninitialized warning Marcin Kościelnicki
  0 siblings, 1 reply; 21+ messages in thread
From: Sergio Durigan Junior @ 2016-02-24 20:44 UTC (permalink / raw)
  To: Marcin Kościelnicki; +Cc: Ulrich Weigand, Wei-cheng Wang, gdb-patches

On Tuesday, February 23 2016, Marcin Kościelnicki wrote:

> On 22/02/16 20:37, Ulrich Weigand wrote:
>>> Hey, what about this patch?  Seems it got approval before.  I've just
>>> applied it on top of master and tested - no regressions on ppc, ppc64,
>>> ppc64le, and indeed fixes gdb.trace tests for all 3 if I enable
>>> tracepoints.  OK if I push it?
>>>
>>> On 30/03/15 18:30, Wei-cheng Wang wrote:
>>>> gdb/ChangeLog
>>>>
>>>> 2015-03-30  Wei-cheng Wang  <cole945@gmail.com>
>>>>
>>>> 	* rs6000-tdep.c (rs6000_frame_cache, rs6000_frame_this_id): Handle
>>>> 	unavailable PC/SP to build unavailable frame.
>>
>> Yes, this is still OK.
>>
>> Thanks,
>> Ulrich
>>
>
> Thanks, pushed.

This has caused a few build failures:

  <http://gdb-build.sergiodj.net/builders/RHEL-s390x-m64/builds/1330>

-- 
Sergio
GPG key ID: 237A 54B1 0287 28BF 00EF  31F4 D0EB 7628 65FC 5E36
Please send encrypted e-mail if possible
http://sergiodj.net/

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

* [PATCH] [OBV] gdb/rs6000: Fix maybe-uninitialized warning.
  2016-02-24 20:44         ` Sergio Durigan Junior
@ 2016-02-24 21:06           ` Marcin Kościelnicki
  0 siblings, 0 replies; 21+ messages in thread
From: Marcin Kościelnicki @ 2016-02-24 21:06 UTC (permalink / raw)
  To: sergiodj; +Cc: uweigand, cole945, gdb-patches, Marcin Kościelnicki

Introduced by 657f9cde9d531c9929bef9e02a8064101d568f50.

gdb/ChangeLog:

	* rs6000-tdep.c (rs6000_frame_cache): Initialize frame and pc to 0
	to avoid spurious warnings.
---
Thanks for the report.  I can't reproduce the problem locally, but this
patch (pushed as obvious) should do the trick.

 gdb/ChangeLog     | 5 +++++
 gdb/rs6000-tdep.c | 2 +-
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index ea9f3f4..95cabdb 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2016-02-24  Marcin Kościelnicki  <koriakin@0x04.net>
+
+	* rs6000-tdep.c (rs6000_frame_cache): Initialize frame and pc to 0
+	to avoid spurious warnings.
+
 2016-02-24  Gary Benson  <gbenson@redhat.com>
 
 	* exec.c (exec_file_locate_attach): Do not attempt to
diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c
index a56b8b6..d0c56d7 100644
--- a/gdb/rs6000-tdep.c
+++ b/gdb/rs6000-tdep.c
@@ -3209,7 +3209,7 @@ rs6000_frame_cache (struct frame_info *this_frame, void **this_cache)
   enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
   struct rs6000_framedata fdata;
   int wordsize = tdep->wordsize;
-  CORE_ADDR func, pc;
+  CORE_ADDR func = 0, pc = 0;
 
   if ((*this_cache) != NULL)
     return (struct rs6000_frame_cache *) (*this_cache);
-- 
2.7.1

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

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

Thread overview: 21+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-30 16:31 [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Wei-cheng Wang
2015-03-30 16:31 ` [PATCH 7/7 v3] Remove tracepoint_action ops Wei-cheng Wang
2015-04-08 17:09   ` Ulrich Weigand
2015-03-30 16:31 ` [PATCH 3/7 v3] Add testcases for ppc64 tracepoint Wei-cheng Wang
2015-04-08 17:02   ` Ulrich Weigand
2015-03-30 16:31 ` [PATCH 4/7 v3] Allow target to decide where to map jump-pad Wei-cheng Wang
2015-04-08 17:04   ` Ulrich Weigand
2015-03-30 16:31 ` [PATCH 6/7 v3] Build unavailable-stack frames for tracepoint Wei-cheng Wang
2015-04-08 17:07   ` Ulrich Weigand
2016-02-22  5:28   ` Marcin Kościelnicki
2016-02-23 18:58     ` Ulrich Weigand
2016-02-24  3:18       ` Marcin Kościelnicki
2016-02-24 20:44         ` Sergio Durigan Junior
2016-02-24 21:06           ` [PATCH] [OBV] gdb/rs6000: Fix maybe-uninitialized warning Marcin Kościelnicki
2015-03-30 16:31 ` [PATCH 2/7 v3] Tracepoint for ppc64 Wei-cheng Wang
2015-04-08 16:57   ` Ulrich Weigand
2015-06-27 17:48     ` Wei-cheng Wang
2015-07-03 16:42       ` Ulrich Weigand
2015-03-30 16:31 ` [PATCH 5/7 v3] Replace write_inferior_data_ptr with write_inferior_data_pointer Wei-cheng Wang
2015-04-08 17:06   ` Ulrich Weigand
2015-04-08 16:56 ` [PATCH 1/7 v3] powerpc: Support z-point type in gdbserver Ulrich Weigand

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).