2012-03-08 Yao Qi <yao@codesourcery.com>
authorYao Qi <yao@codesourcery.com>
Fri, 9 Mar 2012 03:47:15 +0000 (03:47 +0000)
committerYao Qi <yao@codesourcery.com>
Fri, 9 Mar 2012 03:47:15 +0000 (03:47 +0000)
    Pedro Alves  <palves@redhat.com>

Fix PR server/13392.
* linux-x86-low.c (amd64_install_fast_tracepoint_jump_pad): Check
offset of JMP insn.
* tracepoint.c (remove_tracepoint): New.
(cmd_qtdp): Call remove_tracepoint when failed to install.

2012-03-08  Yao Qi  <yao@codesourcery.com>
    Pedro Alves  <palves@redhat.com>

Fix PR server/13392.
* gdb.trace/change-loc.exp (tracepoint_change_loc_1): Remove kfail.
(tracepoint_change_loc_2): Remove kfail.  Return if failed to
download tracepoints.
* gdb.trace/pending.exp (pending_tracepoint_works): Likewise.
(pending_tracepoint_resolved_during_trace): Likewise.
(pending_tracepoint_installed_during_trace): Likewise.
(pending_tracepoint_with_action_resolved): Likewise.

gdb/gdbserver/ChangeLog
gdb/gdbserver/linux-x86-low.c
gdb/gdbserver/tracepoint.c
gdb/testsuite/ChangeLog
gdb/testsuite/gdb.trace/change-loc.exp
gdb/testsuite/gdb.trace/pending.exp

index 521866d7db4c0b50fed5ca634f29bf61832b8c5d..04c0709b2fe63062584bae7d55d88dd50dab808b 100644 (file)
@@ -1,3 +1,12 @@
+2012-03-08  Yao Qi  <yao@codesourcery.com>
+           Pedro Alves  <palves@redhat.com>
+
+       Fix PR server/13392.
+       * linux-x86-low.c (amd64_install_fast_tracepoint_jump_pad): Check
+       offset of JMP insn.
+       * tracepoint.c (remove_tracepoint): New.
+       (cmd_qtdp): Call remove_tracepoint when failed to install.
+
 2012-03-07  Pedro Alves  <palves@redhat.com>
 
        * linux-low.c (get_detach_signal): New.
index 58aaf9ad74b7c31b69216368524e18f441419edd..ed1f8a8bcf52ef9630df6f4c08bade2c533fb21b 100644 (file)
@@ -20,6 +20,7 @@
 #include <stddef.h>
 #include <signal.h>
 #include <limits.h>
+#include <inttypes.h>
 #include "server.h"
 #include "linux-low.h"
 #include "i387-fp.h"
@@ -1200,6 +1201,8 @@ amd64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
 {
   unsigned char buf[40];
   int i, offset;
+  int64_t loffset;
+
   CORE_ADDR buildaddr = *jump_entry;
 
   /* Build the jump pad.  */
@@ -1323,7 +1326,17 @@ amd64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
   *adjusted_insn_addr_end = buildaddr;
 
   /* Finally, write a jump back to the program.  */
-  offset = (tpaddr + orig_size) - (buildaddr + sizeof (jump_insn));
+
+  loffset = (tpaddr + orig_size) - (buildaddr + sizeof (jump_insn));
+  if (loffset > INT_MAX || loffset < INT_MIN)
+    {
+      sprintf (err,
+              "E.Jump back from jump pad too far from tracepoint "
+              "(offset 0x%" PRIx64 " > int32).", loffset);
+      return 1;
+    }
+
+  offset = (int) loffset;
   memcpy (buf, jump_insn, sizeof (jump_insn));
   memcpy (buf + 1, &offset, 4);
   append_insns (&buildaddr, sizeof (jump_insn), buf);
@@ -1332,7 +1345,17 @@ amd64_install_fast_tracepoint_jump_pad (CORE_ADDR tpoint, CORE_ADDR tpaddr,
      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 = *jump_entry - (tpaddr + sizeof (jump_insn));
+  loffset = *jump_entry - (tpaddr + sizeof (jump_insn));
+  if (loffset > INT_MAX || loffset < INT_MIN)
+    {
+      sprintf (err,
+              "E.Jump pad too far from tracepoint "
+              "(offset 0x%" PRIx64 " > int32).", loffset);
+      return 1;
+    }
+
+  offset = (int) loffset;
+
   memcpy (buf, jump_insn, sizeof (jump_insn));
   memcpy (buf + 1, &offset, 4);
   memcpy (jjump_pad_insn, buf, sizeof (jump_insn));
index 21e58ffc543ab05532e134d0b81247abef122bbb..7bf576b1ee5f65c06bf903e6af0f16e9b7121cb6 100644 (file)
@@ -1684,6 +1684,28 @@ find_tracepoint (int id, CORE_ADDR addr)
   return NULL;
 }
 
+/* Remove TPOINT from global list.  */
+
+static void
+remove_tracepoint (struct tracepoint *tpoint)
+{
+  struct tracepoint *tp, *tp_prev;
+
+  for (tp = tracepoints, tp_prev = NULL; tp && tp != tpoint;
+       tp_prev = tp, tp = tp->next)
+    ;
+
+  if (tp)
+    {
+      if (tp_prev)
+       tp_prev->next = tp->next;
+      else
+       tracepoints = tp->next;
+
+      xfree (tp);
+    }
+}
+
 /* There may be several tracepoints with the same number (because they
    are "locations", in GDB parlance); return the next one after the
    given tracepoint, or search from the beginning of the list if the
@@ -2391,6 +2413,8 @@ cmd_qtdp (char *own_buf)
 
       download_tracepoint (tpoint);
       install_tracepoint (tpoint, own_buf);
+      if (strcmp (own_buf, "OK") != 0)
+       remove_tracepoint (tpoint);
 
       unpause_all (1);
       return;
index 4c287d826728fa3abccc55dc094c6abee75dd15e..fa2363e96b483301f7a22d7f144f42c119f9da8c 100644 (file)
@@ -1,3 +1,15 @@
+2012-03-08  Yao Qi  <yao@codesourcery.com>
+           Pedro Alves  <palves@redhat.com>
+
+       Fix PR server/13392.
+       * gdb.trace/change-loc.exp (tracepoint_change_loc_1): Remove kfail.
+       (tracepoint_change_loc_2): Remove kfail.  Return if failed to
+       download tracepoints.
+       * gdb.trace/pending.exp (pending_tracepoint_works): Likewise.
+       (pending_tracepoint_resolved_during_trace): Likewise.
+       (pending_tracepoint_installed_during_trace): Likewise.
+       (pending_tracepoint_with_action_resolved): Likewise.
+
 2012-03-08  Keith Seitz  <keiths@redhat.com>
 
        * gdb.ada/array_bounds.exp: Get breakpoint for line
index d6062fc75a98110002679ce4dbc27dc6da9bd5cc..a5a982f77b00a2b2d3f073d693d3c2c265787222 100644 (file)
@@ -98,7 +98,21 @@ proc tracepoint_change_loc_1 { trace_type } { with_test_prefix "1 $trace_type" {
     gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \
        "continue to marker 1"
     # Set a tracepoint during tracing.
-    gdb_test "${trace_type} set_tracepoint" ".*" "set tracepoint on set_tracepoint"
+    set test "set tracepoint on set_tracepoint"
+    gdb_test_multiple "${trace_type} set_tracepoint" $test {
+       -re "Target returns error code .* too far .*$gdb_prompt $" {
+           if [string equal $trace_type "ftrace"] {
+               # The target was unable to install the fast tracepoint
+               # (e.g., jump pad too far from tracepoint).
+               pass "$test (too far)"
+           } else {
+               fail $test
+           }
+       }
+       -re "\r\n$gdb_prompt $" {
+           pass $test
+       }
+    }
 
     gdb_trace_setactions "set action for tracepoint" "" \
        "collect \$$pcreg" "^$"
@@ -109,15 +123,27 @@ proc tracepoint_change_loc_1 { trace_type } { with_test_prefix "1 $trace_type" {
 \[0-9\]+\[\t \]+\(|fast \)tracepoint\[ \]+keep y.*\<MULTIPLE\>.*4\.1.* in func4.*4\.2.* in func4.*" \
        "tracepoint with two locations"
 
-    gdb_test_multiple "continue" "continue to marker 2" {
-       -re ".*Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
-           pass "continue to marker 2"
-       }
-       -re ".*$gdb_prompt $" {
-           kfail "gdb/13392" "continue to marker 2"
-           return
-       }
+    set test "continue to marker 2"
+    gdb_test_multiple "continue" $test {
+       -re "Target returns error code .* too far .*$gdb_prompt $" {
+            if [string equal $trace_type "ftrace"] {
+               # Expected if the target was unable to install the
+               # fast tracepoint (e.g., jump pad too far from
+               # tracepoint).
+               pass "$test (too far)"
+               # Skip the rest of the tests.
+                return
+            } else {
+               fail "continue to marker 2"
+               fail $test
+            }
+
+       }
+       -re ".*Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
+           pass "continue to marker 2"
+       }
     }
+
     # tracepoint has three locations after shlib change-loc-2 is loaded.
     gdb_test "info trace" \
        "Num     Type\[ \]+Disp Enb Address\[ \]+What.*
@@ -198,18 +224,27 @@ proc tracepoint_change_loc_2 { trace_type } { with_test_prefix "2 $trace_type" {
        "breakpoint on marker"
 
     # tracepoint with two locations will be downloaded and installed.
-    gdb_test_no_output "tstart"
-
-    gdb_test_multiple "continue" "continue to marker 1" {
-       -re ".*Breakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
-           pass "continue to marker 1"
-       }
-       -re ".*$gdb_prompt $" {
-           kfail "gdb/13392" "continue to marker 1"
-           return
+    set test "tstart"
+    gdb_test_multiple "tstart" $test {
+        -re "^tstart\r\n$gdb_prompt $" {
+           pass "tstart"
+        }
+       -re "Target returns error code .* too far .*$gdb_prompt $" {
+            if [string equal $trace_type "ftrace"] {
+               # The target was unable to install the fast tracepoint
+               # (e.g., jump pad too far from tracepoint).
+               pass "$test (too far)"
+               # Skip the rest of the tests.
+               return
+            } else {
+               fail $test
+            }
        }
     }
 
+    gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \
+       "continue to marker 1"
+
     gdb_test "continue" ".*Breakpoint.*marker.*at.*$srcfile.*" \
        "continue to marker 2"
 
index 017aea91ad892f1ad30937b8a714a1e90e7fdcc1..4e7dc31a6d46e19a52e6939d64620c3abc63aa3b 100644 (file)
@@ -132,18 +132,28 @@ proc pending_tracepoint_works { trace_type } { with_test_prefix "$trace_type wor
     gdb_test "break marker" "Breakpoint.*at.* file .*$srcfile, line.*" \
        "breakpoint on marker"
 
-    gdb_test_no_output "tstart" "start trace experiment"
-
-    gdb_test_multiple "continue" "continue to marker" {
-       -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
-           pass "continue to marker"
+    set test "start trace experiment"
+    gdb_test_multiple "tstart" $test {
+       -re "^tstart\r\n$gdb_prompt $" {
+           pass $test
        }
-       -re ".*$gdb_prompt $" {
-           kfail "gdb/13392" "continue to marker"
-           return
+       -re "Target returns error code .* too far .*$gdb_prompt $" {
+           if [string equal $trace_type "ftrace"] {
+               # The target was unable to install the fast tracepoint
+               # (e.g., jump pad too far from tracepoint).
+               pass "$test (too far)"
+               # Skip the rest of the tests.
+               return
+           } else {
+               fail $test
+           }
        }
+
     }
 
+    gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*" \
+       "continue to marker"
+
     gdb_test "tstop" "\[\r\n\]+" "stop trace experiment"
 
     gdb_test "tfind start" "#0 .*" "tfind test frame 0"
@@ -189,13 +199,22 @@ proc pending_tracepoint_resolved_during_trace { trace_type } \
     gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \
        "continue to marker 1"
 
-    gdb_test_multiple "continue" "continue to marker 2" {
-       -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
-           pass "continue to marker 2"
+    set test "continue to marker 2"
+    gdb_test_multiple "continue" $test {
+       -re "Target returns error code .* too far .*$gdb_prompt $" {
+           if [string equal $trace_type "ftrace"] {
+               # Expected if the target was unable to install the
+               # fast tracepoint (e.g., jump pad too far from
+               # tracepoint).
+               pass "$test (too far)"
+               # Skip the rest of the tests.
+               return
+           } else {
+               fail $test
+           }
        }
-       -re ".*$gdb_prompt $" {
-           kfail "gdb/13392" "continue to marker 2"
-           return
+       -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
+           pass $test
        }
     }
 
@@ -253,14 +272,23 @@ proc pending_tracepoint_installed_during_trace { trace_type } \
 \[0-9\]+\[\t \]+\(fast |\)tracepoint\[ \t\]+keep y.*PENDING.*set_point2.*" \
        "single pending tracepoint on set_point2"
 
-    gdb_test_multiple "continue" "continue to marker 2" {
-       -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
-           pass "continue to marker 2"
-       }
-       -re ".*$gdb_prompt $" {
-           kfail "gdb/13392" "continue to marker 2"
-           return
+    set test "continue to marker 2"
+    gdb_test_multiple "continue" $test {
+       -re "Target returns error code .* too far .*$gdb_prompt $" {
+           if [string equal $trace_type "ftrace"] {
+               # Expected if the target was unable to install the
+               # fast tracepoint (e.g., jump pad too far from
+               # tracepoint).
+               pass "$test (too far)"
+               # Skip the rest of the tests.
+               return
+           } else {
+               fail $test
+           }
        }
+       -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
+           pass $test
+       }
     }
 
     gdb_test "tstop" "\[\r\n\]+" "stop trace experiment"
@@ -423,14 +451,24 @@ proc pending_tracepoint_with_action_resolved { trace_type } \
     gdb_test "continue" "Continuing.\r\n\r\nBreakpoint.*marker.*at.*pending.c.*" \
        "continue to marker 1"
 
-    gdb_test_multiple "continue" "continue to marker 2" {
+    set test "continue to marker 2"
+    gdb_test_multiple "continue" $test {
+           -re "Target returns error code .* too far .*$gdb_prompt $" {
+            if [string equal $trace_type "ftrace"] {
+               # Expected if the target was unable to install the
+               # fast tracepoint (e.g., jump pad too far from
+               # tracepoint).
+               pass "$test (too far)"
+               # Skip the rest of the tests.
+               return
+            } else {
+               fail $test
+            }
+       }
        -re "Continuing.\r\n\r\nBreakpoint.*marker.*at.*$srcfile.*$gdb_prompt $" {
            pass "continue to marker 2"
        }
-       -re ".*$gdb_prompt $" {
-           kfail "gdb/13392" "continue to marker 2"
-           return
-       }
+
     }
 
     gdb_test "tstop" "\[\r\n\]+" "stop trace experiment"