This is the mail archive of the gdb-patches@sourceware.org mailing list for the GDB project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

Re: [PATCH] breakpoint remove fail handle bug fix


On Thu, 12 Apr 2012 04:16:50 +0200, Hui Zhu wrote:
> But it didn't handle the issue when the target is remote.
[...]
> (gdb) c &
> Continuing.
> (gdb) d
> Delete all breakpoints? (y or n) y
> Cannot execute this command while the target is running.

This is because you did not turn on non-stop mode:
remote.c:
  if (!non_stop && target_can_async_p () && rs->waiting_for_stop_reply)
    error (_("Cannot execute this command while the target is running."));

It works then, gdbserver has this bug already fixed.

Just I find it a loss of time fixing linux-nat which should get obsoleted by
gdbserver anyway so posting this patch+testcase just FYI.


Regards,
Jan


diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
index ac1a0ea..299b3ca 100644
--- a/gdb/linux-nat.c
+++ b/gdb/linux-nat.c
@@ -4494,9 +4494,9 @@ linux_nat_make_corefile_notes (bfd *obfd, int *note_size)
 }
 
 /* Implement the to_xfer_partial interface for memory reads using the /proc
-   filesystem.  Because we can use a single read() call for /proc, this
-   can be much more efficient than banging away at PTRACE_PEEKTEXT,
-   but it doesn't support writes.  */
+   filesystem.  Because we can use a single read or write call for /proc, this
+   can be much more efficient than banging away at PTRACE_PEEKTEXT or
+   PTRACE_POKETEXT.  */
 
 static LONGEST
 linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
@@ -4508,29 +4508,35 @@ linux_proc_xfer_partial (struct target_ops *ops, enum target_object object,
   int fd;
   char filename[64];
 
-  if (object != TARGET_OBJECT_MEMORY || !readbuf)
-    return 0;
-
-  /* Don't bother for one word.  */
-  if (len < 3 * sizeof (long))
+  if (object != TARGET_OBJECT_MEMORY)
     return 0;
 
   /* We could keep this file open and cache it - possibly one per
      thread.  That requires some juggling, but is even faster.  */
   sprintf (filename, "/proc/%d/mem", PIDGET (inferior_ptid));
-  fd = open (filename, O_RDONLY | O_LARGEFILE);
+  fd = open (filename, (readbuf ? O_RDONLY : O_WRONLY) | O_LARGEFILE);
   if (fd == -1)
     return 0;
 
-  /* If pread64 is available, use it.  It's faster if the kernel
+  /* If pread64 or pwrite64 is available, use it.  It's faster if the kernel
      supports it (only one syscall), and it's 64-bit safe even on
      32-bit platforms (for instance, SPARC debugging a SPARC64
      application).  */
+  if ((readbuf != NULL
+#ifdef HAVE_PREAD64
+       && (pread64 (fd, readbuf, len, offset) != len)
+#else
+       && (lseek (fd, offset, SEEK_SET) == -1 || read (fd, readbuf, len) != len)
+#endif
+       )
+      || (writebuf != NULL
 #ifdef HAVE_PREAD64
-  if (pread64 (fd, readbuf, len, offset) != len)
+	  && (pwrite64 (fd, writebuf, len, offset) != len)
 #else
-  if (lseek (fd, offset, SEEK_SET) == -1 || read (fd, readbuf, len) != len)
+	  && (lseek (fd, offset, SEEK_SET) == -1
+	      || write (fd, writebuf, len) != len)
 #endif
+          ))
     ret = 0;
   else
     ret = len;
@@ -4759,13 +4765,24 @@ linux_xfer_partial (struct target_ops *ops, enum target_object object,
 	offset &= ((ULONGEST) 1 << addr_bit) - 1;
     }
 
-  xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
-				  offset, len);
+  /* Use more expensive linux_proc_xfer_partial only for larger transfers.  */
+  if (len >= 3 * sizeof (long))
+    {
+      xfer = linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
+				      offset, len);
+      if (xfer != 0)
+	return xfer;
+    }
+
+  xfer = super_xfer_partial (ops, object, annex, readbuf, writebuf,
+			     offset, len);
   if (xfer != 0)
     return xfer;
 
-  return super_xfer_partial (ops, object, annex, readbuf, writebuf,
-			     offset, len);
+  /* PTRACE_* of super_xfer_partial may not work if the inferior is running.
+     linux_proc_xfer_partial still may work in such case.  */
+  return linux_proc_xfer_partial (ops, object, annex, readbuf, writebuf,
+				  offset, len);
 }
 
 static void
diff --git a/gdb/testsuite/gdb.base/async-breakpoint.c b/gdb/testsuite/gdb.base/async-breakpoint.c
new file mode 100644
index 0000000..3cdb0c1
--- /dev/null
+++ b/gdb/testsuite/gdb.base/async-breakpoint.c
@@ -0,0 +1,37 @@
+/* This testcase is part of GDB, the GNU debugger.
+
+   Copyright 2012 Free Software Foundation, Inc.
+
+   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/>.  */
+
+static volatile v;
+
+static int
+func (void)
+{
+  return ++v;
+}
+
+static volatile int stopme;
+
+int
+main (void)
+{
+  int timeout = 60 * 10;
+
+  while (!stopme && timeout-- > 0)
+    usleep (1000000 / 10);
+
+  return func ();
+}
diff --git a/gdb/testsuite/gdb.base/async-breakpoint.exp b/gdb/testsuite/gdb.base/async-breakpoint.exp
new file mode 100644
index 0000000..d2469cf
--- /dev/null
+++ b/gdb/testsuite/gdb.base/async-breakpoint.exp
@@ -0,0 +1,59 @@
+# Copyright (C) 2012 Free Software Foundation, Inc.
+#
+# 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/>.
+
+set testfile async-breakpoint
+
+# Required for non-stop.
+if ![support_displaced_stepping] { 
+    unsupported "displaced stepping"
+    return -1
+}
+
+if { [prepare_for_testing ${testfile}.exp ${testfile}] } {
+    return -1
+}
+
+gdb_test_no_output "set target-async on"
+
+# Required for remote targets due to:
+# Cannot execute this command while the target is running.
+# Required also for local mode as GDB does not insert breakpoints otherwise.
+gdb_test_no_output "set non-stop on"
+
+if ![runto_main] then {
+   return 0
+}
+
+delete_breakpoints
+
+gdb_breakpoint "main"
+
+gdb_test "continue &" {Continuing\.}
+
+# FAIL was: warning: Error removing breakpoint 1
+gdb_test_no_output {delete $bpnum}
+
+# FAIL was: Cannot access memory at address 0x40057c
+gdb_breakpoint "func"
+
+set test "set variable stopme=1"
+gdb_test_multiple $test $test {
+    -re "$gdb_prompt " {
+	exp_continue
+    }
+    -re "Breakpoint \[0-9\]+, func \\(\\) at " {
+	pass $test
+    }
+}
diff --git a/gdb/testsuite/lib/gdbserver-support.exp b/gdb/testsuite/lib/gdbserver-support.exp
index ee66e48..557e86d 100644
--- a/gdb/testsuite/lib/gdbserver-support.exp
+++ b/gdb/testsuite/lib/gdbserver-support.exp
@@ -47,6 +47,9 @@
 proc gdb_target_cmd { targetname serialport } {
     global gdb_prompt
 
+    # Do not use ending anchor for "$gdb_prompt $" as in async mode we may get
+    # also notification of the stopped target.
+
     set serialport_re [string_to_regexp $serialport]
     for {set i 1} {$i <= 3} {incr i} {
 	send_gdb "target $targetname $serialport\n"
@@ -58,26 +61,26 @@ proc gdb_target_cmd { targetname serialport } {
 	    -re "unknown host.*$gdb_prompt" {
 	        verbose "Couldn't look up $serialport"
 	    }
-	    -re "Couldn't establish connection to remote.*$gdb_prompt $" {
+	    -re "Couldn't establish connection to remote.*$gdb_prompt " {
 		verbose "Connection failed"
 	    }
 	    -re "Remote MIPS debugging.*$gdb_prompt" {
 		verbose "Set target to $targetname"
 		return 0
 	    }
-	    -re "Remote debugging using .*$serialport_re.*$gdb_prompt $" {
+	    -re "Remote debugging using .*$serialport_re.*$gdb_prompt " {
 		verbose "Set target to $targetname"
 		return 0
 	    }
-	    -re "Remote debugging using stdio.*$gdb_prompt $" {
+	    -re "Remote debugging using stdio.*$gdb_prompt " {
 		verbose "Set target to $targetname"
 		return 0
 	    }
-	    -re "Remote target $targetname connected to.*$gdb_prompt $" {
+	    -re "Remote target $targetname connected to.*$gdb_prompt " {
 		verbose "Set target to $targetname"
 		return 0
 	    }
-	    -re "Connected to.*$gdb_prompt $" { 
+	    -re "Connected to.*$gdb_prompt " { 
 		verbose "Set target to $targetname"
 		return 0
 	    }


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]