rpms/gdb/devel gdb-archer.patch,1.24,1.25 gdb.spec,1.376,1.377

Jan Kratochvil jkratoch at fedoraproject.org
Tue Aug 18 19:37:35 UTC 2009


Author: jkratoch

Update of /cvs/pkgs/rpms/gdb/devel
In directory cvs1.fedora.phx.redhat.com:/tmp/cvs-serv6618

Modified Files:
	gdb-archer.patch gdb.spec 
Log Message:
* Tue Aug 18 2009 Jan Kratochvil <jan.kratochvil at redhat.com> - 6.8.50.20090818-3
- archer-jankratochvil-fedora12 commit: 850e3cb38a25cb7fdfa4cef667626ffbde51bcac
- Fix the hardware watchpoints.


gdb-archer.patch:
 Makefile.in                                              |   95 
 NEWS                                                     |    7 
 ada-lang.c                                               |   43 
 amd64-linux-nat.c                                        |   45 
 block.c                                                  |   24 
 block.h                                                  |   12 
 breakpoint.c                                             |  137 -
 breakpoint.h                                             |    3 
 c-exp.y                                                  |  252 +-
 c-lang.c                                                 |    6 
 c-typeprint.c                                            |   47 
 cli/cli-cmds.c                                           |   72 
 coffread.c                                               |    3 
 config.in                                                |    8 
 config/i386/nm-i386.h                                    |  125 +
 config/i386/nm-linux64.h                                 |   54 
 config/mips/nm-irix5.h                                   |   44 
 configure                                                |   79 
 configure.ac                                             |   47 
 cp-name-parser.y                                         |    5 
 cp-namespace.c                                           |  245 +
 cp-support.c                                             |   88 
 cp-support.h                                             |   49 
 dbxread.c                                                |    1 
 doc/gdb.texinfo                                          |  504 ++++
 doc/gdbint.texinfo                                       |   62 
 doc/observer.texi                                        |    5 
 dwarf2-frame.c                                           |   28 
 dwarf2-frame.h                                           |    4 
 dwarf2expr.c                                             |   86 
 dwarf2expr.h                                             |   68 
 dwarf2loc.c                                              |  357 ++
 dwarf2loc.h                                              |    6 
 dwarf2read.c                                             | 1842 ++++++++++-----
 elfread.c                                                |   11 
 eval.c                                                   |  170 +
 expression.h                                             |   11 
 f-exp.y                                                  |    4 
 f-lang.c                                                 |  457 ---
 f-lang.h                                                 |   45 
 f-typeprint.c                                            |   36 
 f-valprint.c                                             |  267 --
 findcmd.c                                                |  111 
 findvar.c                                                |  126 -
 frame.c                                                  |   19 
 frame.h                                                  |    6 
 gdbinit.in                                               |   10 
 gdbserver/linux-i386-low.c                               |  210 +
 gdbserver/linux-x86-64-low.c                             |  184 +
 gdbthread.h                                              |    3 
 gdbtypes.c                                               |  596 ++++
 gdbtypes.h                                               |  146 +
 gnu-v3-abi.c                                             |   18 
 gnulib/Makefile.in                                       |    4 
 i386-linux-nat.c                                         |   47 
 i386-nat.c                                               |   49 
 i386-nat.h                                               |   17 
 infrun.c                                                 |    8 
 jv-lang.c                                                |    1 
 language.h                                               |    1 
 linespec.c                                               |   62 
 linux-nat.c                                              |   88 
 linux-nat.h                                              |    6 
 m2-lang.c                                                |    1 
 machoread.c                                              |    1 
 main.c                                                   |   80 
 maint.c                                                  |    8 
 mdebugread.c                                             |    2 
 mi/mi-cmd-var.c                                          |  165 -
 mi/mi-cmds.c                                             |    2 
 mi/mi-cmds.h                                             |    2 
 mi/mi-main.c                                             |    5 
 mipsread.c                                               |    1 
 objfiles.c                                               |   21 
 objfiles.h                                               |   21 
 parse.c                                                  |  154 +
 parser-defs.h                                            |   25 
 ppc-linux-nat.c                                          |   19 
 printcmd.c                                               |   90 
 python/lib/gdb/FrameIterator.py                          |   33 
 python/lib/gdb/FrameWrapper.py                           |  112 
 python/lib/gdb/__init__.py                               |   19 
 python/lib/gdb/backtrace.py                              |   42 
 python/lib/gdb/command/__init__.py                       |    1 
 python/lib/gdb/command/alias.py                          |   59 
 python/lib/gdb/command/backtrace.py                      |  106 
 python/lib/gdb/command/ignore_errors.py                  |   37 
 python/lib/gdb/command/pahole.py                         |   75 
 python/lib/gdb/command/require.py                        |   57 
 python/lib/gdb/command/save_breakpoints.py               |   65 
 python/lib/gdb/command/upto.py                           |  129 +
 python/lib/gdb/function/__init__.py                      |    1 
 python/lib/gdb/function/caller_is.py                     |   58 
 python/lib/gdb/function/in_scope.py                      |   47 
 python/python-block.c                                    |  265 ++
 python/python-breakpoint.c                               |  665 +++++
 python/python-cmd.c                                      |   17 
 python/python-frame.c                                    |  116 
 python/python-hooks.c                                    |   50 
 python/python-inferior.c                                 |  926 +++++++
 python/python-infthread.c                                |  285 ++
 python/python-internal.h                                 |   69 
 python/python-membuf.c                                   |  268 ++
 python/python-param.c                                    |  606 ++++
 python/python-prettyprint.c                              |   21 
 python/python-symbol.c                                   |  336 ++
 python/python-symtab.c                                   |  322 ++
 python/python-type.c                                     |  170 +
 python/python-utils.c                                    |   46 
 python/python-value.c                                    |   55 
 python/python.c                                          |  384 +++
 python/python.h                                          |    4 
 scm-lang.c                                               |    1 
 scm-valprint.c                                           |    4 
 solib-darwin.c                                           |    1 
 solib-spu.c                                              |    7 
 solib-svr4.c                                             |    4 
 solib.c                                                  |    3 
 solist.h                                                 |    2 
 somread.c                                                |    1 
 spu-tdep.c                                               |    2 
 stabsread.c                                              |    4 
 stack.c                                                  |   38 
 symfile.c                                                |   42 
 symfile.h                                                |   12 
 symmisc.c                                                |    4 
 symtab.c                                                 |  321 +-
 symtab.h                                                 |   20 
 target.c                                                 |   20 
 target.h                                                 |   32 
 testsuite/gdb.arch/powerpc-power7.exp                    |  175 +
 testsuite/gdb.arch/powerpc-power7.s                      |  107 
 testsuite/gdb.arch/x86_64-vla-typedef-foo.S              |  455 +++
 testsuite/gdb.arch/x86_64-vla-typedef.c                  |   43 
 testsuite/gdb.arch/x86_64-vla-typedef.exp                |   64 
 testsuite/gdb.base/arrayidx.c                            |    7 
 testsuite/gdb.base/arrayidx.exp                          |   10 
 testsuite/gdb.base/help.exp                              |    2 
 testsuite/gdb.base/lineno-makeup-func.c                  |   21 
 testsuite/gdb.base/lineno-makeup.c                       |   35 
 testsuite/gdb.base/lineno-makeup.exp                     |   78 
 testsuite/gdb.base/macscp.exp                            |    8 
 testsuite/gdb.base/radix.exp                             |    7 
 testsuite/gdb.base/valgrind-attach.c                     |   28 
 testsuite/gdb.base/valgrind-attach.exp                   |   94 
 testsuite/gdb.base/valgrind-attach.sh                    |   20 
 testsuite/gdb.base/vla-overflow.c                        |   30 
 testsuite/gdb.base/vla-overflow.exp                      |  108 
 testsuite/gdb.base/vla.c                                 |   55 
 testsuite/gdb.base/vla.exp                               |   62 
 testsuite/gdb.base/watchpoint-hw.c                       |    6 
 testsuite/gdb.base/watchpoint-hw.exp                     |   45 
 testsuite/gdb.cp/cp-relocate.exp                         |    6 
 testsuite/gdb.cp/cplusfuncs.cc                           |    6 
 testsuite/gdb.cp/cplusfuncs.exp                          |  195 +
 testsuite/gdb.cp/expand-sals.exp                         |    2 
 testsuite/gdb.cp/member-ptr.cc                           |   17 
 testsuite/gdb.cp/member-ptr.exp                          |   34 
 testsuite/gdb.cp/namespace-multiple-imports.cc           |   20 
 testsuite/gdb.cp/namespace-multiple-imports.exp          |   49 
 testsuite/gdb.cp/namespace-nested-imports.cc             |   36 
 testsuite/gdb.cp/namespace-nested-imports.exp            |   57 
 testsuite/gdb.cp/namespace-no-imports.cc                 |   37 
 testsuite/gdb.cp/namespace-no-imports.exp                |   76 
 testsuite/gdb.cp/namespace-recursive.cc                  |   30 
 testsuite/gdb.cp/namespace-recursive.exp                 |   66 
 testsuite/gdb.cp/namespace-using.cc                      |  128 -
 testsuite/gdb.cp/namespace-using.exp                     |  130 +
 testsuite/gdb.cp/namespace.exp                           |   23 
 testsuite/gdb.cp/overload.exp                            |    8 
 testsuite/gdb.cp/ovldbreak.exp                           |   46 
 testsuite/gdb.cp/shadowing.cc                            |   48 
 testsuite/gdb.cp/shadowing.exp                           |   91 
 testsuite/gdb.dwarf2/callframecfa.S                      |  309 ++
 testsuite/gdb.dwarf2/callframecfa.exp                    |   55 
 testsuite/gdb.dwarf2/dw2-aranges.S                       |  140 +
 testsuite/gdb.dwarf2/dw2-aranges.exp                     |   40 
 testsuite/gdb.dwarf2/dw2-stripped.c                      |   42 
 testsuite/gdb.dwarf2/dw2-stripped.exp                    |   79 
 testsuite/gdb.dwarf2/dw2-struct-member-data-location.S   |   83 
 testsuite/gdb.dwarf2/dw2-struct-member-data-location.exp |   37 
 testsuite/gdb.fortran/common-block.exp                   |  101 
 testsuite/gdb.fortran/common-block.f90                   |   67 
 testsuite/gdb.fortran/dwarf-stride.exp                   |   42 
 testsuite/gdb.fortran/dwarf-stride.f90                   |   40 
 testsuite/gdb.fortran/dynamic.exp                        |  145 +
 testsuite/gdb.fortran/dynamic.f90                        |   98 
 testsuite/gdb.fortran/library-module-lib.f90             |   28 
 testsuite/gdb.fortran/library-module-main.f90            |   23 
 testsuite/gdb.fortran/library-module.exp                 |   53 
 testsuite/gdb.fortran/logical.exp                        |   44 
 testsuite/gdb.fortran/logical.f90                        |   33 
 testsuite/gdb.fortran/module.exp                         |   28 
 testsuite/gdb.fortran/module.f90                         |   37 
 testsuite/gdb.fortran/string.exp                         |   59 
 testsuite/gdb.fortran/string.f90                         |   37 
 testsuite/gdb.gdb/selftest.exp                           |    4 
 testsuite/gdb.mi/gdb701.exp                              |    2 
 testsuite/gdb.mi/mi-var-display.exp                      |    4 
 testsuite/gdb.mi/mi2-var-display.exp                     |    4 
 testsuite/gdb.opt/array-from-register-func.c             |   22 
 testsuite/gdb.opt/array-from-register.c                  |   28 
 testsuite/gdb.opt/array-from-register.exp                |   33 
 testsuite/gdb.python/Makefile.in                         |    2 
 testsuite/gdb.python/python-cmd.exp                      |   27 
 testsuite/gdb.python/python-frame.exp                    |   48 
 testsuite/gdb.python/python-function.exp                 |   27 
 testsuite/gdb.python/python-inferior.c                   |   49 
 testsuite/gdb.python/python-inferior.exp                 |  201 +
 testsuite/gdb.python/python-infthread.c                  |   14 
 testsuite/gdb.python/python-infthread.exp                |   58 
 testsuite/gdb.python/python-mi.exp                       |   96 
 testsuite/gdb.python/python-prettyprint.c                |   13 
 testsuite/gdb.python/python-prettyprint.exp              |   11 
 testsuite/gdb.python/python-prettyprint.py               |   12 
 testsuite/gdb.python/python-template.exp                 |   25 
 testsuite/gdb.python/python-value.exp                    |   68 
 testsuite/gdb.python/python.exp                          |   27 
 testsuite/gdb.threads/watchpoint-fork-forkoff.c          |  175 +
 testsuite/gdb.threads/watchpoint-fork-mt.c               |  157 +
 testsuite/gdb.threads/watchpoint-fork.c                  |   57 
 testsuite/gdb.threads/watchpoint-fork.exp                |  130 +
 testsuite/gdb.threads/watchthreads-reorder.c             |  366 ++
 testsuite/gdb.threads/watchthreads-reorder.exp           |  101 
 testsuite/lib/cp-support.exp                             |    3 
 testsuite/lib/gdb.exp                                    |    1 
 testsuite/lib/mi-support.exp                             |   86 
 testsuite/lib/python-support.exp                         |   53 
 thread.c                                                 |   18 
 top.c                                                    |    1 
 typeprint.c                                              |   14 
 typeprint.h                                              |    3 
 ui-file.c                                                |   20 
 ui-file.h                                                |    6 
 utils.c                                                  |    7 
 valarith.c                                               |   45 
 valops.c                                                 |  254 +-
 valprint.c                                               |    3 
 value.c                                                  |  145 +
 value.h                                                  |    8 
 varobj.c                                                 |  610 +++-
 varobj.h                                                 |   32 
 xcoffread.c                                              |    1 
 243 files changed, 18341 insertions(+), 2642 deletions(-)

Index: gdb-archer.patch
===================================================================
RCS file: /cvs/pkgs/rpms/gdb/devel/gdb-archer.patch,v
retrieving revision 1.24
retrieving revision 1.25
diff -u -p -r1.24 -r1.25
--- gdb-archer.patch	18 Aug 2009 18:51:17 -0000	1.24
+++ gdb-archer.patch	18 Aug 2009 19:37:35 -0000	1.25
@@ -2,7 +2,7 @@ http://sourceware.org/gdb/wiki/ProjectAr
 http://sourceware.org/gdb/wiki/ArcherBranchManagement
 
 GIT snapshot:
-commit 5e0d1cc74f119391a2c3ae25ef5749fc28674f06
+commit 850e3cb38a25cb7fdfa4cef667626ffbde51bcac
 
 branch `archer' - the merge of branches:
 archer-tromey-call-frame-cfa
@@ -290,6 +290,102 @@ index 9b5d2c6..61676a9 100644
    ada_op_name,
    ada_dump_subexp_body,
    ada_evaluate_subexp
+diff --git a/gdb/amd64-linux-nat.c b/gdb/amd64-linux-nat.c
+index 7d8461c..a6d35d7 100644
+--- a/gdb/amd64-linux-nat.c
++++ b/gdb/amd64-linux-nat.c
+@@ -270,6 +270,8 @@ amd64_linux_dr_get (ptid_t ptid, int regnum)
+   return value;
+ }
+ 
++/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
++
+ static void
+ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+ {
+@@ -286,6 +288,8 @@ amd64_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+     perror_with_name (_("Couldn't write debug register"));
+ }
+ 
++/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ amd64_linux_dr_set_control (unsigned long control)
+ {
+@@ -297,6 +301,8 @@ amd64_linux_dr_set_control (unsigned long control)
+     amd64_linux_dr_set (ptid, DR_CONTROL, control);
+ }
+ 
++/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+ {
+@@ -310,18 +316,55 @@ amd64_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+     amd64_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
+ }
+ 
++/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
++
+ static void
+ amd64_linux_dr_reset_addr (int regnum)
+ {
+   amd64_linux_dr_set_addr (regnum, 0);
+ }
+ 
++/* Get DR_STATUS from only the one LWP of INFERIOR_PTID.  */
++
+ static unsigned long
+ amd64_linux_dr_get_status (void)
+ {
+   return amd64_linux_dr_get (inferior_ptid, DR_STATUS);
+ }
+ 
++/* Unset VALUE bits in DR_STATUS in all LWPs of LWP_LIST.  */
++
++static void
++amd64_linux_dr_unset_status (unsigned long mask)
++{
++  struct lwp_info *lp;
++  ptid_t ptid;
++
++  ALL_LWPS (lp, ptid)
++    {
++      unsigned long value;
++      
++      value = amd64_linux_dr_get (ptid, DR_STATUS);
++      value &= ~mask;
++      amd64_linux_dr_set (ptid, DR_STATUS, value);
++    }
++}
++
++/* See i386_dr_low_type.detach.  Do not use wrappers amd64_linux_dr_set_control
++   or amd64_linux_dr_reset_addr as they would modify the register cache
++   (amd64_linux_dr).  */
++
++static void
++amd64_linux_dr_detach (void)
++{
++  int regnum;
++
++  amd64_linux_dr_set (inferior_ptid, DR_CONTROL, 0);
++  amd64_linux_dr_unset_status (~0UL);
++  for (regnum = DR_FIRSTADDR; regnum <= DR_LASTADDR; regnum++)
++    amd64_linux_dr_set (inferior_ptid, regnum, 0);
++}
++
+ static void
+ amd64_linux_new_thread (ptid_t ptid)
+ {
+@@ -672,6 +715,8 @@ _initialize_amd64_linux_nat (void)
+   i386_dr_low.set_addr = amd64_linux_dr_set_addr;
+   i386_dr_low.reset_addr = amd64_linux_dr_reset_addr;
+   i386_dr_low.get_status = amd64_linux_dr_get_status;
++  i386_dr_low.unset_status = amd64_linux_dr_unset_status;
++  i386_dr_low.detach = amd64_linux_dr_detach;
+   i386_set_debug_register_length (8);
+ 
+   /* Override the GNU/Linux inferior startup hook.  */
 diff --git a/gdb/block.c b/gdb/block.c
 index 1889ecd..37fa342 100644
 --- a/gdb/block.c
@@ -368,7 +464,7 @@ index 53e7371..d373f8a 100644
 +
  #endif /* BLOCK_H */
 diff --git a/gdb/breakpoint.c b/gdb/breakpoint.c
-index f3940e1..70222a4 100644
+index f3940e1..2349fbc 100644
 --- a/gdb/breakpoint.c
 +++ b/gdb/breakpoint.c
 @@ -59,6 +59,7 @@
@@ -477,7 +573,97 @@ index f3940e1..70222a4 100644
  	return;
        }
  
-@@ -8843,6 +8856,22 @@ all_tracepoints ()
+@@ -1690,6 +1703,7 @@ detach_breakpoints (int pid)
+     if (b->inserted)
+       val |= remove_breakpoint (b, mark_inserted);
+   }
++  val |= target_detach_watchpoints ();
+   do_cleanups (old_chain);
+   return val;
+ }
+@@ -1782,12 +1796,14 @@ remove_breakpoint (struct bp_location *b, insertion_state_t is)
+ 	return val;
+       b->inserted = (is == mark_inserted);
+     }
+-  else if (b->loc_type == bp_loc_hardware_watchpoint)
++  /* bp_loc_hardware_watchpoint with mark_inserted is being handled by
++     target_detach_watchpoints.  */
++  else if (b->loc_type == bp_loc_hardware_watchpoint && is == mark_uninserted)
+     {
+       struct value *v;
+       struct value *n;
+ 
+-      b->inserted = (is == mark_inserted);
++      b->inserted = 0;
+       val = target_remove_watchpoint (b->address, b->length, 
+ 				      b->watchpoint_type);
+ 
+@@ -2961,8 +2977,12 @@ bpstat_check_location (const struct bp_location *bl, CORE_ADDR bp_addr)
+ 
+ /* If BS refers to a watchpoint, determine if the watched values
+    has actually changed, and we should stop.  If not, set BS->stop
+-   to 0.  */
+-static void
++   to 0.
++   Return 0 for watchpoints which could not be the cause of this trap.
++   In such case PRINT_IT will be print_it_noop and STOP will be 0.
++   Otherwise return 1 but in such case it is not guaranteed whether this
++   breakpoint did or did not trigger this trap.  */
++static int
+ bpstat_check_watchpoint (bpstat bs)
+ {
+   const struct bp_location *bl = bs->breakpoint_at;
+@@ -3051,8 +3071,10 @@ bpstat_check_watchpoint (bpstat bs)
+ 	     anything for this watchpoint.  */
+ 	  bs->print_it = print_it_noop;
+ 	  bs->stop = 0;
++	  return 0;
+ 	}
+     }
++  return 1;
+ }
+ 
+ 
+@@ -3156,6 +3178,8 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
+ 
+   ALL_BP_LOCATIONS (bl)
+   {
++    bpstat bs_prev = bs;
++
+     b = bl->owner;
+     gdb_assert (b);
+     if (!breakpoint_enabled (b) && b->enable_state != bp_permanent)
+@@ -3176,6 +3200,7 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
+     /* Come here if it's a watchpoint, or if the break address matches */
+ 
+     bs = bpstat_alloc (bl, bs);	/* Alloc a bpstat to explain stop */
++    gdb_assert (bs_prev->next == bs);
+ 
+     /* Assume we stop.  Should we find watchpoint that is not actually
+        triggered, or if condition of breakpoint is false, we'll reset
+@@ -3183,9 +3208,18 @@ bpstat_stop_status (CORE_ADDR bp_addr, ptid_t ptid)
+     bs->stop = 1;
+     bs->print = 1;
+ 
+-    bpstat_check_watchpoint (bs);
+-    if (!bs->stop)
+-      continue;
++    if (!bpstat_check_watchpoint (bs))
++      {
++	/* Ensure bpstat_explains_signal stays false if this BL could not be
++	   the cause of this trap.  */
++
++	gdb_assert (bs->print_it == print_it_noop);
++	gdb_assert (!bs->stop);
++	xfree (bs);
++	bs = bs_prev;
++	bs->next = NULL;
++	continue;
++      }
+ 
+     if (b->type == bp_thread_event || b->type == bp_overlay_event
+ 	|| b->type == bp_longjmp_master)
+@@ -8843,6 +8877,22 @@ all_tracepoints ()
    return tp_vec;
  }
  
@@ -500,7 +686,7 @@ index f3940e1..70222a4 100644
  
  /* This help string is used for the break, hbreak, tbreak and thbreak commands.
     It is defined as a macro to prevent duplication.
-@@ -9345,4 +9374,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
+@@ -9345,4 +9395,5 @@ inferior in all-stop mode, gdb behaves as if always-inserted mode is off."),
    automatic_hardware_breakpoints = 1;
  
    observer_attach_about_to_proceed (breakpoint_about_to_proceed);
@@ -10362,6 +10548,274 @@ index 5e55573..5439aba 100644
  # This Makefile.in is free software; the Free Software Foundation
  # gives unlimited permission to copy and/or distribute it,
  # with or without modifications, as long as this notice is preserved.
+diff --git a/gdb/i386-linux-nat.c b/gdb/i386-linux-nat.c
+index 991b27f..411b41b 100644
+--- a/gdb/i386-linux-nat.c
++++ b/gdb/i386-linux-nat.c
+@@ -586,6 +586,8 @@ i386_linux_store_inferior_registers (struct target_ops *ops,
+ 
+ static unsigned long i386_linux_dr[DR_CONTROL + 1];
+ 
++/* Get debug register REGNUM value from only the one LWP of PTID.  */
++
+ static unsigned long
+ i386_linux_dr_get (ptid_t ptid, int regnum)
+ {
+@@ -614,6 +616,8 @@ i386_linux_dr_get (ptid_t ptid, int regnum)
+   return value;
+ }
+ 
++/* Set debug register REGNUM to VALUE in only the one LWP of PTID.  */
++
+ static void
+ i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+ {
+@@ -630,6 +634,8 @@ i386_linux_dr_set (ptid_t ptid, int regnum, unsigned long value)
+     perror_with_name (_("Couldn't write debug register"));
+ }
+ 
++/* Set DR_CONTROL to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ i386_linux_dr_set_control (unsigned long control)
+ {
+@@ -641,6 +647,8 @@ i386_linux_dr_set_control (unsigned long control)
+     i386_linux_dr_set (ptid, DR_CONTROL, control);
+ }
+ 
++/* Set address REGNUM (zero based) to ADDR in all LWPs of LWP_LIST.  */
++
+ static void
+ i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+ {
+@@ -654,18 +662,55 @@ i386_linux_dr_set_addr (int regnum, CORE_ADDR addr)
+     i386_linux_dr_set (ptid, DR_FIRSTADDR + regnum, addr);
+ }
+ 
++/* Set address REGNUM (zero based) to zero in all LWPs of LWP_LIST.  */
++
+ static void
+ i386_linux_dr_reset_addr (int regnum)
+ {
+   i386_linux_dr_set_addr (regnum, 0);
+ }
+ 
++/* Get DR_STATUS from only the one LWP of INFERIOR_PTID.  */
++
+ static unsigned long
+ i386_linux_dr_get_status (void)
+ {
+   return i386_linux_dr_get (inferior_ptid, DR_STATUS);
+ }
+ 
++/* Unset VALUE bits in DR_STATUS in all LWPs of LWP_LIST.  */
++
++static void
++i386_linux_dr_unset_status (unsigned long mask)
++{
++  struct lwp_info *lp;
++  ptid_t ptid;
++
++  ALL_LWPS (lp, ptid)
++    {
++      unsigned long value;
++      
++      value = i386_linux_dr_get (ptid, DR_STATUS);
++      value &= ~mask;
++      i386_linux_dr_set (ptid, DR_STATUS, value);
++    }
++}
++
++/* See i386_dr_low_type.detach.  Do not use wrappers i386_linux_dr_set_control
++   or i386_linux_dr_reset_addr as they would modify the register cache
++   (i386_linux_dr).  */
++
++static void
++i386_linux_dr_detach (void)
++{
++  int regnum;
++
++  i386_linux_dr_set (inferior_ptid, DR_CONTROL, 0);
++  i386_linux_dr_unset_status (~0UL);
++  for (regnum = DR_FIRSTADDR; regnum <= DR_LASTADDR; regnum++)
++    i386_linux_dr_set (inferior_ptid, regnum, 0);
++}
++
+ static void
+ i386_linux_new_thread (ptid_t ptid)
+ {
+@@ -832,6 +877,8 @@ _initialize_i386_linux_nat (void)
+   i386_dr_low.set_addr = i386_linux_dr_set_addr;
+   i386_dr_low.reset_addr = i386_linux_dr_reset_addr;
+   i386_dr_low.get_status = i386_linux_dr_get_status;
++  i386_dr_low.unset_status = i386_linux_dr_unset_status;
++  i386_dr_low.detach = i386_linux_dr_detach;
+   i386_set_debug_register_length (4);
+ 
+   /* Override the default ptrace resume method.  */
+diff --git a/gdb/i386-nat.c b/gdb/i386-nat.c
+index ab1bd8a..ee330b8 100644
+--- a/gdb/i386-nat.c
++++ b/gdb/i386-nat.c
+@@ -137,8 +137,11 @@ struct i386_dr_low_type i386_dr_low;
+ #define I386_DR_GET_RW_LEN(i) \
+   ((dr_control_mirror >> (DR_CONTROL_SHIFT + DR_CONTROL_SIZE * (i))) & 0x0f)
+ 
++/* Mask that this I'th watchpoint has triggered.  */
++#define I386_DR_WATCH_MASK(i)	(1 << (i))
++
+ /* Did the watchpoint whose address is in the I'th register break?  */
+-#define I386_DR_WATCH_HIT(i)	(dr_status_mirror & (1 << (i)))
++#define I386_DR_WATCH_HIT(i)	(dr_status_mirror & I386_DR_WATCH_MASK (i))
+ 
+ /* A macro to loop over all debug registers.  */
+ #define ALL_DEBUG_REGISTERS(i)	for (i = 0; i < DR_NADDR; i++)
+@@ -358,6 +361,10 @@ i386_insert_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
+   i386_dr_low.set_addr (i, addr);
+   i386_dr_low.set_control (dr_control_mirror);
+ 
++  /* Only a sanity check for leftover bits (set possibly only by inferior).  */
++  if (i386_dr_low.unset_status)
++    i386_dr_low.unset_status (I386_DR_WATCH_MASK (i));
++
+   return 0;
+ }
+ 
+@@ -387,6 +394,11 @@ i386_remove_aligned_watchpoint (CORE_ADDR addr, unsigned len_rw_bits)
+ 	      i386_dr_low.set_control (dr_control_mirror);
+ 	      if (i386_dr_low.reset_addr)
+ 		i386_dr_low.reset_addr (i);
++
++	      /* Status must be already queried for each LWP.  Otherwise it will
++	         be lost in all-stop mode + breakpoint always-inserted off.  */
++	      if (i386_dr_low.unset_status)
++		i386_dr_low.unset_status (I386_DR_WATCH_MASK (i));
+ 	    }
+ 	  retval = 0;
+ 	}
+@@ -520,6 +532,17 @@ i386_remove_watchpoint (CORE_ADDR addr, int len, int type)
+   return retval;
+ }
+ 
++/* See target_detach_watchpoints.  */
++
++static int
++i386_detach_watchpoints (void)
++{
++  if (i386_dr_low.detach)
++    i386_dr_low.detach ();
++
++  return 0;
++}
++
+ /* Return non-zero if we can watch a memory region that starts at
+    address ADDR and whose length is LEN bytes.  */
+ 
+@@ -575,28 +598,7 @@ static int
+ i386_stopped_by_watchpoint (void)
+ {
+   CORE_ADDR addr = 0;
+-  return i386_stopped_data_address (&current_target, &addr);
+-}
+-
+-/* Return non-zero if the inferior has some break/watchpoint that
+-   triggered.  */
+-
+-static int
+-i386_stopped_by_hwbp (void)
+-{
+-  int i;
+-
+-  dr_status_mirror = i386_dr_low.get_status ();
+-  if (maint_show_dr)
+-    i386_show_dr ("stopped_by_hwbp", 0, 0, hw_execute);
+-
+-  ALL_DEBUG_REGISTERS(i)
+-    {
+-      if (I386_DR_WATCH_HIT (i))
+-	return 1;
+-    }
+-
+-  return 0;
++  return target_stopped_data_address (&current_target, &addr);
+ }
+ 
+ /* Insert a hardware-assisted breakpoint at BP_TGT->placed_address.
+@@ -690,6 +692,7 @@ i386_use_watchpoints (struct target_ops *t)
+   t->to_stopped_data_address = i386_stopped_data_address;
+   t->to_insert_watchpoint = i386_insert_watchpoint;
+   t->to_remove_watchpoint = i386_remove_watchpoint;
++  t->to_detach_watchpoints = i386_detach_watchpoints;
+   t->to_insert_hw_breakpoint = i386_insert_hw_breakpoint;
+   t->to_remove_hw_breakpoint = i386_remove_hw_breakpoint;
+ }
+diff --git a/gdb/i386-nat.h b/gdb/i386-nat.h
+index f49b9f6..cd31958 100644
+--- a/gdb/i386-nat.h
++++ b/gdb/i386-nat.h
+@@ -49,16 +49,23 @@ extern void i386_use_watchpoints (struct target_ops *);
+    functions are:
+ 
+       set_control              -- set the debug control (DR7)
+-				  register to a given value
++				  register to a given value for all LWPs
+ 
+       set_addr                 -- put an address into one debug
+-				  register
++				  register for all LWPs
+ 
+       reset_addr               -- reset the address stored in
+-				  one debug register
++				  one debug register for all LWPs
+ 
+       get_status               -- return the value of the debug
+-				  status (DR6) register.
++				  status (DR6) register for current LWP
++
++      unset_status             -- unset the specified bits of the debug
++				  status (DR6) register for all LWPs
++
++      detach                   -- clear all debug registers of only the
++				  INFERIOR_PTID task without affecting any
++				  register caches.
+ 
+    Additionally, the native file should set the debug_register_length
+    field to 4 or 8 depending on the number of bytes used for
+@@ -70,6 +77,8 @@ struct i386_dr_low_type
+     void (*set_addr) (int, CORE_ADDR);
+     void (*reset_addr) (int);
+     unsigned long (*get_status) (void);
++    void (*unset_status) (unsigned long);
++    void (*detach) (void);
+     int debug_register_length;
+   };
+ 
+diff --git a/gdb/infrun.c b/gdb/infrun.c
+index e3eddce..8917ac9 100644
+--- a/gdb/infrun.c
++++ b/gdb/infrun.c
+@@ -2630,6 +2630,10 @@ handle_inferior_event (struct execution_control_state *ecs)
+ 
+       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ 
++      /* Clear WATCHPOINT_TRIGGERED values from previous stop which could
++	 confuse bpstat_stop_status and bpstat_explains_signal.  */
++      watchpoints_triggered (&ecs->ws);
++
+       ecs->event_thread->stop_bpstat = bpstat_stop_status (stop_pc, ecs->ptid);
+ 
+       ecs->random_signal = !bpstat_explains_signal (ecs->event_thread->stop_bpstat);
+@@ -2667,6 +2671,10 @@ handle_inferior_event (struct execution_control_state *ecs)
+ 
+       stop_pc = regcache_read_pc (get_thread_regcache (ecs->ptid));
+ 
++      /* Clear WATCHPOINT_TRIGGERED values from previous stop which could
++	 confuse bpstat_stop_status and bpstat_explains_signal.  */
++      watchpoints_triggered (&ecs->ws);
++
+       /* This causes the eventpoints and symbol table to be reset.
+          Must do this now, before trying to determine whether to
+          stop.  */
 diff --git a/gdb/jv-lang.c b/gdb/jv-lang.c
 index 6b68e7d..5095180 100644
 --- a/gdb/jv-lang.c
@@ -10507,6 +10961,158 @@ index 3e943a1..3b8956c 100644
  	    build_canonical_line_spec (values.sals, copy, canonical);
  	}
        return values;
+diff --git a/gdb/linux-nat.c b/gdb/linux-nat.c
+index 1308844..e6fad24 100644
+--- a/gdb/linux-nat.c
++++ b/gdb/linux-nat.c
+@@ -1629,6 +1629,7 @@ resume_callback (struct lwp_info *lp, void *data)
+       lp->stopped = 0;
+       lp->step = 0;
+       memset (&lp->siginfo, 0, sizeof (lp->siginfo));
++      lp->watchpoint_hit_set = 0;
+     }
+   else if (lp->stopped && debug_linux_nat)
+     fprintf_unfiltered (gdb_stdlog, "RC: Not resuming sibling %s (has pending)\n",
+@@ -1766,6 +1767,7 @@ linux_nat_resume (struct target_ops *ops,
+ 
+   linux_ops->to_resume (linux_ops, ptid, step, signo);
+   memset (&lp->siginfo, 0, sizeof (lp->siginfo));
++  lp->watchpoint_hit_set = 0;
+ 
+   if (debug_linux_nat)
+     fprintf_unfiltered (gdb_stdlog,
+@@ -2164,6 +2166,78 @@ maybe_clear_ignore_sigint (struct lwp_info *lp)
+     }
+ }
+ 
++/* Fetch the possible triggered data watchpoint info and store it to LP.
++   The hardware data watchpoint trigger gets cleared during this fetch.  */
++
++static void
++save_sigtrap (struct lwp_info *lp)
++{
++  struct cleanup *old_chain;
++
++  /* linux_nat_stopped_data_address is not even installed in this case.  */
++  if (linux_ops->to_stopped_data_address == NULL)
++    return;
++
++  old_chain = save_inferior_ptid ();
++  inferior_ptid = lp->ptid;
++
++  lp->watchpoint_hit_set =
++    linux_ops->to_stopped_data_address (&current_target, &lp->watchpoint_hit);
++
++  do_cleanups (old_chain);
++}
++
++/* Wrap target_stopped_data_address where the GNU/Linux native target may be
++   directed by the watchpoint/debug register number.  Base the reported value
++   on the triggered data address instead.  During inferior stop the assignment
++   of watchpoint/debug registers may change making the register number specific
++   trigger info stale.  */
++
++static int
++linux_nat_stopped_data_address (struct target_ops *ops, CORE_ADDR *addr_p)
++{
++  struct lwp_info *lp = find_lwp_pid (inferior_ptid);
++
++  gdb_assert (lp != NULL);
++
++  *addr_p = lp->watchpoint_hit;
++
++  return lp->watchpoint_hit_set;
++}
++
++/* In `set follow-fork-mode child' with multithreaded parent we need to detach
++   watchpoints from all the LWPs.  In such case INFERIOR_PTID will be the
++   non-threaded new child while LWP_LIST will still contain all the threads of
++   the parent being detached.  */
++
++static int
++linux_nat_detach_watchpoints (void)
++{
++  struct lwp_info *lp;
++  int found = 0, retval = 0;
++  ptid_t filter = pid_to_ptid (ptid_get_pid (inferior_ptid));
++  struct cleanup *old_chain = save_inferior_ptid ();
++
++  for (lp = lwp_list; lp; lp = lp->next)
++    if (ptid_match (lp->ptid, filter))
++      {
++	inferior_ptid = lp->ptid;
++	retval |= linux_ops->to_detach_watchpoints ();
++	found = 1;
++      }
++
++  do_cleanups (old_chain);
++
++  if (!found)
++    {
++      gdb_assert (!is_lwp (inferior_ptid));
++
++      retval |= linux_ops->to_detach_watchpoints ();
++    }
++
++  return retval;
++}
++
+ /* Wait until LP is stopped.  */
+ 
+ static int
+@@ -2215,6 +2289,8 @@ stop_wait_callback (struct lwp_info *lp, void *data)
+ 	      /* Save the trap's siginfo in case we need it later.  */
+ 	      save_siginfo (lp);
+ 
++	      save_sigtrap (lp);
++
+ 	      /* Now resume this LWP and get the SIGSTOP event. */
+ 	      errno = 0;
+ 	      ptrace (PTRACE_CONT, GET_LWP (lp->ptid), 0, 0);
+@@ -2579,9 +2655,13 @@ linux_nat_filter_event (int lwpid, int status, int options)
+       add_thread (lp->ptid);
+     }
+ 
+-  /* Save the trap's siginfo in case we need it later.  */
+   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP)
+-    save_siginfo (lp);
++    {
++      /* Save the trap's siginfo in case we need it later.  */
++      save_siginfo (lp);
++
++      save_sigtrap (lp);
++    }
+ 
+   /* Handle GNU/Linux's extended waitstatus for trace events.  */
+   if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGTRAP && status >> 16 != 0)
+@@ -4871,6 +4951,10 @@ linux_nat_add_target (struct target_ops *t)
+   t->to_thread_alive = linux_nat_thread_alive;
+   t->to_pid_to_str = linux_nat_pid_to_str;
+   t->to_has_thread_control = tc_schedlock;
++  if (linux_ops->to_stopped_data_address)
++    t->to_stopped_data_address = linux_nat_stopped_data_address;
++  if (linux_ops->to_detach_watchpoints)
++    t->to_detach_watchpoints = linux_nat_detach_watchpoints;
+ 
+   t->to_can_async_p = linux_nat_can_async_p;
+   t->to_is_async_p = linux_nat_is_async_p;
+diff --git a/gdb/linux-nat.h b/gdb/linux-nat.h
+index d1ed6fc..faf68bb 100644
+--- a/gdb/linux-nat.h
++++ b/gdb/linux-nat.h
+@@ -62,6 +62,12 @@ struct lwp_info
+      be the address of a hardware watchpoint.  */
+   struct siginfo siginfo;
+ 
++  /* WATCHPOINT_HIT_SET is non-zero if this LWP stopped with a trap and a data
++     watchpoint has been found as triggered.  In such case WATCHPOINT_HIT
++     contains data address of the triggered data watchpoint.  */
++  unsigned watchpoint_hit_set : 1;
++  CORE_ADDR watchpoint_hit;
++
+   /* Non-zero if we expect a duplicated SIGINT.  */
+   int ignore_sigint;
+ 
 diff --git a/gdb/m2-lang.c b/gdb/m2-lang.c
 index 88c7e5e..2d0b3ca 100644
 --- a/gdb/m2-lang.c
@@ -11406,6 +12012,43 @@ index cbda9c3..a07e6f2 100644
 +extern void exp_types_mark_used (struct expression *exp);
 +
  #endif /* PARSER_DEFS_H */
+diff --git a/gdb/ppc-linux-nat.c b/gdb/ppc-linux-nat.c
+index 47b74ad..22fb2fc 100644
+--- a/gdb/ppc-linux-nat.c
++++ b/gdb/ppc-linux-nat.c
+@@ -1391,6 +1391,24 @@ ppc_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw)
+   return 0;
+ }
+ 
++/* See target_detach_watchpoints.  Do not use wrapper
++   ppc_linux_remove_watchpoint as it would modify the register cache
++   (saved_dabr_value).  */
++
++static int
++ppc_linux_detach_watchpoints (void)
++{
++  pid_t tid;
++
++  tid = TIDGET (inferior_ptid);
++  if (tid == 0)
++    tid = PIDGET (inferior_ptid);
++
++  if (ptrace (PTRACE_SET_DEBUGREG, tid, NULL, NULL) < 0)
++    return -1;
++  return 0;
++}
++
+ static void
+ ppc_linux_new_thread (ptid_t ptid)
+ {
+@@ -1648,6 +1666,7 @@ _initialize_ppc_linux_nat (void)
+   t->to_region_ok_for_hw_watchpoint = ppc_linux_region_ok_for_hw_watchpoint;
+   t->to_insert_watchpoint = ppc_linux_insert_watchpoint;
+   t->to_remove_watchpoint = ppc_linux_remove_watchpoint;
++  t->to_detach_watchpoints = ppc_linux_detach_watchpoints;
+   t->to_stopped_by_watchpoint = ppc_linux_stopped_by_watchpoint;
+   t->to_stopped_data_address = ppc_linux_stopped_data_address;
+   t->to_watchpoint_addr_within_range = ppc_linux_watchpoint_addr_within_range;
 diff --git a/gdb/printcmd.c b/gdb/printcmd.c
 index 5d8b936..fb0a455 100644
 --- a/gdb/printcmd.c
@@ -18928,11 +19571,94 @@ index 740d4e0..461ff95 100644
  						  const domain_enum domain);
  
  extern struct symtabs_and_lines
+diff --git a/gdb/target.c b/gdb/target.c
+index 7ee444f..631e5f8 100644
+--- a/gdb/target.c
++++ b/gdb/target.c
+@@ -124,6 +124,8 @@ static int debug_to_insert_watchpoint (CORE_ADDR, int, int);
+ 
+ static int debug_to_remove_watchpoint (CORE_ADDR, int, int);
+ 
++static int debug_to_detach_watchpoints (void);
++
+ static int debug_to_stopped_by_watchpoint (void);
+ 
+ static int debug_to_stopped_data_address (struct target_ops *, CORE_ADDR *);
+@@ -584,6 +586,7 @@ update_current_target (void)
+       INHERIT (to_remove_hw_breakpoint, t);
+       INHERIT (to_insert_watchpoint, t);
+       INHERIT (to_remove_watchpoint, t);
++      INHERIT (to_detach_watchpoints, t);
+       INHERIT (to_stopped_data_address, t);
+       INHERIT (to_have_steppable_watchpoint, t);
+       INHERIT (to_have_continuable_watchpoint, t);
+@@ -694,6 +697,9 @@ update_current_target (void)
+   de_fault (to_remove_watchpoint,
+ 	    (int (*) (CORE_ADDR, int, int))
+ 	    return_minus_one);
++  de_fault (to_detach_watchpoints,
++	    (int (*) (void))
++	    return_zero);
+   de_fault (to_stopped_by_watchpoint,
+ 	    (int (*) (void))
+ 	    return_zero);
+@@ -3095,6 +3101,19 @@ debug_to_remove_watchpoint (CORE_ADDR addr, int len, int type)
+   return retval;
+ }
+ 
++static int
++debug_to_detach_watchpoints (void)
++{
++  int retval;
++
++  retval = debug_target.to_detach_watchpoints ();
++
++  fprintf_unfiltered (gdb_stdlog,
++		      "target_detach_watchpoints () = %ld\n",
++		      (unsigned long) retval);
++  return retval;
++}
++
+ static void
+ debug_to_terminal_init (void)
+ {
+@@ -3342,6 +3361,7 @@ setup_target_debug (void)
+   current_target.to_remove_hw_breakpoint = debug_to_remove_hw_breakpoint;
+   current_target.to_insert_watchpoint = debug_to_insert_watchpoint;
+   current_target.to_remove_watchpoint = debug_to_remove_watchpoint;
++  current_target.to_detach_watchpoints = debug_to_detach_watchpoints;
+   current_target.to_stopped_by_watchpoint = debug_to_stopped_by_watchpoint;
+   current_target.to_stopped_data_address = debug_to_stopped_data_address;
+   current_target.to_watchpoint_addr_within_range = debug_to_watchpoint_addr_within_range;
 diff --git a/gdb/target.h b/gdb/target.h
-index 2c743e9..ef29610 100644
+index 2c743e9..dbbce12 100644
 --- a/gdb/target.h
 +++ b/gdb/target.h
-@@ -1157,6 +1157,20 @@ extern int target_search_memory (CORE_ADDR start_addr,
+@@ -376,6 +376,7 @@ struct target_ops
+     int (*to_remove_hw_breakpoint) (struct gdbarch *, struct bp_target_info *);
+     int (*to_remove_watchpoint) (CORE_ADDR, int, int);
+     int (*to_insert_watchpoint) (CORE_ADDR, int, int);
++    int (*to_detach_watchpoints) (void);
+     int (*to_stopped_by_watchpoint) (void);
+     int to_have_steppable_watchpoint;
+     int to_have_continuable_watchpoint;
+@@ -1120,6 +1121,15 @@ extern char *normal_pid_to_str (ptid_t ptid);
+ #define	target_remove_watchpoint(addr, len, type)	\
+      (*current_target.to_remove_watchpoint) (addr, len, type)
+ 
++/* Clear all debug registers without affecting any register caches.  Function
++   acts on INFERIOR_PTID which should be the forked-off process, either the
++   non-threaded child one or the threaded parent one, depending on `set
++   follow-fork-mode'.  Both watchpoints and hardware breakpoints get removed.
++   Return 0 on success, -1 on failure.  */
++
++#define	target_detach_watchpoints()	\
++     (*current_target.to_detach_watchpoints) ()
++
+ #define target_insert_hw_breakpoint(gdbarch, bp_tgt) \
+      (*current_target.to_insert_hw_breakpoint) (gdbarch, bp_tgt)
+ 
+@@ -1157,6 +1167,20 @@ extern int target_search_memory (CORE_ADDR start_addr,
                                   ULONGEST pattern_len,
                                   CORE_ADDR *found_addrp);
  
@@ -18953,7 +19679,7 @@ index 2c743e9..ef29610 100644
  /* Command logging facility.  */
  
  #define target_log_command(p)						\
-@@ -1276,6 +1290,14 @@ extern struct target_ops *find_target_beneath (struct target_ops *);
+@@ -1276,6 +1300,14 @@ extern struct target_ops *find_target_beneath (struct target_ops *);
  
  extern char *target_get_osdata (const char *type);
  
@@ -20519,26 +21245,111 @@ index 0000000..5da7378
 +gdb_test "p temp1" " = '1' <repeats 78 times>" "second: print temp1"
 +gdb_test "p temp2" " = '2' <repeats 78 times>" "second: print temp2"
 +gdb_test "p temp3" " = '3' <repeats 48 times>" "second: print temp3"
-diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp
-index 4095ccf..03c07d5 100644
---- a/gdb/testsuite/gdb.cp/cp-relocate.exp
-+++ b/gdb/testsuite/gdb.cp/cp-relocate.exp
-@@ -30,7 +30,7 @@ proc get_func_address { func } {
-     global gdb_prompt hex
+diff --git a/gdb/testsuite/gdb.base/watchpoint-hw.c b/gdb/testsuite/gdb.base/watchpoint-hw.c
+index 8da9af5..e2de53a 100644
+--- a/gdb/testsuite/gdb.base/watchpoint-hw.c
++++ b/gdb/testsuite/gdb.base/watchpoint-hw.c
+@@ -20,5 +20,11 @@ int watchee;
+ int
+ main (void)
+ {
++  volatile int dummy;
++
++  dummy = watchee;
++  dummy = 1;
++  dummy = 2;	/* break-at-exit */
++
+   return 0;
+ }
+diff --git a/gdb/testsuite/gdb.base/watchpoint-hw.exp b/gdb/testsuite/gdb.base/watchpoint-hw.exp
+index a2bb731..d74d6c7 100644
+--- a/gdb/testsuite/gdb.base/watchpoint-hw.exp
++++ b/gdb/testsuite/gdb.base/watchpoint-hw.exp
+@@ -21,19 +21,12 @@ if {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]
+     return
+ }
  
-     set rfunc [string_to_regexp $func]
--    gdb_test_multiple "print '${func}'" "get address of ${func}" {
-+    gdb_test_multiple "print ${func}" "get address of ${func}" {
- 	-re "\\\$\[0-9\]+ = \\{.*\\} (0|($hex) <${rfunc}>)\[\r\n\]+${gdb_prompt} $" {
- 	    # $1 = {int ()} 0x24 <function_bar>
- 	    # But if the function is at zero, the name may be omitted.
-@@ -130,7 +130,7 @@ gdb_test "add-symbol-file ${binfile} 0 -s ${func1_sec} 0x10000 -s ${func2_sec} 0
- 	"y"
+-set testfile watchpoint-hw
+-set srcfile ${testfile}.c
+-set binfile ${objdir}/${subdir}/${testfile}
+-if  { [gdb_compile "${srcdir}/${subdir}/${srcfile}" "${binfile}" executable {debug}] != "" } {
+-    untested "Couldn't compile test program"
++set test watchpoint-hw
++set srcfile ${test}.c
++if { [prepare_for_testing ${test}.exp ${test} ${srcfile}] } {
+     return -1
+ }
  
- # Make sure the function addresses were updated.
--gdb_test "break *'$func1_name'" \
-+gdb_test "break *$func1_name" \
-     "Breakpoint $decimal at 0x1....: file .*"
+-gdb_exit
+-gdb_start
+-gdb_reinitialize_dir $srcdir/$subdir
+-gdb_load ${binfile}
+-
+ # Create the watchpoint before the inferior gets started.  Now the native CPU
+ # target is still not active and its `to_can_use_hw_breakpoint' is not
+ # installed, therefore only a software watchpoint gets created.
+@@ -43,10 +36,40 @@ gdb_test "watch watchee" "atchpoint 1: watchee"
+ # `runto_main' or `runto main' would delete the watchpoint created above.
+ 
+ if { [gdb_start_cmd] < 0 } {
+-    untested start
++    untested ${test}.exp
+     return -1
+ }
+ gdb_test "" "main .* at .*" "start"
+ 
+ # Check it is really a `hw'-watchpoint.
+ gdb_test "info watchpoints" "1 *hw watchpoint .* watchee"
++
++# Before the inferior gets started we would get:
++# 	Target does not support this type of hardware watchpoint.
++gdb_test "delete 1"
++gdb_test "rwatch watchee"
++
++set breakline [gdb_get_line_number "break-at-exit"]
++gdb_breakpoint $breakline
++
++gdb_test "continue" "Continuing.\r\nHardware read watchpoint 3: watchee\r\n\r\nValue = 0\r\n.*"
++
++# Here should be no repeated notification of the read watchpoint.
++gdb_test "continue" \
++	 "Continuing\\.\[ \r\n\]+Breakpoint \[0-9\]+, .*break-at-exit.*" \
++	 "continue to break-at-exit after rwatch"
++
++clean_restart ${test}
++
++if ![runto_main] {
++    untested ${test}.exp
++    return -1
++}
++
++gdb_test "hbreak ${srcfile}:${breakline}" \
++	 "Hardware assisted breakpoint 2 at 0x\[0-9a-f\]+: file .*${srcfile}, line ${breakline}\\." \
++	 "hbreak"
++
++gdb_test "continue" \
++	 "Continuing\\.\[ \r\n\]+Breakpoint \[0-9\]+, .*break-at-exit.*" \
++	 "continue to break-at-exit after hbreak"
+diff --git a/gdb/testsuite/gdb.cp/cp-relocate.exp b/gdb/testsuite/gdb.cp/cp-relocate.exp
+index 4095ccf..03c07d5 100644
+--- a/gdb/testsuite/gdb.cp/cp-relocate.exp
++++ b/gdb/testsuite/gdb.cp/cp-relocate.exp
+@@ -30,7 +30,7 @@ proc get_func_address { func } {
+     global gdb_prompt hex
+ 
+     set rfunc [string_to_regexp $func]
+-    gdb_test_multiple "print '${func}'" "get address of ${func}" {
++    gdb_test_multiple "print ${func}" "get address of ${func}" {
+ 	-re "\\\$\[0-9\]+ = \\{.*\\} (0|($hex) <${rfunc}>)\[\r\n\]+${gdb_prompt} $" {
+ 	    # $1 = {int ()} 0x24 <function_bar>
+ 	    # But if the function is at zero, the name may be omitted.
+@@ -130,7 +130,7 @@ gdb_test "add-symbol-file ${binfile} 0 -s ${func1_sec} 0x10000 -s ${func2_sec} 0
+ 	"y"
+ 
+ # Make sure the function addresses were updated.
+-gdb_test "break *'$func1_name'" \
++gdb_test "break *$func1_name" \
+     "Breakpoint $decimal at 0x1....: file .*"
 -gdb_test "break *'$func2_name'" \
 +gdb_test "break *$func2_name" \
      "Breakpoint $decimal at 0x2....: file .*"
@@ -24965,6 +25776,1028 @@ index 5223fc8..03e1eab 100644
  }
  
  gdb_py_test_multiple "multi-line python command" \
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
+new file mode 100644
+index 0000000..4dc308b
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork-forkoff.c
+@@ -0,0 +1,175 @@
++/* Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++   Copyright 2008, 2009 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 2 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, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <string.h>
++#include <errno.h>
++
++static void
++delay (void)
++{
++  int i = usleep (1000000 / 100);
++  assert (i == 0 || errno == EINTR);
++}
++
++#if defined FOLLOW_PARENT
++
++static void
++forkoff (int nr)
++{
++  pid_t child, pid_got;
++  int exit_code = 42 + nr;
++  int status, i;
++
++  child = fork ();
++  switch (child)
++    {
++    case -1:
++      assert (0);
++    case 0:
++      printf ("child%d: %d\n", nr, (int) getpid ());
++      /* Delay to get both the "child%d" and "parent%d" message printed without
++	 a race breaking expect by its endless wait on `$gdb_prompt$':
++	 Breakpoint 3, breakpoint () at ../../../gdb/testsuite/gdb.threads/watchpoint-fork.c:33
++	 33      }
++	 (gdb) parent2: 14223  */
++      i = sleep (1);
++      assert (i == 0);
++
++      /* We must not get caught here (against a forgotten breakpoint).  */
++      var++;
++      breakpoint ();
++
++      _exit (exit_code);
++    default:
++      printf ("parent%d: %d\n", nr, (int) child);
++      /* Delay to get both the "child%d" and "parent%d" message printed, see
++	 above.  */
++      i = sleep (1);
++      assert (i == 0);
++
++      pid_got = wait (&status);
++      assert (pid_got == child);
++      assert (WIFEXITED (status));
++      assert (WEXITSTATUS (status) == exit_code);
++
++      /* We must get caught here (against a false watchpoint removal).  */
++      breakpoint ();
++    }
++}
++
++#elif defined FOLLOW_CHILD
++
++static volatile int usr1_got;
++
++static void
++handler_usr1 (int signo)
++{
++  usr1_got++;
++}
++
++static void
++forkoff (int nr)
++{
++  pid_t child;
++  int i, loop;
++  struct sigaction act, oldact;
++#ifdef THREAD
++  void *thread_result;
++#endif
++
++  memset (&act, 0, sizeof act);
++  act.sa_flags = SA_RESTART;
++  act.sa_handler = handler_usr1;
++  sigemptyset (&act.sa_mask);
++  i = sigaction (SIGUSR1, &act, &oldact);
++  assert (i == 0);
++
++  child = fork ();
++  switch (child)
++    {
++    case -1:
++      assert (0);
++    default:
++      printf ("parent%d: %d\n", nr, (int) child);
++
++      /* Sleep for a while to possibly get incorrectly ATTACH_THREADed by GDB
++	 tracing the child fork with no longer valid thread/lwp entries of the
++	 parent.  */
++
++      i = sleep (2);
++      assert (i == 0);
++
++      /* We must not get caught here (against a forgotten breakpoint).  */
++
++      var++;
++      breakpoint ();
++
++#ifdef THREAD
++      /* And neither got caught our thread.  */
++
++      step = 99;
++      i = pthread_join (thread, &thread_result);
++      assert (i == 0);
++      assert (thread_result == (void *) 99UL);
++#endif
++
++      /* Be sure our child knows we did not get caught above.  */
++
++      i = kill (child, SIGUSR1);
++      assert (i == 0);
++
++      /* Sleep for a while to check GDB's `info threads' no longer tracks us in
++	 the child fork.  */
++
++      i = sleep (2);
++      assert (i == 0);
++
++      _exit (0);
++    case 0:
++      printf ("child%d: %d\n", nr, (int) getpid ());
++
++      /* Let the parent signal us about its success.  Be careful of races.  */
++
++      for (loop = 0; loop < 1000; loop++)
++	{
++	  /* Parent either died (and USR1_GOT is zero) or it succeeded.  */
++	  if (kill (getppid (), 0) != 0)
++	    break;
++	  /* Parent succeeded?  */
++	  if (usr1_got)
++	    break;
++
++	  delay ();
++	}
++      assert (usr1_got);
++
++      /* We must get caught here (against a false watchpoint removal).  */
++
++      breakpoint ();
++    }
++
++  i = sigaction (SIGUSR1, &oldact, NULL);
++  assert (i == 0);
++}
++
++#else
++# error "!FOLLOW_PARENT && !FOLLOW_CHILD"
++#endif
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
+new file mode 100644
+index 0000000..edacfc0
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork-mt.c
+@@ -0,0 +1,157 @@
++/* Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++   Copyright 2008, 2009 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 2 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, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <assert.h>
++#include <unistd.h>
++#include <sys/wait.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <pthread.h>
++
++#include <asm/unistd.h>
++#include <unistd.h>
++#define gettid() syscall (__NR_gettid)
++
++/* Non-atomic `var++' should not hurt as we synchronize the threads by the STEP
++   variable.  Hit-comments need to be duplicite there to catch both at-stops
++   and behind-stops, depending on the target.  */
++
++static volatile int var;
++
++static void
++dummy (void)
++{
++}
++
++static void
++breakpoint (void)
++{
++}
++
++/* Include here the functions:
++   static void forkoff (int nr);
++   static void delay (void);  */
++
++static pthread_t thread;
++static volatile int step;
++#define THREAD
++
++#include "watchpoint-fork-forkoff.c"
++
++static void *
++start (void *arg)
++{
++  if (step >= 3)
++    goto step_3;
++
++  while (step != 1)
++    delay ();
++
++  var++;	/* validity-thread-B */
++  dummy ();	/* validity-thread-B */
++  step = 2;
++  while (step != 3)
++    {
++      if (step == 99)
++	goto step_99;
++      delay ();
++    }
++
++step_3:
++  if (step >= 5)
++    goto step_5;
++
++  var++;	/* after-fork1-B */
++  dummy ();	/* after-fork1-B */
++  step = 4;
++  while (step != 5)
++    {
++      if (step == 99)
++	goto step_99;
++      delay ();
++    }
++
++step_5:
++  var++;	/* after-fork2-B */
++  dummy ();	/* after-fork2-B */
++  return (void *) 5UL;
++
++step_99:
++  /* We must not get caught here (against a forgotten breakpoint).  */
++  var++;
++  breakpoint ();
++  return (void *) 99UL;
++}
++
++int
++main (void)
++{
++  int i;
++  void *thread_result;
++
++  setbuf (stdout, NULL);
++  printf ("main: %d\n", (int) gettid ());
++
++  /* General watchpoints validity.  */
++  var++;	/* validity-first */
++  dummy ();	/* validity-first */
++
++  i = pthread_create (&thread, NULL, start, NULL);
++  assert (i == 0);
++
++  var++;	/* validity-thread-A */
++  dummy ();	/* validity-thread-A */
++  step = 1;
++  while (step != 2)
++    delay ();
++
++  /* Hardware watchpoints got disarmed here.  */
++  forkoff (1);
++
++  var++;	/* after-fork1-A */
++  dummy ();	/* after-fork1-A */
++  step = 3;
++#ifdef FOLLOW_CHILD
++  /* Spawn new thread as it was deleted in the child of FORK.  */
++  i = pthread_create (&thread, NULL, start, NULL);
++  assert (i == 0);
++#endif
++  while (step != 4)
++    delay ();
++
++  /* A sanity check for double hardware watchpoints removal.  */
++  forkoff (2);
++
++  var++;	/* after-fork2-A */
++  dummy ();	/* after-fork2-A */
++  step = 5;
++#ifdef FOLLOW_CHILD
++  /* Spawn new thread as it was deleted in the child of FORK.  */
++  i = pthread_create (&thread, NULL, start, NULL);
++  assert (i == 0);
++#endif
++
++  i = pthread_join (thread, &thread_result);
++  assert (i == 0);
++  assert (thread_result == (void *) 5UL);
++
++  return 0;
++}
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.c b/gdb/testsuite/gdb.threads/watchpoint-fork.c
+new file mode 100644
+index 0000000..5f62e7f
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork.c
+@@ -0,0 +1,57 @@
++/* Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++   Copyright 2008, 2009 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 2 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, write to the Free Software
++   Foundation, Inc., 59 Temple Place - Suite 330,
++   Boston, MA 02111-1307, USA.  */
++
++#include <assert.h>
++#include <unistd.h>
++#include <sys/wait.h>
++#include <stdio.h>
++#include <stdlib.h>
++
++static volatile int var;
++
++static void
++breakpoint (void)
++{
++}
++
++/* Include here the function:
++   static void forkoff (int nr);  */
++
++#include "watchpoint-fork-forkoff.c"
++
++int
++main (void)
++{
++  setbuf (stdout, NULL);
++  printf ("main: %d\n", (int) getpid ());
++
++  /* General watchpoints validity.  */
++  var++;
++  /* Hardware watchpoints got disarmed here.  */
++  forkoff (1);
++  /* This watchpoint got lost before.  */
++  var++;
++  /* A sanity check for double hardware watchpoints removal.  */
++  forkoff (2);
++  var++;
++
++  return 0;
++}
+diff --git a/gdb/testsuite/gdb.threads/watchpoint-fork.exp b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
+new file mode 100644
+index 0000000..1dc93ab
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchpoint-fork.exp
+@@ -0,0 +1,130 @@
++# Copyright 2008, 2009 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/>.
++
++# Test case for forgotten hw-watchpoints after fork()-off of a process.
++
++proc test {type symbol} {
++    global objdir subdir srcdir
++
++    set test watchpoint-fork
++
++    global pf_prefix
++    set prefix_test $pf_prefix
++    lappend pf_prefix "$type:"
++    set prefix_mt $pf_prefix
++
++    # no threads
++
++    set pf_prefix $prefix_mt
++    lappend pf_prefix "singlethreaded:"
++
++    set executable ${test}-${type}
++    if { [gdb_compile ${srcdir}/${subdir}/${test}.c ${objdir}/${subdir}/${executable} executable [list debug additional_flags=-D$symbol]] != "" } {
++	untested ${test}.exp
++	return -1
++    }
++    clean_restart $executable
++
++    gdb_test "show detach-on-fork" "Whether gdb will detach the child of a fork is on."
++    gdb_test "set follow-fork-mode $type"
++    gdb_test "show follow-fork-mode" "Debugger response to a program call of fork or vfork is \"$type\"."
++    # Testcase uses it for the `follow-fork-mode child' type.
++    gdb_test "handle SIGUSR1 nostop noprint pass"
++
++    if { ![runto_main] } then {
++	gdb_suppress_tests
++	return
++    }
++
++    # Install the watchpoint only after getting into MAIN - workaround some PPC
++    # problem.
++    gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
++
++    # It is never hit but it should not be left over in the fork()ed-off child.
++    gdb_breakpoint "breakpoint"
++
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 0.*New value = 1.*forkoff *\\(1\\).*" "watchpoints work"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint after the first fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 1.*New value = 2.*forkoff *\\(2\\).*" "watchpoint after the first fork"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint after the second fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 2.*New value = 3.*return *0;" "watchpoint after the second fork"
++    gdb_test "continue" "Continuing..*Program exited normally." "finish"
++
++
++    # threads
++
++    set pf_prefix $prefix_mt
++    lappend pf_prefix "multithreaded:"
++
++    set executable ${test}-mt-${type}
++    if { [gdb_compile_pthreads ${srcdir}/${subdir}/${test}-mt.c ${objdir}/${subdir}/${executable} executable [list debug additional_flags=-D$symbol]] != "" } {
++	untested ${test}.exp
++	return -1
++    }
++    clean_restart $executable
++
++    gdb_test "set follow-fork-mode $type"
++    # Testcase uses it for the `follow-fork-mode child' type.
++    gdb_test "handle SIGUSR1 nostop noprint pass"
++
++    if { ![runto_main] } then {
++	gdb_suppress_tests
++	return
++    }
++
++    # Install the watchpoint only after getting into MAIN - workaround some PPC
++    # problem.
++    gdb_test "watch var" "atchpoint 2: var" "Set the watchpoint"
++
++    # It is never hit but it should not be left over in the fork()ed-off child.
++    gdb_breakpoint "breakpoint"
++
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 0.*New value = 1.*validity-first.*" "singlethread watchpoints work"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 1.*New value = 2.*validity-thread-A.*" "multithreaded watchpoints work at A"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 2.*New value = 3.*validity-thread-B.*" "multithreaded watchpoints work at B"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint (A) after the first fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 3.*New value = 4.*after-fork1-A.*" "watchpoint A after the first fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 4.*New value = 5.*after-fork1-B.*" "watchpoint B after the first fork"
++    gdb_test "continue" \
++	     "reakpoint 3, breakpoint.*" "breakpoint (A) after the second fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 5.*New value = 6.*after-fork2-A.*" "watchpoint A after the second fork"
++    gdb_test "continue" \
++	     "atchpoint 2: var.*Old value = 6.*New value = 7.*after-fork2-B.*" "watchpoint B after the second fork"
++    gdb_test "continue" "Continuing..*Program exited normally." "finish"
++
++
++    # cleanup
++
++    set pf_prefix $prefix_test
++}
++
++test parent FOLLOW_PARENT
++
++# Only GNU/Linux is known to support `set follow-fork-mode child'.
++if {[istarget "*-*-linux*"]} {
++    test child FOLLOW_CHILD
++}
+diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.c b/gdb/testsuite/gdb.threads/watchthreads-reorder.c
+new file mode 100644
+index 0000000..14f42d6
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchthreads-reorder.c
+@@ -0,0 +1,366 @@
++/* This testcase is part of GDB, the GNU debugger.
++
++   Copyright 2009 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/>.  */
++
++#define _GNU_SOURCE
++#include <pthread.h>
++#include <stdio.h>
++#include <limits.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <string.h>
++#include <assert.h>
++#include <sys/types.h>
++#include <signal.h>
++#include <unistd.h>
++#include <asm/unistd.h>
++
++#define gettid() syscall (__NR_gettid)
++
++/* Terminate always in the main task, it can lock up with SIGSTOPped GDB
++   otherwise.  */
++#define TIMEOUT (gettid () == getpid() ? 10 : 15)
++
++static pthread_mutex_t gdbstop_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static pid_t thread1_tid;
++static pthread_cond_t thread1_tid_cond = PTHREAD_COND_INITIALIZER;
++static pthread_mutex_t thread1_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static pid_t thread2_tid;
++static pthread_cond_t thread2_tid_cond = PTHREAD_COND_INITIALIZER;
++static pthread_mutex_t thread2_tid_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static pthread_mutex_t terminate_mutex = PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP;
++
++static volatile int thread1_rwatch;
++static volatile int thread2_rwatch;
++
++static int unused1_rwatch;
++static int unused2_rwatch;
++
++/* Do not use alarm as it would create a ptrace event which would hang up us if
++ * we are being traced by GDB which we stopped ourselves.  */
++
++static void timed_mutex_lock (pthread_mutex_t *mutex)
++{
++  int i;
++  struct timespec start, now;
++
++  i = clock_gettime (CLOCK_MONOTONIC, &start);
++  assert (i == 0);
++
++  do
++    {
++      i = pthread_mutex_trylock (mutex);
++      if (i == 0)
++	return;
++      assert (i == EBUSY);
++
++      i = clock_gettime (CLOCK_MONOTONIC, &now);
++      assert (i == 0);
++      assert (now.tv_sec >= start.tv_sec);
++    }
++  while (now.tv_sec - start.tv_sec < TIMEOUT);
++
++  fprintf (stderr, "Timed out waiting for internal lock!\n");
++  exit (EXIT_FAILURE);
++}
++
++static void *
++thread1_func (void *unused)
++{
++  int i;
++  volatile int rwatch_store;
++
++  thread1_tid = gettid ();
++  i = pthread_cond_signal (&thread1_tid_cond);
++  assert (i == 0);
++
++  /* Be sure GDB is already stopped before continuing.  */
++  timed_mutex_lock (&gdbstop_mutex);
++  i = pthread_mutex_unlock (&gdbstop_mutex);
++  assert (i == 0);
++
++  rwatch_store = thread1_rwatch;
++
++  /* Be sure the "T (tracing stop)" test can proceed for both threads.  */
++  timed_mutex_lock (&terminate_mutex);
++  i = pthread_mutex_unlock (&terminate_mutex);
++  assert (i == 0);
++
++  return NULL;
++}
++
++static void *
++thread2_func (void *unused)
++{
++  int i;
++  volatile int rwatch_store;
++
++  thread2_tid = gettid ();
++  i = pthread_cond_signal (&thread2_tid_cond);
++  assert (i == 0);
++
++  /* Be sure GDB is already stopped before continuing.  */
++  timed_mutex_lock (&gdbstop_mutex);
++  i = pthread_mutex_unlock (&gdbstop_mutex);
++  assert (i == 0);
++
++  rwatch_store = thread2_rwatch;
++
++  /* Be sure the "T (tracing stop)" test can proceed for both threads.  */
++  timed_mutex_lock (&terminate_mutex);
++  i = pthread_mutex_unlock (&terminate_mutex);
++  assert (i == 0);
++
++  return NULL;
++}
++
++static const char *
++proc_string (const char *filename, const char *line)
++{
++  FILE *f;
++  static char buf[LINE_MAX];
++  size_t line_len = strlen (line);
++
++  f = fopen (filename, "r");
++  if (f == NULL)
++    {
++      fprintf (stderr, "fopen (\"%s\") for \"%s\": %s\n", filename, line,
++	       strerror (errno));
++      exit (EXIT_FAILURE);
++    }
++  while (errno = 0, fgets (buf, sizeof (buf), f))
++    {
++      char *s;
++
++      s = strchr (buf, '\n');
++      assert (s != NULL);
++      *s = 0;
++
++      if (strncmp (buf, line, line_len) != 0)
++	continue;
++
++      if (fclose (f))
++	{
++	  fprintf (stderr, "fclose (\"%s\") for \"%s\": %s\n", filename, line,
++		   strerror (errno));
++	  exit (EXIT_FAILURE);
++	}
++
++      return &buf[line_len];
++    }
++  if (errno != 0)
++    {
++      fprintf (stderr, "fgets (\"%s\": %s\n", filename, strerror (errno));
++      exit (EXIT_FAILURE);
++    }
++  fprintf (stderr, "\"%s\": No line \"%s\" found.\n", filename, line);
++  exit (EXIT_FAILURE);
++}
++
++static unsigned long
++proc_ulong (const char *filename, const char *line)
++{
++  const char *s = proc_string (filename, line);
++  long retval;
++  char *end;
++
++  errno = 0;
++  retval = strtol (s, &end, 10);
++  if (retval < 0 || retval >= LONG_MAX || (end && *end))
++    {
++      fprintf (stderr, "\"%s\":\"%s\": %ld, %s\n", filename, line, retval,
++	       strerror (errno));
++      exit (EXIT_FAILURE);
++    }
++  return retval;
++}
++
++static void
++state_wait (pid_t process, const char *wanted)
++{
++  char *filename;
++  int i;
++  struct timespec start, now;
++  const char *state;
++
++  i = asprintf (&filename, "/proc/%lu/status", (unsigned long) process);
++  assert (i > 0);
++
++  i = clock_gettime (CLOCK_MONOTONIC, &start);
++  assert (i == 0);
++
++  do
++    {
++      state = proc_string (filename, "State:\t");
++      if (strcmp (state, wanted) == 0)
++	{
++	  free (filename);
++	  return;
++	}
++
++      if (sched_yield ())
++	{
++	  perror ("sched_yield()");
++	  exit (EXIT_FAILURE);
++	}
++
++      i = clock_gettime (CLOCK_MONOTONIC, &now);
++      assert (i == 0);
++      assert (now.tv_sec >= start.tv_sec);
++    }
++  while (now.tv_sec - start.tv_sec < TIMEOUT);
++
++  fprintf (stderr, "Timed out waiting for PID %lu \"%s\" (now it is \"%s\")!\n",
++	   (unsigned long) process, wanted, state);
++  exit (EXIT_FAILURE);
++}
++
++static volatile pid_t tracer = 0;
++static pthread_t thread1, thread2;
++
++static void
++cleanup (void)
++{
++  printf ("Resuming GDB PID %lu.\n", (unsigned long) tracer);
++
++  if (tracer)
++    {
++      int i;
++      int tracer_save = tracer;
++
++      tracer = 0;
++
++      i = kill (tracer_save, SIGCONT);
++      assert (i == 0);
++    }
++}
++
++int
++main (int argc, char **argv)
++{
++  int i;
++  int standalone = 0;
++
++  if (argc == 2 && strcmp (argv[1], "-s") == 0)
++    standalone = 1;
++  else
++    assert (argc == 1);
++
++  setbuf (stdout, NULL);
++
++  timed_mutex_lock (&gdbstop_mutex);
++
++  timed_mutex_lock (&terminate_mutex);
++
++  i = pthread_create (&thread1, NULL, thread1_func, NULL);
++  assert (i == 0);
++
++  i = pthread_create (&thread2, NULL, thread2_func, NULL);
++  assert (i == 0);
++
++  if (!standalone)
++    {
++      tracer = proc_ulong ("/proc/self/status", "TracerPid:\t");
++      if (tracer == 0)
++	{
++	  fprintf (stderr, "The testcase must be run by GDB!\n");
++	  exit (EXIT_FAILURE);
++	}
++      if (tracer != getppid ())
++	{
++	  fprintf (stderr, "The testcase parent must be our GDB tracer!\n");
++	  exit (EXIT_FAILURE);
++	}
++    }
++
++  /* SIGCONT our debugger in the case of our crash as we would deadlock
++     otherwise.  */
++
++  atexit (cleanup);
++
++  printf ("Stopping GDB PID %lu.\n", (unsigned long) tracer);
++
++  if (tracer)
++    {
++      i = kill (tracer, SIGSTOP);
++      assert (i == 0);
++      state_wait (tracer, "T (stopped)");
++    }
++
++  timed_mutex_lock (&thread1_tid_mutex);
++  timed_mutex_lock (&thread2_tid_mutex);
++
++  /* Let the threads start.  */
++  i = pthread_mutex_unlock (&gdbstop_mutex);
++  assert (i == 0);
++
++  printf ("Waiting till the threads initialize their TIDs.\n");
++
++  if (thread1_tid == 0)
++    {
++      i = pthread_cond_wait (&thread1_tid_cond, &thread1_tid_mutex);
++      assert (i == 0);
++
++      assert (thread1_tid > 0);
++    }
++
++  if (thread2_tid == 0)
++    {
++      i = pthread_cond_wait (&thread2_tid_cond, &thread2_tid_mutex);
++      assert (i == 0);
++
++      assert (thread2_tid > 0);
++    }
++
++  printf ("Thread 1 TID = %lu, thread 2 TID = %lu, PID = %lu.\n",
++	  (unsigned long) thread1_tid, (unsigned long) thread2_tid,
++	  (unsigned long) getpid ());
++
++  printf ("Waiting till the threads get trapped by the watchpoints.\n");
++
++  if (tracer)
++    {
++      /* s390x-unknown-linux-gnu will fail with "R (running)".  */
++
++      state_wait (thread1_tid, "T (tracing stop)");
++
++      state_wait (thread2_tid, "T (tracing stop)");
++    }
++
++  cleanup ();
++
++  printf ("Joining the threads.\n");
++
++  i = pthread_mutex_unlock (&terminate_mutex);
++  assert (i == 0);
++
++  i = pthread_join (thread1, NULL);
++  assert (i == 0);
++
++  i = pthread_join (thread2, NULL);
++  assert (i == 0);
++
++  printf ("Exiting.\n");	/* break-at-exit */
++
++  /* Just prevent compiler `warning: ‘unusedX_rwatch’ defined but not used'.  */
++  unused1_rwatch = 1;
++  unused2_rwatch = 2;
++
++  return EXIT_SUCCESS;
++}
+diff --git a/gdb/testsuite/gdb.threads/watchthreads-reorder.exp b/gdb/testsuite/gdb.threads/watchthreads-reorder.exp
+new file mode 100644
+index 0000000..8f65364
+--- /dev/null
++++ b/gdb/testsuite/gdb.threads/watchthreads-reorder.exp
+@@ -0,0 +1,101 @@
++# This testcase is part of GDB, the GNU debugger.
++
++# Copyright 2009 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/>.
++
++# Test GDB can cope with two watchpoints being hit by different threads at the
++# same time, GDB reports one of them and after "continue" to report the other
++# one GDB should not be confused by differently set watchpoints that time.
++# This is the goal of "reorder1".  "reorder0" tests the basic functionality of
++# two watchpoint being hit at the same time, without reordering them during the
++# stop.  The formerly broken functionality is due to the all-stop mode default
++# "show breakpoint always-inserted" being "off".  Formerly the remembered hit
++# could be assigned during continuation of a thread with pending SIGTRAP to the
++# different/new watchpoint, just based on the watchpoint/debug register number.
++
++if {[target_info exists gdb,no_hardware_watchpoints]
++    || ![istarget *-*-linux*]} {
++    return 0;
++}
++
++set testfile "watchthreads-reorder"
++set srcfile ${testfile}.c
++set binfile ${objdir}/${subdir}/${testfile}
++if {[gdb_compile_pthreads "${srcdir}/${subdir}/${srcfile}" ${binfile} executable [list debug additional_flags=-lrt]] != "" } {
++    return -1
++}
++
++foreach reorder {0 1} {
++
++    global pf_prefix
++    set prefix_test $pf_prefix
++    lappend pf_prefix "reorder$reorder:"
++
++    clean_restart $testfile
++
++    gdb_test "set can-use-hw-watchpoints 1"
++
++    if ![runto_main] {
++	gdb_suppress_tests
++    }
++
++    # Use "rwatch" as "watch" would report the watchpoint changed just based on its
++    # read memory value during a stop by unrelated event.  We are interested to not
++    # to lose the hardware watchpoint trigger.
++
++    gdb_test "rwatch thread1_rwatch" "Hardware read watchpoint \[0-9\]+: thread1_rwatch"
++    gdb_test {set $rwatch1=$bpnum}
++    set test "rwatch thread2_rwatch"
++    gdb_test_multiple $test $test {
++	-re "Target does not support this type of hardware watchpoint\\.\r\n$gdb_prompt $" {
++	    # ppc64 supports at most 1 hw watchpoints.
++	    unsupported $test
++	    return
++	}
++	-re "Hardware read watchpoint \[0-9\]+: thread2_rwatch\r\n$gdb_prompt $" {
++	    pass $test
++	}
++    }
++    gdb_test {set $rwatch2=$bpnum}
++    gdb_breakpoint [gdb_get_line_number "break-at-exit"]
++
++    # The watchpoints can happen in arbitrary order depending on random:
++    # SEL: Found 2 SIGTRAP events, selecting #[01]
++    # As GDB contains no srand() on the specific host/OS it will behave always the
++    # same.  Such order cannot be guaranteed for GDB in general.
++
++    gdb_test "continue" \
++	     "Hardware read watchpoint \[0-9\]+: thread\[12\]_rwatch\r\n\r\nValue = 0\r\n0x\[0-9a-f\]+ in thread\[12\]_func .*" \
++	     "continue a"
++
++    if $reorder {
++	gdb_test {delete $rwatch1}
++	gdb_test {delete $rwatch2}
++
++	gdb_test "rwatch unused1_rwatch" "Hardware read watchpoint \[0-9\]+: unused1_rwatch"
++	gdb_test "rwatch unused2_rwatch" "Hardware read watchpoint \[0-9\]+: unused2_rwatch"
++
++	gdb_test "rwatch thread1_rwatch" "Hardware read watchpoint \[0-9\]+: thread1_rwatch"
++	gdb_test "rwatch thread2_rwatch" "Hardware read watchpoint \[0-9\]+: thread2_rwatch"
++    }
++
++    gdb_test "continue" \
++	     "Hardware read watchpoint \[0-9\]+: thread\[12\]_rwatch\r\n\r\nValue = 0\r\n0x\[0-9a-f\]+ in thread\[12\]_func .*" \
++	     "continue b"
++
++    gdb_continue_to_breakpoint "break-at-exit" ".*break-at-exit.*"
++
++    set pf_prefix $prefix_test
++}
 diff --git a/gdb/testsuite/lib/cp-support.exp b/gdb/testsuite/lib/cp-support.exp
 index dbd2f59..44e1b51 100644
 --- a/gdb/testsuite/lib/cp-support.exp


Index: gdb.spec
===================================================================
RCS file: /cvs/pkgs/rpms/gdb/devel/gdb.spec,v
retrieving revision 1.376
retrieving revision 1.377
diff -u -p -r1.376 -r1.377
--- gdb.spec	18 Aug 2009 19:10:33 -0000	1.376
+++ gdb.spec	18 Aug 2009 19:37:35 -0000	1.377
@@ -14,7 +14,7 @@ Version: 6.8.50.20090818
 
 # The release always contains a leading reserved number, start it at 1.
 # `upstream' is not a part of `name' to stay fully rpm dependencies compatible for the testing.
-Release: 2%{?_with_upstream:.upstream}%{?dist}
+Release: 3%{?_with_upstream:.upstream}%{?dist}
 
 License: GPLv3+
 Group: Development/Debuggers
@@ -821,6 +821,10 @@ fi
 %endif
 
 %changelog
+* Tue Aug 18 2009 Jan Kratochvil <jan.kratochvil at redhat.com> - 6.8.50.20090818-3
+- archer-jankratochvil-fedora12 commit: 850e3cb38a25cb7fdfa4cef667626ffbde51bcac
+- Fix the hardware watchpoints.
+
 * Tue Aug 18 2009 Jan Kratochvil <jan.kratochvil at redhat.com> - 6.8.50.20090818-2
 - Fix patch fuzz 0.
 




More information about the scm-commits mailing list