=== added file 'ChangeLog.linaro'
--- a/ChangeLog.linaro	1970-01-01 00:00:00 +0000
+++ b/ChangeLog.linaro	2011-03-04 19:27:32 +0000
@@ -0,0 +1,511 @@
+2011-03-04  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Backport from mainline:
+
+	2011-03-04  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* inflow.c (terminal_init_inferior_with_pgrp): Copy ttystate.
+	(terminal_save_ours): Remove misleading comment.
+	(inflow_inferior_data_cleanup): Free ttystate.
+	(inflow_inferior_exit): Likewise.
+	(copy_terminal_info): Copy ttystate.
+
+	* serial.c (serial_copy_tty_state): New function.
+	* serial.h (serial_copy_tty_state): Add prototype.
+	(struct serial_ops): Add copy_tty_state callback.
+	* ser-base.c (ser_base_copy_tty_state): New function.
+	* ser-base.h (ser_base_copy_tty_state): Add prototype.
+	* ser-go32.c (dos_copy_tty_state): New function.
+	(dos_ops): Install copy_tty_state callback.
+	* ser-mingw.c (_initialize_ser_windows): Likewise.
+	* ser-pipe.c (_initialize_ser_pipe): Likewise.
+	* ser-unix.c (hardwire_copy_tty_state): New function.
+	(_initialize_ser_hardwire): Install it.
+
+2011-03-01  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Fix LP #620611
+	Backport from mainline:
+
+	2011-03-01  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* arm-linux-tdep.c (ARM_LDR_PC_SP_4): Add define.
+	(arm_linux_restart_syscall_init): Handle both on-stack and in-kernel
+	versions of the trampoline.  Handle Thumb vs. ARM addresses.
+	(arm_kernel_linux_restart_syscall_tramp_frame): New global.
+	(arm_linux_init_abi): Install it.
+
+2011-02-21  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Backport from mainline:
+
+	2011-02-21  Matthew Gretton-Dann <matthew.gretton-dann@arm.com>
+		    Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/
+	* arm-linux-nat.c: Include "observer.h" and "gdbthread.h".
+	(PTRACE_GETHBPREGS, PTRACE_SETHBPREGS): Define.
+	(struct arm_linux_hwbp_cap): New type.
+	(arm_linux_get_hwbp_cap): New function.
+	(arm_linux_get_hw_breakpoint_count): Likewise.
+	(arm_linux_get_hw_watchpoint_count): Likewise.
+	(arm_linux_can_use_hw_breakpoint): Likewise.
+	(arm_hwbp_type): New type.
+	(arm_hwbp_control_t): Likewise.
+	(struct arm_linux_hw_breakpoint): Likewise.
+	(struct arm_linux_thread_points): Likewise.
+	(arm_threads): New global variable.
+	(arm_linux_find_breakpoints_by_tid): New function.
+	(arm_hwbp_control_initialize): Likewise.
+	(arm_hwbp_control_is_enabled): Likewise.
+	(arm_hwbp_control_disable): Likewise.
+	(arm_linux_hw_breakpoint_initialize): Likewise.
+	(arm_linux_get_hwbp_type): Likewise.
+	(arm_linux_hw_watchpoint_initialize): Likewise.
+	(arm_linux_hw_breakpoint_equal): Likewise.
+	(arm_linux_insert_hw_breakpoint1): Likewise.
+	(arm_linux_remove_hw_breakpoint1): Likewise.
+	(arm_linux_insert_hw_breakpoint): Likewise.
+	(arm_linux_remove_hw_breakpoint): Likewise.
+	(arm_linux_region_ok_for_hw_watchpoint): Likewise.
+	(arm_linux_insert_watchpoint): Likewise.
+	(arm_linux_remove_watchpoint): Likewise.
+	(arm_linux_stopped_data_address): Likewise.
+	(arm_linux_stopped_by_watchpoint): Likewise.
+	(arm_linux_watchpoint_addr_within_range): Likewise.
+	(arm_linux_new_thread): Likewise.
+	(arm_linux_thread_exit): Likewise.
+	(_initialize_arm_linux_nat): Install hardware breakpoint/watchpoint
+	related target callbacks.  Register arm_linux_new_thread and
+	arm_linux_thread_exit.
+	* arm-tdep.h (arm_pc_is_thumb): Add prototype.
+	* arm-tdep.c (arm_pc_is_thumb): Make global.
+	(arm_gdbarch_init): Call set_gdbarch_have_nonsteppable_watchpoint.
+
+	gdb/testsuite/
+	* lib/gdb.exp (skip_hw_breakpoint_tests): Add arm*-*-* target.
+	(skip_hw_watchpoint_tests): Likewise.
+	(skip_hw_watchpoint_multi_tests): Likewise.
+
+	2011-02-21  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/
+	* breakpoint.c (update_watchpoint): Do not attempt to recreate
+	per-frame locations while within a function epilogue.
+
+	2011-02-21  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/testsuite/
+	* lib/gdb.exp (skip_hw_breakpoint_tests): New procedure.
+	(skip_hw_watchpoint_tests): Likewise.
+	(skip_hw_watchpoint_multi_tests): Likewise.
+	(skip_hw_watchpoint_access_tests): Likewise.
+
+	* gdb.base/hbreak.exp: Use appropriate skip_hw_..._tests checks.
+	* gdb.base/pr11022.exp: Likewise.
+	* gdb.base/watch-read.exp: Likewise.
+	* gdb.base/watch_thread_num.exp: Likewise.
+	* gdb.base/watchpoint-hw-hit-once.exp: Likewise.
+	* gdb.base/watchpoint-hw.exp: Likewise.
+	* gdb.threads/local-watch-wrong-thread.exp: Likewise.
+	* gdb.threads/watchthreads-reorder.exp: Likewise.
+	* gdb.threads/watchthreads.exp: Likewise.
+	* gdb.threads/watchthreads2.exp: Likewise.
+
+2011-02-04  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* version.in: Bump version.
+
+2011-02-04  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	GDB Linaro 7.2-2011.02-0 released.
+
+	gdb/
+	* version.in: Update.
+
+2011-02-04  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Fix LP #711375
+	Backport from mainline:
+
+	2011-02-04  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* dwarf2read.c (dwarf2_ranges_read): Skip empty range entries.
+	Complain about inverted range entries.
+	(dwarf2_record_block_ranges): Likewise.
+
+2011-02-03  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Fix LP #616000
+	Backport from mainline:
+
+	2011-02-03  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* arm-tdep.c (arm_skip_stack_protector): Accept any symbol that
+	starts with __stack_chk_guard as stack guard symbol.
+
+2011-02-03  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Fix LP #661253
+	Backport from mainline:
+
+	2011-02-02  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* arm-tdep.c (skip_prologue_function): Add GDBARCH and IS_THUMB
+	arguments.  Skip in-prologue calls to glibc __aeabi_read_tp
+	implementation even if no symbols are available.
+	(thumb_analyze_prologue): Update call to skip_prologue_function.
+	(arm_analyze_prologue): Likewise.
+
+	2011-02-02  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* arm-tdep.c: Include "observer.h".
+	(arm_prologue_this_id): Use frame PC if get_frame_func returns 0.
+	(arm_exidx_data_key): New static variable.
+	(struct arm_exidx_entry, arm_exidx_entry_s): New data types.
+	(struct arm_exidx_data): Likewise.
+	(arm_exidx_data_free): New function.
+	(arm_compare_exidx_entries): Likewise.
+	(arm_obj_section_from_vma): Likewise.
+	(arm_exidx_new_objfile): Likewise.
+	(arm_find_exidx_entry): Likewise.
+	(arm_exidx_fill_cache): Likewise.
+	(arm_exidx_unwind_sniffer): Likewise.
+	(arm_exidx_unwind): New global variable.
+	(arm_gdbarch_init): Append unwinder arm_exidx_unwind.
+	(_initialize_arm_tdep): Attach arm_exidx_new_objfile to new_objfile
+	observer.  Register arm_exidx_data_key as objfile data.
+
+2011-02-03  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Fix LP #685494
+	Backport from mainline:
+
+	2011-01-19  Yao Qi  <yao@codesourcery.com>
+
+	gdb/testsuite/
+	* lib/dwarf.exp (dwarf2_support): Change supported targets to a
+	positve list.
+
+	2011-01-19  Yao Qi  <yao@codesourcery.com>
+
+	gdb/testsuite/
+	* gdb.asm/asm-source.exp: Replace ARM target triplet with a
+	canonical form.
+	Remove "xscale-*-*"
+	* gdb.xml/tdesc-regs.exp: Likewise.
+	* gdb.python/py-section-script.exp: Replace ARM target triplet
+	with canonical form.
+	Match arm*-*-symbianelf*.
+	* gdb.base/dup-sect.exp: Likewise.
+	* lib/dwarf.exp: New.
+	* gdb.dwarf2/callframecfa.exp: Check dwarf2 support by routine
+	dwarf2_support.
+	* gdb.dwarf2/dup-psym.exp: Likewise.
+	* gdb.dwarf2/dw2-anonymous-func.exp: Likewise.
+	* gdb.dwarf2/dw2-bad-parameter-type.exp: Likewise.
+	* gdb.dwarf2/dw2-basic.exp: Likewise.
+	* gdb.dwarf2/dw2-compressed.exp: Likewise.
+	* gdb.dwarf2/dw2-cu-size.exp: Likewise.
+	* gdb.dwarf2/dw2-empty-namespace.exp: Likewise.
+	* gdb.dwarf2/dw2-inheritance.exp: Likewise.
+	* gdb.dwarf2/dw2-intercu.exp: Likewise.
+	* gdb.dwarf2/dw2-intermix.exp: Likewise.
+	* gdb.dwarf2/dw2-modula2-self-type.exp: Likewise.
+	* gdb.dwarf2/dw2-noloc.exp: Likewise.
+	* gdb.dwarf2/dw2-op-call.exp: Likewise.
+	* gdb.dwarf2/dw2-producer.exp: Likewise.
+	* gdb.dwarf2/dw2-ranges.exp: Likewise.
+	* gdb.dwarf2/dw2-ref-missing-frame.exp: Likewise.
+	* gdb.dwarf2/dw2-strp.exp: Likewise.
+	* gdb.dwarf2/dw2-unresolved.exp: Likewise.
+	* gdb.dwarf2/mac-fileno.exp: Likewise.
+	* gdb.dwarf2/member-ptr-forwardref.exp: Likewise.
+	* gdb.dwarf2/pieces.exp: Likewise.
+	* gdb.dwarf2/valop.exp: Likewise.
+	* gdb.dwarf2/watch-notconst.exp: Likewise.
+
+2011-02-03  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	Backport from mainline:
+
+	2011-02-02  Ulrich Weigand  <ulrich.weigand@linaro.org>
+
+	gdb/
+	* arm-tdep.c (arm_analyze_load_stack_chk_guard): Avoid build break
+	due to accessing uninitialized variable.  Fix indentation.
+
+2011-01-14  Yao Qi  <yao@codesourcery.com>
+
+	Fix the first fail in LP #615972
+	Backport from mainline:
+
+	2011-01-14  Yao Qi  <yao@codesourcery.com>
+
+	gdb/
+	* arm-tdep.c (arm_register_reggroup_p): FPS register is in
+	save_reggroup, restore_reggroup and all_reggroup.
+
+	2010-12-20  Yao Qi  <yao@codesourcery.com>
+
+	gdb/
+	* arm-tdep.c (arm_register_reggroup_p): New.
+	(arm_gdbarch_init): Set arm_register_reggroup_p for hook
+	register_reggroup_p.
+
+	2010-12-20  Yao Qi  <yao@codesourcery.com>
+
+	gdb/
+	* features/arm-core.xml:  Add attribute type to reg from r0 to r12.
+	* features/arm-with-iwmmxt.c: Regenerate.
+	* features/arm-with-neon.c: Regenerate.
+	* features/arm-with-vfpv2.c: Regenerate.
+	* features/arm-with-vfpv3.c: Regenerate.
+
+2010-12-29  Yao Qi  <yao@codesourcery.com>
+
+	Backport from mainline.  Fix LP:616003.
+
+	gdb/
+	2010-12-23  Yao Qi  <yao@codesourcery.com>
+	* arm-tdep.c (arm_gdbarch_init): Remove invoke to
+	set_gdbarch_deprecated_fp_regnum.
+
+2010-12-27  Yao Qi  <yao@codesourcery.com>
+
+	Handle -fstack-protector prologue code.  Fix LP:616000
+	Backport from mainline:
+
+	2010-12-23  Yao Qi  <yao@codesourcery.com>
+
+	gdb/
+	* arm-tdep.c (thumb_analyze_prologue): Move some code ...
+	(EXTRACT_MOVW_MOVT_IMM_T): ... here.  New macro.
+	(EXTRACT_MOVW_MOVT_IMM_A): New macro.
+	(arm_analyze_load_stack_chk_guard): New.
+	(arm_skip_stack_protector): New.
+	(arm_skip_prologue): Adjust post_prologue_pc by
+	arm_skip_stack_protector.
+
+2010-12-14  Yao Qi  <yao@codesourcery.com>
+
+	Merge from FSF GDB 7.2.  Fix LP:685702.
+
+	gdb/testsuite/
+	2010-12-14  Yao Qi  <yao@codesourcery.com>
+	Backport from mainline:
+
+	2010-09-02  Jan Kratochvil  <jan.kratochvil@redhat.com>
+	* gdb.base/printcmds.exp (test_float_accepted): Import gdb_prompt.
+	Move here, negate and extend by XFAIL the "p 0x1.1" test from ... 
+	* (test_float_rejected): ... here.
+
+2010-11-08  Michael Hope  <michael.hope@linaro.org>
+
+        gdb/
+        * version.in: Bump version.
+
+2010-11-08  Michael Hope  <michael.hope@linaro.org>
+
+        GDB Linaro 7.2-2010.11-0 released.
+
+        gdb/
+        * version.in: Update.
+
+2010-10-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #663542
+	Backport from mainline:
+
+	2010-10-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/
+	* arm-tdep.c (thumb_get_next_pc_raw): Handle Thumb-16 encoding
+	for "mov pc, REG" as well.
+	(thumb_instruction_changes_pc): Likewise.
+
+2010-10-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #663539
+	Backport from mainline:
+
+	2010-10-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/testsuite/
+	* gdb.base/watch_thread_num.exp: Revert 2008-09-03 change.
+	Skip test completely if gdb,no_hardware_watchpoints.
+
+2010-10-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #663537
+	Backport from mainline:
+
+	2010-10-19  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/testsuite/
+	* gdb.base/foll-fork.exp: Make regexps to match catchpoint hits more
+	strict, but do not check for any particular function name within libc.
+
+2010-10-15  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #615984
+	Backport from mainline:
+
+	2010-10-12  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	* gdb.base/break-interp.exp (test_ld): Replace gdb_expect by
+	gdb_test_multiple.
+
+	2010-10-12  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/testsuite/
+	* break-interp.exp (test_ld): Use two separate gdb_expect statements
+	for the "info files" test to avoid timeouts on slow machines.
+
+	2010-10-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	gdb/testsuite/
+	Fix missing _start PIE relocation on ppc64 due to stop on dl_main.
+	* break-interp.exp (reach): Move the core body ...
+	(reach_1): ... here.  Use stop-on-solib-events for _dl_debug_state.
+	(test_ld): Provide always real argument, even to the linker.  Replace
+	dl_main by _dl_debug_state.
+
+	2010-10-11  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	gdb/testsuite/
+	Fix results of prelinked PIEs on ppc*.
+	* gdb.base/break-interp.exp (reach, test_core, test_attach_gdb):
+	Accept also DISPLACEMENT "PRESENT".
+	(main): Replace "ZERO" displacements by "PRESENT".
+
+	2010-09-10  Edjunior Barbosa Machado  <emachado@linux.vnet.ibm.com>
+
+	gdb/testsuite/
+	* gdb.base/break-interp.exp (test_ld) <istarget powerpc64-*>: Add
+	is_lp64_target to check 64bit target.
+
+	2010-09-09  Jan Kratochvil  <jan.kratochvil@redhat.com>
+
+	gdb/testsuite/
+	* gdb.base/break-interp.exp (reach): Permit leading . for ppc64.
+	(test_ld) <powerpc64-*>: New.
+
+2010-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/
+	* version.in: Bump version.
+
+2010-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	GDB Linaro 7.2-2010.10-0 released.
+
+	gdb/
+	* version.in: Update.
+
+2010-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #523959
+	Backport from mainline:
+
+	2010-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+	gdb/
+	* arm-tdep.c (thumb_expand_immediate): New function.
+	(thumb_instruction_changes_pc): Likewise.
+	(thumb2_instruction_changes_pc): Likewise.
+	(thumb_analyze_prologue): Handle 32-bit Thumb instructions during
+	prologue parsing.  Improved support for optimized code.
+	(thumb_scan_prologue): Do not reply on line-number information,
+	use same heuristics as arm_scan_prologue insead.
+	(skip_prologue_function): Accept functions
+	"__tls_get_addr" and "__aeabi_read_tp".
+
+2010-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #615982
+	Backport from mainline:
+
+	2010-10-08  Ulrich Weigand  <uweigand@de.ibm.com>
+		    Daniel Jacobowitz  <dan@codesourcery.com>
+	gdb/
+	* arm-tdep.c (thumb_in_function_epilogue_p)
+	(arm_in_function_epilogue_p): New.
+	(arm_gdbarch_init): Install arm_in_function_epilogue_p as
+	gdbarch_in_function_epilogue_p callback.
+
+2010-10-06  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Backport from mainline:
+
+	2010-08-20  Maciej W. Rozycki  <macro@codesourcery.com>
+
+	libiberty/
+	* pex-common.c (pex_read_err): Set stderr_pipe to -1 if a
+	corresponding stream has been opened.
+	(pex_free): Close pipe file descriptors corresponding to child's
+	stdout and stderr before waiting.
+
+2010-09-22  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	* src-release: Support gdb-linaro packages.
+
+	gdb/
+	* version.in: Set to Linaro GDB version number.
+
+	* configure.ac (PKGVERSION, BUGURL): Refer to Linaro.
+	* configure: Regenerate.
+
+	gdb/gdbserver/
+	* configure.ac (PKGVERSION, BUGURL): Refer to Linaro.
+	* configure: Regenerate.
+
+	gdb/doc/
+	* configure.ac (PKGVERSION, BUGURL): Refer to Linaro.
+	* configure: Regenerate.
+
+2010-09-14  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #620595
+	Backport from mainline:
+
+	2010-09-08  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	gdb/testsuite/
+	* gdb.threads/threxit-hop-specific.exp: Use "continue" instead
+	of "next" to proceed over pthread_exit call.
+
+2010-09-14  Ulrich Weigand  <uweigand@de.ibm.com>
+
+	Fix LP #615988
+	Backport from mainline:
+
+	2010-09-09  Ulrich Weigand  <uweigand@de.ibm.com>
+	gdb/
+	* dwarf2read.c (fixup_partial_die): Do not set dummy name for
+	anonymous class partial DIEs.
+
+	2010-09-08  Ulrich Weigand  <uweigand@de.ibm.com>
+	gdb/testsuite/
+	* gdb.base/maint.exp: Avoid wildcards against potentially very long
+	"maint print statistics" output to prevent expect timeouts.
+
+2010-09-10  Yao Qi  <yao@codesourcery.com>
+
+	Fix LP:#615995.
+	Backport from mainline:
+	
+	2010-09-08  Yao Qi  <yao@codesourcery.com>              
+      		Pedro Alves  <pedro@codesourery.com>
+	
+	* infrun.c (resume): When inferior is waiting_for_vfork_done,
+	clear step and don't use displaced stepping.
+        Extend comment on ignoring single-step requests on vfork
+	parents waiting for a vfork-done.
+

=== modified file 'gdb/arm-linux-nat.c'
--- a/gdb/arm-linux-nat.c	2010-04-12 13:52:38 +0000
+++ b/gdb/arm-linux-nat.c	2011-02-21 15:28:17 +0000
@@ -26,6 +26,8 @@
 #include "linux-nat.h"
 #include "target-descriptions.h"
 #include "auxv.h"
+#include "observer.h"
+#include "gdbthread.h"
 
 #include "arm-tdep.h"
 #include "arm-linux-tdep.h"
@@ -61,6 +63,11 @@
 #define PTRACE_SETVFPREGS 28
 #endif
 
+#ifndef PTRACE_GETHBPREGS
+#define PTRACE_GETHBPREGS 29
+#define PTRACE_SETHBPREGS 30
+#endif
+
 /* These are in <asm/elf.h> in current kernels.  */
 #define HWCAP_VFP       64
 #define HWCAP_IWMMXT    512
@@ -735,6 +742,564 @@
   return NULL;
 }
 
+/* Information describing the hardware breakpoint capabilities.  */
+struct arm_linux_hwbp_cap
+{
+  gdb_byte arch;
+  gdb_byte max_wp_length;
+  gdb_byte wp_count;
+  gdb_byte bp_count;
+};
+
+/* Get hold of the Hardware Breakpoint information for the target we are
+   attached to.  Returns NULL if the kernel doesn't support Hardware 
+   breakpoints at all, or a pointer to the information structure.  */
+static const struct arm_linux_hwbp_cap *
+arm_linux_get_hwbp_cap (void)
+{
+  /* The info structure we return.  */
+  static struct arm_linux_hwbp_cap info;
+
+  /* Is INFO in a good state?  -1 means that no attempt has been made to
+     initialize INFO; 0 means an attempt has been made, but it failed; 1
+     means INFO is in an initialized state.  */
+  static int available = -1;
+
+  if (available == -1)
+    {
+      int tid;
+      unsigned int val;
+
+      tid = GET_THREAD_ID (inferior_ptid);
+      if (ptrace (PTRACE_GETHBPREGS, tid, 0, &val) < 0)
+	available = 0;
+      else
+	{
+	  info.arch = (gdb_byte)((val >> 24) & 0xff);
+	  info.max_wp_length = (gdb_byte)((val >> 16) & 0xff);
+	  info.wp_count = (gdb_byte)((val >> 8) & 0xff);
+	  info.bp_count = (gdb_byte)(val & 0xff);
+	  available = (info.arch != 0);
+	}
+    }
+
+  return available == 1 ? &info : NULL;
+}
+
+/* How many hardware breakpoints are available?  */
+static int
+arm_linux_get_hw_breakpoint_count (void)
+{
+  const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
+  return cap != NULL ? cap->bp_count : 0;
+}
+
+/* How many hardware watchpoints are available?  */
+static int
+arm_linux_get_hw_watchpoint_count (void)
+{
+  const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
+  return cap != NULL ? cap->wp_count : 0;
+}
+
+/* Have we got a free break-/watch-point available for use?  Returns -1 if
+   there is not an appropriate resource available, otherwise returns 1.  */
+static int
+arm_linux_can_use_hw_breakpoint (int type, int cnt, int ot)
+{
+  if (type == bp_hardware_watchpoint || type == bp_read_watchpoint
+      || type == bp_access_watchpoint || type == bp_watchpoint)
+    {
+      if (cnt + ot > arm_linux_get_hw_watchpoint_count ())
+	return -1;
+    }
+  else if (type == bp_hardware_breakpoint)
+    {
+      if (cnt > arm_linux_get_hw_breakpoint_count ())
+	return -1;
+    }
+  else
+    gdb_assert (FALSE);
+
+  return 1;
+}
+
+/* Enum describing the different types of ARM hardware break-/watch-points.  */
+typedef enum
+{
+  arm_hwbp_break = 0,
+  arm_hwbp_load = 1,
+  arm_hwbp_store = 2,
+  arm_hwbp_access = 3
+} arm_hwbp_type;
+
+/* Type describing an ARM Hardware Breakpoint Control register value.  */
+typedef unsigned int arm_hwbp_control_t;
+
+/* Structure used to keep track of hardware break-/watch-points.  */
+struct arm_linux_hw_breakpoint
+{
+  /* Address to break on, or being watched.  */
+  unsigned int address;
+  /* Control register for break-/watch- point.  */
+  arm_hwbp_control_t control;
+};
+
+/* Structure containing arrays of the break and watch points which are have
+   active in each thread.
+
+   The Linux ptrace interface to hardware break-/watch-points presents the 
+   values in a vector centred around 0 (which is used fo generic information).
+   Positive indicies refer to breakpoint addresses/control registers, negative
+   indices to watchpoint addresses/control registers.
+
+   The Linux vector is indexed as follows:
+      -((i << 1) + 2): Control register for watchpoint i.
+      -((i << 1) + 1): Address register for watchpoint i.
+                    0: Information register.
+       ((i << 1) + 1): Address register for breakpoint i.
+       ((i << 1) + 2): Control register for breakpoint i.
+
+   This structure is used as a per-thread cache of the state stored by the 
+   kernel, so that we don't need to keep calling into the kernel to find a 
+   free breakpoint.
+
+   We treat break-/watch-points with their enable bit clear as being deleted.
+   */
+typedef struct arm_linux_thread_points
+{
+  /* Thread ID.  */
+  int tid;
+  /* Breakpoints for thread.  */
+  struct arm_linux_hw_breakpoint *bpts;
+  /* Watchpoint for threads.  */
+  struct arm_linux_hw_breakpoint *wpts;
+} *arm_linux_thread_points_p;
+DEF_VEC_P (arm_linux_thread_points_p);
+
+/* Vector of hardware breakpoints for each thread.  */
+VEC(arm_linux_thread_points_p) *arm_threads = NULL;
+
+/* Find the list of hardware break-/watch-points for a thread with id TID.
+   If no list exists for TID we return NULL if ALLOC_NEW is 0, otherwise we
+   create a new list and return that.  */
+static struct arm_linux_thread_points *
+arm_linux_find_breakpoints_by_tid (int tid, int alloc_new)
+{
+  int i;
+  struct arm_linux_thread_points *t;
+
+  for (i = 0; VEC_iterate (arm_linux_thread_points_p, arm_threads, i, t); ++i)
+    {
+      if (t->tid == tid)
+	return t;
+    }
+
+  t = NULL;
+
+  if (alloc_new)
+    {
+      t = xmalloc (sizeof (struct arm_linux_thread_points));
+      t->tid = tid;
+      t->bpts = xzalloc (arm_linux_get_hw_breakpoint_count ()
+			 * sizeof (struct arm_linux_hw_breakpoint));
+      t->wpts = xzalloc (arm_linux_get_hw_watchpoint_count ()
+			 * sizeof (struct arm_linux_hw_breakpoint));
+      VEC_safe_push (arm_linux_thread_points_p, arm_threads, t);
+    }
+
+  return t;
+}
+
+/* Initialize an ARM hardware break-/watch-point control register value.
+   BYTE_ADDRESS_SELECT is the mask of bytes to trigger on; HWBP_TYPE is the 
+   type of break-/watch-point; ENABLE indicates whether the point is enabled.
+   */
+static arm_hwbp_control_t 
+arm_hwbp_control_initialize (unsigned byte_address_select,
+			     arm_hwbp_type hwbp_type,
+			     int enable)
+{
+  gdb_assert ((byte_address_select & ~0xffU) == 0);
+  gdb_assert (hwbp_type != arm_hwbp_break 
+	      || ((byte_address_select & 0xfU) != 0));
+
+  return (byte_address_select << 5) | (hwbp_type << 3) | (3 << 1) | enable;
+}
+
+/* Does the breakpoint control value CONTROL have the enable bit set?  */
+static int
+arm_hwbp_control_is_enabled (arm_hwbp_control_t control)
+{
+  return control & 0x1;
+}
+
+/* Change a breakpoint control word so that it is in the disabled state.  */
+static arm_hwbp_control_t
+arm_hwbp_control_disable (arm_hwbp_control_t control)
+{
+  return control & ~0x1;
+}
+
+/* Initialise the hardware breakpoint structure P.  The breakpoint will be
+   enabled, and will point to the placed address of BP_TGT.  */
+static void
+arm_linux_hw_breakpoint_initialize (struct gdbarch *gdbarch,
+				    struct bp_target_info *bp_tgt,
+				    struct arm_linux_hw_breakpoint *p)
+{
+  unsigned mask;
+  CORE_ADDR address = bp_tgt->placed_address;
+
+  /* We have to create a mask for the control register which says which bits
+     of the word pointed to by address to break on.  */
+  if (arm_pc_is_thumb (address))
+    mask = 0x3 << (address & 2);
+  else
+    mask = 0xf;
+
+  p->address = (unsigned int) (address & ~3);
+  p->control = arm_hwbp_control_initialize (mask, arm_hwbp_break, 1);
+}
+
+/* Get the ARM hardware breakpoint type from the RW value we're given when
+   asked to set a watchpoint.  */
+static arm_hwbp_type 
+arm_linux_get_hwbp_type (int rw)
+{
+  if (rw == hw_read)
+    return arm_hwbp_load;
+  else if (rw == hw_write)
+    return arm_hwbp_store;
+  else
+    return arm_hwbp_access;
+}
+
+/* Initialize the hardware breakpoint structure P for a watchpoint at ADDR
+   to LEN.  The type of watchpoint is given in RW.  */
+static void
+arm_linux_hw_watchpoint_initialize (CORE_ADDR addr, int len, int rw,
+				    struct arm_linux_hw_breakpoint *p)
+{
+  const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
+  unsigned mask;
+
+  gdb_assert (cap != NULL);
+  gdb_assert (cap->max_wp_length != 0);
+
+  mask = (1 << len) - 1;
+
+  p->address = (unsigned int) addr;
+  p->control = arm_hwbp_control_initialize (mask, 
+					    arm_linux_get_hwbp_type (rw), 1);
+}
+
+/* Are two break-/watch-points equal?  */
+static int
+arm_linux_hw_breakpoint_equal (const struct arm_linux_hw_breakpoint *p1,
+			       const struct arm_linux_hw_breakpoint *p2)
+{
+  return p1->address == p2->address && p1->control == p2->control;
+}
+
+/* Insert the hardware breakpoint (WATCHPOINT = 0) or watchpoint (WATCHPOINT
+   =1) BPT for thread TID.  */
+static void
+arm_linux_insert_hw_breakpoint1 (const struct arm_linux_hw_breakpoint* bpt, 
+				int tid, int watchpoint)
+{
+  struct arm_linux_thread_points *t = arm_linux_find_breakpoints_by_tid (tid, 1);
+  gdb_byte count, i;
+  struct arm_linux_hw_breakpoint* bpts;
+  int dir;
+
+  gdb_assert (t != NULL);
+
+  if (watchpoint)
+    {
+      count = arm_linux_get_hw_watchpoint_count ();
+      bpts = t->wpts;
+      dir = -1;
+    }
+  else
+    {
+      count = arm_linux_get_hw_breakpoint_count ();
+      bpts = t->bpts;
+      dir = 1;
+    }
+
+  for (i = 0; i < count; ++i)
+    if (!arm_hwbp_control_is_enabled (bpts[i].control))
+      {
+	errno = 0;
+	if (ptrace (PTRACE_SETHBPREGS, tid, dir * ((i << 1) + 1), 
+		    &bpt->address) < 0)
+	  perror_with_name (_("Unexpected error setting breakpoint address"));
+	if (ptrace (PTRACE_SETHBPREGS, tid, dir * ((i << 1) + 2), 
+		    &bpt->control) < 0)
+	  perror_with_name (_("Unexpected error setting breakpoint"));
+
+	memcpy (bpts + i, bpt, sizeof (struct arm_linux_hw_breakpoint));
+	break;
+      }
+
+  gdb_assert (i != count);
+}
+
+/* Remove the hardware breakpoint (WATCHPOINT = 0) or watchpoint
+   (WATCHPOINT = 1) BPT for thread TID.  */
+static void
+arm_linux_remove_hw_breakpoint1 (const struct arm_linux_hw_breakpoint *bpt, 
+				 int tid, int watchpoint)
+{
+  struct arm_linux_thread_points *t = arm_linux_find_breakpoints_by_tid (tid, 0);
+  gdb_byte count, i;
+  struct arm_linux_hw_breakpoint *bpts;
+  int dir;
+
+  gdb_assert (t != NULL);
+
+  if (watchpoint)
+    {
+      count = arm_linux_get_hw_watchpoint_count ();
+      bpts = t->wpts;
+      dir = -1;
+    }
+  else
+    {
+      count = arm_linux_get_hw_breakpoint_count ();
+      bpts = t->bpts;
+      dir = 1;
+    }
+
+  for (i = 0; i < count; ++i)
+    if (arm_linux_hw_breakpoint_equal (bpt, bpts + i))
+      {
+	errno = 0;
+	bpts[i].control = arm_hwbp_control_disable (bpts[i].control);
+	if (ptrace (PTRACE_SETHBPREGS, tid, dir * ((i << 1) + 2), 
+		    &bpts[i].control) < 0)
+	  perror_with_name (_("Unexpected error clearing breakpoint"));
+	break;
+      }
+
+  gdb_assert (i != count);
+}
+
+/* Insert a Hardware breakpoint.  */
+static int
+arm_linux_insert_hw_breakpoint (struct gdbarch *gdbarch, 
+				struct bp_target_info *bp_tgt)
+{
+  ptid_t ptid;
+  struct lwp_info *lp;
+  struct arm_linux_hw_breakpoint p;
+
+  if (arm_linux_get_hw_breakpoint_count () == 0)
+    return -1;
+
+  arm_linux_hw_breakpoint_initialize (gdbarch, bp_tgt, &p);
+  ALL_LWPS (lp, ptid)
+    arm_linux_insert_hw_breakpoint1 (&p, TIDGET (ptid), 0);
+
+  return 0;
+}
+
+/* Remove a hardware breakpoint.  */
+static int
+arm_linux_remove_hw_breakpoint (struct gdbarch *gdbarch, 
+				struct bp_target_info *bp_tgt)
+{
+  ptid_t ptid;
+  struct lwp_info *lp;
+  struct arm_linux_hw_breakpoint p;
+
+  if (arm_linux_get_hw_breakpoint_count () == 0)
+    return -1;
+
+  arm_linux_hw_breakpoint_initialize (gdbarch, bp_tgt, &p);
+  ALL_LWPS (lp, ptid)
+    arm_linux_remove_hw_breakpoint1 (&p, TIDGET (ptid), 0);
+
+  return 0;
+}
+
+/* Are we able to use a hardware watchpoint for the LEN bytes starting at 
+   ADDR?  */
+static int
+arm_linux_region_ok_for_hw_watchpoint (CORE_ADDR addr, int len)
+{
+  const struct arm_linux_hwbp_cap *cap = arm_linux_get_hwbp_cap ();
+  CORE_ADDR max_wp_length, aligned_addr;
+
+  /* Can not set watchpoints for zero or negative lengths.  */
+  if (len <= 0)
+    return 0;
+
+  /* Need to be able to use the ptrace interface.  */
+  if (cap == NULL || cap->wp_count == 0)
+    return 0;
+
+  /* Test that the range [ADDR, ADDR + LEN) fits into the largest address
+     range covered by a watchpoint.  */
+  max_wp_length = (CORE_ADDR)cap->max_wp_length;
+  aligned_addr = addr & ~(max_wp_length - 1);
+
+  if (aligned_addr + max_wp_length < addr + len)
+    return 0;
+
+  /* The current ptrace interface can only handle watchpoints that are a
+     power of 2.  */
+  if ((len & (len - 1)) != 0)
+    return 0;
+
+  /* All tests passed so we must be able to set a watchpoint.  */
+  return 1;
+}
+
+/* Insert a Hardware breakpoint.  */
+static int
+arm_linux_insert_watchpoint (CORE_ADDR addr, int len, int rw,
+			     struct expression *cond)
+{
+  ptid_t ptid;
+  struct lwp_info *lp;
+  struct arm_linux_hw_breakpoint p;
+
+  if (arm_linux_get_hw_watchpoint_count () == 0)
+    return -1;
+
+  arm_linux_hw_watchpoint_initialize (addr, len, rw, &p);
+  ALL_LWPS (lp, ptid)
+    arm_linux_insert_hw_breakpoint1 (&p, TIDGET (ptid), 1);
+
+  return 0;
+}
+
+/* Remove a hardware breakpoint.  */
+static int
+arm_linux_remove_watchpoint (CORE_ADDR addr, int len, int rw,
+			     struct expression *cond)
+{
+  ptid_t ptid;
+  struct lwp_info *lp;
+  struct arm_linux_hw_breakpoint p;
+
+  if (arm_linux_get_hw_watchpoint_count () == 0)
+    return -1;
+
+  arm_linux_hw_watchpoint_initialize (addr, len, rw, &p);
+  ALL_LWPS (lp, ptid)
+    arm_linux_remove_hw_breakpoint1 (&p, TIDGET (ptid), 1);
+
+  return 0;
+}
+
+/* What was the data address the target was stopped on accessing.  */
+static int
+arm_linux_stopped_data_address (struct target_ops *target, CORE_ADDR *addr_p)
+{
+  struct siginfo *siginfo_p = linux_nat_get_siginfo (inferior_ptid);
+  int slot = siginfo_p->si_errno;
+
+  /* This must be a hardware breakpoint.  */
+  if (siginfo_p->si_signo != SIGTRAP
+      || (siginfo_p->si_code & 0xffff) != 0x0004 /* TRAP_HWBKPT */)
+    return 0;
+
+  /* We must be able to set hardware watchpoints.  */
+  if (arm_linux_get_hw_watchpoint_count () == 0)
+    return 0;
+
+  /* If we are in a positive slot then we're looking at a breakpoint and not
+     a watchpoint.  */
+  if (slot >= 0)
+    return 0;
+
+  *addr_p = (CORE_ADDR) (uintptr_t) siginfo_p->si_addr;
+  return 1;
+}
+
+/* Has the target been stopped by hitting a watchpoint?  */
+static int
+arm_linux_stopped_by_watchpoint (void)
+{
+  CORE_ADDR addr;
+  return arm_linux_stopped_data_address (&current_target, &addr);
+}
+
+static int
+arm_linux_watchpoint_addr_within_range (struct target_ops *target,
+					CORE_ADDR addr,
+					CORE_ADDR start, int length)
+{
+  return start <= addr && start + length - 1 >= addr;
+}
+
+/* Handle thread creation.  We need to copy the breakpoints and watchpoints
+   in the parent thread to the child thread.  */
+static void
+arm_linux_new_thread (ptid_t ptid)
+{
+  int tid = TIDGET (ptid);
+  const struct arm_linux_hwbp_cap *info = arm_linux_get_hwbp_cap ();
+
+  if (info != NULL)
+    {
+      int i;
+      struct arm_linux_thread_points *p;
+      struct arm_linux_hw_breakpoint *bpts;
+
+      if (VEC_empty (arm_linux_thread_points_p, arm_threads))
+	return;
+
+      /* Get a list of breakpoints from any thread. */
+      p = VEC_last (arm_linux_thread_points_p, arm_threads);
+
+      /* Copy that thread's breakpoints and watchpoints to the new thread. */
+      for (i = 0; i < info->bp_count; i++)
+	if (arm_hwbp_control_is_enabled (p->bpts[i].control))
+	  arm_linux_insert_hw_breakpoint1 (p->bpts + i, tid, 0);
+      for (i = 0; i < info->wp_count; i++)
+	if (arm_hwbp_control_is_enabled (p->wpts[i].control))
+	  arm_linux_insert_hw_breakpoint1 (p->wpts + i, tid, 1);
+    }
+}
+
+/* Handle thread exit.  Tidy up the memory that has been allocated for the
+   thread.  */
+static void
+arm_linux_thread_exit (struct thread_info *tp, int silent)
+{
+  const struct arm_linux_hwbp_cap *info = arm_linux_get_hwbp_cap ();
+
+  if (info != NULL)
+    {
+      int i;
+      int tid = TIDGET (tp->ptid);
+      struct arm_linux_thread_points *t = NULL, *p;
+
+      for (i = 0; 
+	   VEC_iterate (arm_linux_thread_points_p, arm_threads, i, p); i++)
+	{
+	  if (p->tid == tid)
+	    {
+	      t = p;
+	      break;
+	    }
+	}
+
+      if (t == NULL)
+	return;
+
+      VEC_unordered_remove (arm_linux_thread_points_p, arm_threads, i);
+
+      xfree (t->bpts);
+      xfree (t->wpts);
+      xfree (t);
+    }
+}
+
 void _initialize_arm_linux_nat (void);
 
 void
@@ -751,8 +1316,23 @@
   t->to_fetch_registers = arm_linux_fetch_inferior_registers;
   t->to_store_registers = arm_linux_store_inferior_registers;
 
+  /* Add our hardware breakpoint and watchpoint implementation.  */
+  t->to_can_use_hw_breakpoint = arm_linux_can_use_hw_breakpoint;
+  t->to_insert_hw_breakpoint = arm_linux_insert_hw_breakpoint;
+  t->to_remove_hw_breakpoint = arm_linux_remove_hw_breakpoint;
+  t->to_region_ok_for_hw_watchpoint = arm_linux_region_ok_for_hw_watchpoint;
+  t->to_insert_watchpoint = arm_linux_insert_watchpoint;
+  t->to_remove_watchpoint = arm_linux_remove_watchpoint;
+  t->to_stopped_by_watchpoint = arm_linux_stopped_by_watchpoint;
+  t->to_stopped_data_address = arm_linux_stopped_data_address;
+  t->to_watchpoint_addr_within_range = arm_linux_watchpoint_addr_within_range;
+
   t->to_read_description = arm_linux_read_description;
 
   /* Register the target.  */
   linux_nat_add_target (t);
+
+  /* Handle thread creation and exit */
+  observer_attach_thread_exit (arm_linux_thread_exit);
+  linux_nat_set_new_thread (t, arm_linux_new_thread);
 }

=== modified file 'gdb/arm-linux-tdep.c'
--- a/gdb/arm-linux-tdep.c	2010-08-30 15:33:03 +0000
+++ b/gdb/arm-linux-tdep.c	2011-03-01 18:25:53 +0000
@@ -239,6 +239,7 @@
    whenever OABI support has been enabled in the kernel.  */
 #define ARM_OABI_SYSCALL_RESTART_SYSCALL 0xef900000
 #define ARM_LDR_PC_SP_12		0xe49df00c
+#define ARM_LDR_PC_SP_4			0xe49df004
 
 static void
 arm_linux_sigtramp_cache (struct frame_info *this_frame,
@@ -355,10 +356,35 @@
 				struct trad_frame_cache *this_cache,
 				CORE_ADDR func)
 {
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
   CORE_ADDR sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
-
-  trad_frame_set_reg_addr (this_cache, ARM_PC_REGNUM, sp);
-  trad_frame_set_reg_value (this_cache, ARM_SP_REGNUM, sp + 12);
+  CORE_ADDR pc = get_frame_memory_unsigned (this_frame, sp, 4);
+  CORE_ADDR cpsr = get_frame_register_unsigned (this_frame, ARM_PS_REGNUM);
+  int sp_offset;
+
+  /* There are two variants of this trampoline; with older kernels, the
+     stub is placed on the stack, while newer kernels use the stub from
+     the vector page.  They are identical except that the older version
+     increments SP by 12 (to skip stored PC and the stub itself), while
+     the newer version increments SP only by 4 (just the stored PC).  */
+  if (self->insn[1].bytes == ARM_LDR_PC_SP_4)
+    sp_offset = 4;
+  else
+    sp_offset = 12;
+
+  /* Update Thumb bit in CPSR.  */
+  if (pc & 1)
+    cpsr |= CPSR_T;
+  else
+    cpsr &= ~CPSR_T;
+
+  /* Remove Thumb bit from PC.  */
+  pc = gdbarch_addr_bits_remove (gdbarch, pc);
+
+  /* Save previous register values.  */
+  trad_frame_set_reg_value (this_cache, ARM_SP_REGNUM, sp + sp_offset);
+  trad_frame_set_reg_value (this_cache, ARM_PC_REGNUM, pc);
+  trad_frame_set_reg_value (this_cache, ARM_PS_REGNUM, cpsr);
 
   /* Save a frame ID.  */
   trad_frame_set_id (this_cache, frame_id_build (sp, func));
@@ -417,6 +443,17 @@
   arm_linux_restart_syscall_init
 };
 
+static struct tramp_frame arm_kernel_linux_restart_syscall_tramp_frame = {
+  NORMAL_FRAME,
+  4,
+  {
+    { ARM_OABI_SYSCALL_RESTART_SYSCALL, -1 },
+    { ARM_LDR_PC_SP_4, -1 },
+    { TRAMP_SENTINEL_INSN }
+  },
+  arm_linux_restart_syscall_init
+};
+
 /* Core file and register set support.  */
 
 #define ARM_LINUX_SIZEOF_GREGSET (18 * INT_REGISTER_SIZE)
@@ -1005,6 +1042,8 @@
 				&arm_eabi_linux_rt_sigreturn_tramp_frame);
   tramp_frame_prepend_unwinder (gdbarch,
 				&arm_linux_restart_syscall_tramp_frame);
+  tramp_frame_prepend_unwinder (gdbarch,
+				&arm_kernel_linux_restart_syscall_tramp_frame);
 
   /* Core file support.  */
   set_gdbarch_regset_from_core_section (gdbarch,

=== modified file 'gdb/arm-tdep.c'
--- a/gdb/arm-tdep.c	2010-08-30 15:33:03 +0000
+++ b/gdb/arm-tdep.c	2011-02-21 15:28:00 +0000
@@ -29,6 +29,7 @@
 #include "gdb_string.h"
 #include "dis-asm.h"		/* For register styles. */
 #include "regcache.h"
+#include "reggroups.h"
 #include "doublest.h"
 #include "value.h"
 #include "arch-utils.h"
@@ -42,6 +43,7 @@
 #include "prologue-value.h"
 #include "target-descriptions.h"
 #include "user-regs.h"
+#include "observer.h"
 
 #include "arm-tdep.h"
 #include "gdb/sim-arm.h"
@@ -346,7 +348,7 @@
    function.  This function should be called for addresses unrelated to
    any executing frame; otherwise, prefer arm_frame_is_thumb.  */
 
-static int
+int
 arm_pc_is_thumb (CORE_ADDR memaddr)
 {
   struct obj_section *sec;
@@ -430,33 +432,55 @@
 }
 
 /* Return 1 if PC is the start of a compiler helper function which
-   can be safely ignored during prologue skipping.  */
+   can be safely ignored during prologue skipping.  IS_THUMB is true
+   if the function is known to be a Thumb function due to the way it
+   is being called.  */
 static int
-skip_prologue_function (CORE_ADDR pc)
+skip_prologue_function (struct gdbarch *gdbarch, CORE_ADDR pc, int is_thumb)
 {
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
   struct minimal_symbol *msym;
-  const char *name;
 
   msym = lookup_minimal_symbol_by_pc (pc);
-  if (msym == NULL || SYMBOL_VALUE_ADDRESS (msym) != pc)
-    return 0;
-
-  name = SYMBOL_LINKAGE_NAME (msym);
-  if (name == NULL)
-    return 0;
-
-  /* The GNU linker's Thumb call stub to foo is named
-     __foo_from_thumb.  */
-  if (strstr (name, "_from_thumb") != NULL)
-    name += 2;
-
-  /* On soft-float targets, __truncdfsf2 is called to convert promoted
-     arguments to their argument types in non-prototyped
-     functions.  */
-  if (strncmp (name, "__truncdfsf2", strlen ("__truncdfsf2")) == 0)
-    return 1;
-  if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
-    return 1;
+  if (msym != NULL
+      && SYMBOL_VALUE_ADDRESS (msym) == pc
+      && SYMBOL_LINKAGE_NAME (msym) != NULL)
+    {
+      const char *name = SYMBOL_LINKAGE_NAME (msym);
+
+      /* The GNU linker's Thumb call stub to foo is named
+	 __foo_from_thumb.  */
+      if (strstr (name, "_from_thumb") != NULL)
+	name += 2;
+
+      /* On soft-float targets, __truncdfsf2 is called to convert promoted
+	 arguments to their argument types in non-prototyped
+	 functions.  */
+      if (strncmp (name, "__truncdfsf2", strlen ("__truncdfsf2")) == 0)
+	return 1;
+      if (strncmp (name, "__aeabi_d2f", strlen ("__aeabi_d2f")) == 0)
+	return 1;
+
+      /* Internal functions related to thread-local storage.  */
+      if (strncmp (name, "__tls_get_addr", strlen ("__tls_get_addr")) == 0)
+	return 1;
+      if (strncmp (name, "__aeabi_read_tp", strlen ("__aeabi_read_tp")) == 0)
+	return 1;
+    }
+  else
+    {
+      /* If we run against a stripped glibc, we may be unable to identify
+	 special functions by name.  Check for one important case,
+	 __aeabi_read_tp, by comparing the *code* against the default
+	 implementation (this is hand-written ARM assembler in glibc).  */
+
+      if (!is_thumb
+	  && read_memory_unsigned_integer (pc, 4, byte_order_for_code)
+	     == 0xe3e00a0f /* mov r0, #0xffff0fff */
+	  && read_memory_unsigned_integer (pc + 4, 4, byte_order_for_code)
+	     == 0xe240f01f) /* sub pc, r0, #31 */
+	return 1;
+    }
 
   return 0;
 }
@@ -470,6 +494,167 @@
 #define BranchDest(addr,instr) \
   ((CORE_ADDR) (((long) (addr)) + 8 + (sbits (instr, 0, 23) << 2)))
 
+/* Extract the immediate from instruction movw/movt of encoding T.  INSN1 is
+   the first 16-bit of instruction, and INSN2 is the second 16-bit of
+   instruction.  */
+#define EXTRACT_MOVW_MOVT_IMM_T(insn1, insn2) \
+  ((bits ((insn1), 0, 3) << 12)               \
+   | (bits ((insn1), 10, 10) << 11)           \
+   | (bits ((insn2), 12, 14) << 8)            \
+   | bits ((insn2), 0, 7))
+
+/* Extract the immediate from instruction movw/movt of encoding A.  INSN is
+   the 32-bit instruction.  */
+#define EXTRACT_MOVW_MOVT_IMM_A(insn) \
+  ((bits ((insn), 16, 19) << 12) \
+   | bits ((insn), 0, 11))
+
+/* Decode immediate value; implements ThumbExpandImmediate pseudo-op.  */
+
+static unsigned int
+thumb_expand_immediate (unsigned int imm)
+{
+  unsigned int count = imm >> 7;
+
+  if (count < 8)
+    switch (count / 2)
+      {
+      case 0:
+	return imm & 0xff;
+      case 1:
+	return (imm & 0xff) | ((imm & 0xff) << 16);
+      case 2:
+	return ((imm & 0xff) << 8) | ((imm & 0xff) << 24);
+      case 3:
+	return (imm & 0xff) | ((imm & 0xff) << 8)
+		| ((imm & 0xff) << 16) | ((imm & 0xff) << 24);
+      }
+
+  return (0x80 | (imm & 0x7f)) << (32 - count);
+}
+
+/* Return 1 if the 16-bit Thumb instruction INST might change
+   control flow, 0 otherwise.  */
+
+static int
+thumb_instruction_changes_pc (unsigned short inst)
+{
+  if ((inst & 0xff00) == 0xbd00)	/* pop {rlist, pc} */
+    return 1;
+
+  if ((inst & 0xf000) == 0xd000)	/* conditional branch */
+    return 1;
+
+  if ((inst & 0xf800) == 0xe000)	/* unconditional branch */
+    return 1;
+
+  if ((inst & 0xff00) == 0x4700)	/* bx REG, blx REG */
+    return 1;
+
+  if ((inst & 0xff87) == 0x4687)	/* mov pc, REG */
+    return 1;
+
+  if ((inst & 0xf500) == 0xb100)	/* CBNZ or CBZ.  */
+    return 1;
+
+  return 0;
+}
+
+/* Return 1 if the 32-bit Thumb instruction in INST1 and INST2
+   might change control flow, 0 otherwise.  */
+
+static int
+thumb2_instruction_changes_pc (unsigned short inst1, unsigned short inst2)
+{
+  if ((inst1 & 0xf800) == 0xf000 && (inst2 & 0x8000) == 0x8000)
+    {
+      /* Branches and miscellaneous control instructions.  */
+
+      if ((inst2 & 0x1000) != 0 || (inst2 & 0xd001) == 0xc000)
+	{
+	  /* B, BL, BLX.  */
+	  return 1;
+	}
+      else if (inst1 == 0xf3de && (inst2 & 0xff00) == 0x3f00)
+	{
+	  /* SUBS PC, LR, #imm8.  */
+	  return 1;
+	}
+      else if ((inst2 & 0xd000) == 0x8000 && (inst1 & 0x0380) != 0x0380)
+	{
+	  /* Conditional branch.  */
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  if ((inst1 & 0xfe50) == 0xe810)
+    {
+      /* Load multiple or RFE.  */
+
+      if (bit (inst1, 7) && !bit (inst1, 8))
+	{
+	  /* LDMIA or POP */
+	  if (bit (inst2, 15))
+	    return 1;
+	}
+      else if (!bit (inst1, 7) && bit (inst1, 8))
+	{
+	  /* LDMDB */
+	  if (bit (inst2, 15))
+	    return 1;
+	}
+      else if (bit (inst1, 7) && bit (inst1, 8))
+	{
+	  /* RFEIA */
+	  return 1;
+	}
+      else if (!bit (inst1, 7) && !bit (inst1, 8))
+	{
+	  /* RFEDB */
+	  return 1;
+	}
+
+      return 0;
+    }
+
+  if ((inst1 & 0xffef) == 0xea4f && (inst2 & 0xfff0) == 0x0f00)
+    {
+      /* MOV PC or MOVS PC.  */
+      return 1;
+    }
+
+  if ((inst1 & 0xff70) == 0xf850 && (inst2 & 0xf000) == 0xf000)
+    {
+      /* LDR PC.  */
+      if (bits (inst1, 0, 3) == 15)
+	return 1;
+      if (bit (inst1, 7))
+	return 1;
+      if (bit (inst2, 11))
+	return 1;
+      if ((inst2 & 0x0fc0) == 0x0000)
+	return 1;	
+
+      return 0;
+    }
+
+  if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf000)
+    {
+      /* TBB.  */
+      return 1;
+    }
+
+  if ((inst1 & 0xfff0) == 0xe8d0 && (inst2 & 0xfff0) == 0xf010)
+    {
+      /* TBH.  */
+      return 1;
+    }
+
+  return 0;
+}
+
 /* Analyze a Thumb prologue, looking for a recognizable stack frame
    and frame pointer.  Scan until we encounter a store that could
    clobber the stack frame unexpectedly, or an unknown instruction.
@@ -488,6 +673,7 @@
   struct pv_area *stack;
   struct cleanup *back_to;
   CORE_ADDR offset;
+  CORE_ADDR unrecognized_pc = 0;
 
   for (i = 0; i < 16; i++)
     regs[i] = pv_register (i, 0);
@@ -625,9 +811,8 @@
 	  constant = read_memory_unsigned_integer (loc, 4, byte_order);
 	  regs[bits (insn, 8, 10)] = pv_constant (constant);
 	}
-      else if ((insn & 0xe000) == 0xe000 && cache == NULL)
+      else if ((insn & 0xe000) == 0xe000)
 	{
-	  /* Only recognize 32-bit instructions for prologue skipping.  */
 	  unsigned short inst2;
 
 	  inst2 = read_memory_unsigned_integer (start + 2, 2,
@@ -654,61 +839,258 @@
 	      if (bit (inst2, 12) == 0)
 		nextpc = nextpc & 0xfffffffc;
 
-	      if (!skip_prologue_function (nextpc))
-		break;
-	    }
-	  else if ((insn & 0xfe50) == 0xe800	/* stm{db,ia} Rn[!], { registers } */
-		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
-	    ;
-	  else if ((insn & 0xfe50) == 0xe840	/* strd Rt, Rt2, [Rn, #imm] */
-		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
-	    ;
+	      if (!skip_prologue_function (gdbarch, nextpc,
+					   bit (inst2, 12) != 0))
+		break;
+	    }
+
+	  else if ((insn & 0xffd0) == 0xe900    /* stmdb Rn{!}, { registers } */
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    {
+	      pv_t addr = regs[bits (insn, 0, 3)];
+	      int regno;
+
+	      if (pv_area_store_would_trash (stack, addr))
+		break;
+
+	      /* Calculate offsets of saved registers.  */
+	      for (regno = ARM_LR_REGNUM; regno >= 0; regno--)
+		if (inst2 & (1 << regno))
+		  {
+		    addr = pv_add_constant (addr, -4);
+		    pv_area_store (stack, addr, 4, regs[regno]);
+		  }
+
+	      if (insn & 0x0020)
+		regs[bits (insn, 0, 3)] = addr;
+	    }
+
+	  else if ((insn & 0xff50) == 0xe940	/* strd Rt, Rt2, [Rn, #+/-imm]{!} */
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    {
+	      int regno1 = bits (inst2, 12, 15);
+	      int regno2 = bits (inst2, 8, 11);
+	      pv_t addr = regs[bits (insn, 0, 3)];
+
+	      offset = inst2 & 0xff;
+	      if (insn & 0x0080)
+		addr = pv_add_constant (addr, offset);
+	      else
+		addr = pv_add_constant (addr, -offset);
+
+	      if (pv_area_store_would_trash (stack, addr))
+		break;
+
+	      pv_area_store (stack, addr, 4, regs[regno1]);
+	      pv_area_store (stack, pv_add_constant (addr, 4),
+			     4, regs[regno2]);
+
+	      if (insn & 0x0020)
+		regs[bits (insn, 0, 3)] = addr;
+	    }
+
+	  else if ((insn & 0xfff0) == 0xf8c0	/* str Rt,[Rn,+/-#imm]{!} */
+		   && (inst2 & 0x0c00) == 0x0c00
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    {
+	      int regno = bits (inst2, 12, 15);
+	      pv_t addr = regs[bits (insn, 0, 3)];
+
+	      offset = inst2 & 0xff;
+	      if (inst2 & 0x0200)
+		addr = pv_add_constant (addr, offset);
+	      else
+		addr = pv_add_constant (addr, -offset);
+
+	      if (pv_area_store_would_trash (stack, addr))
+		break;
+
+	      pv_area_store (stack, addr, 4, regs[regno]);
+
+	      if (inst2 & 0x0100)
+		regs[bits (insn, 0, 3)] = addr;
+	    }
+
+	  else if ((insn & 0xfff0) == 0xf8c0	/* str.w Rt,[Rn,#imm] */
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    {
+	      int regno = bits (inst2, 12, 15);
+	      pv_t addr;
+
+	      offset = inst2 & 0xfff;
+	      addr = pv_add_constant (regs[bits (insn, 0, 3)], offset);
+
+	      if (pv_area_store_would_trash (stack, addr))
+		break;
+
+	      pv_area_store (stack, addr, 4, regs[regno]);
+	    }
+
+	  else if ((insn & 0xffd0) == 0xf880	/* str{bh}.w Rt,[Rn,#imm] */
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    /* Ignore stores of argument registers to the stack.  */
+	    ;
+
+	  else if ((insn & 0xffd0) == 0xf800	/* str{bh} Rt,[Rn,#+/-imm] */
+		   && (inst2 & 0x0d00) == 0x0c00
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    /* Ignore stores of argument registers to the stack.  */
+	    ;
+
 	  else if ((insn & 0xffd0) == 0xe890	/* ldmia Rn[!], { registers } */
-	      && (inst2 & 0x8000) == 0x0000
-	      && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
-	    ;
+		   && (inst2 & 0x8000) == 0x0000
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    /* Ignore block loads from the stack, potentially copying
+	       parameters from memory.  */
+	    ;
+
+	  else if ((insn & 0xffb0) == 0xe950	/* ldrd Rt, Rt2, [Rn, #+/-imm] */
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    /* Similarly ignore dual loads from the stack.  */
+	    ;
+
+	  else if ((insn & 0xfff0) == 0xf850	/* ldr Rt,[Rn,#+/-imm] */
+		   && (inst2 & 0x0d00) == 0x0c00
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    /* Similarly ignore single loads from the stack.  */
+	    ;
+
+	  else if ((insn & 0xfff0) == 0xf8d0	/* ldr.w Rt,[Rn,#imm] */
+		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
+	    /* Similarly ignore single loads from the stack.  */
+	    ;
+
 	  else if ((insn & 0xfbf0) == 0xf100	/* add.w Rd, Rn, #imm */
 		   && (inst2 & 0x8000) == 0x0000)
-	    /* Since we only recognize this for prologue skipping, do not bother
-	       to compute the constant.  */
-	    regs[bits (inst2, 8, 11)] = regs[bits (insn, 0, 3)];
-	  else if ((insn & 0xfbf0) == 0xf1a0	/* sub.w Rd, Rn, #imm12 */
-		   && (inst2 & 0x8000) == 0x0000)
-	    /* Since we only recognize this for prologue skipping, do not bother
-	       to compute the constant.  */
-	    regs[bits (inst2, 8, 11)] = regs[bits (insn, 0, 3)];
-	  else if ((insn & 0xfbf0) == 0xf2a0	/* sub.w Rd, Rn, #imm8 */
-		   && (inst2 & 0x8000) == 0x0000)
-	    /* Since we only recognize this for prologue skipping, do not bother
-	       to compute the constant.  */
-	    regs[bits (inst2, 8, 11)] = regs[bits (insn, 0, 3)];
-	  else if ((insn & 0xff50) == 0xf850	/* ldr.w Rd, [Rn, #imm]{!} */
-		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
-	    ;
-	  else if ((insn & 0xff50) == 0xe950	/* ldrd Rt, Rt2, [Rn, #imm]{!} */
-		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
-	    ;
-	  else if ((insn & 0xff50) == 0xf800	/* strb.w or strh.w */
-		   && pv_is_register (regs[bits (insn, 0, 3)], ARM_SP_REGNUM))
-	    ;
+	    {
+	      unsigned int imm = ((bits (insn, 10, 10) << 11)
+				  | (bits (inst2, 12, 14) << 8)
+				  | bits (inst2, 0, 7));
+
+	      regs[bits (inst2, 8, 11)]
+		= pv_add_constant (regs[bits (insn, 0, 3)],
+				   thumb_expand_immediate (imm));
+	    }
+
+	  else if ((insn & 0xfbf0) == 0xf200	/* addw Rd, Rn, #imm */
+		   && (inst2 & 0x8000) == 0x0000)
+	    {
+	      unsigned int imm = ((bits (insn, 10, 10) << 11)
+				  | (bits (inst2, 12, 14) << 8)
+				  | bits (inst2, 0, 7));
+
+	      regs[bits (inst2, 8, 11)]
+		= pv_add_constant (regs[bits (insn, 0, 3)], imm);
+	    }
+
+	  else if ((insn & 0xfbf0) == 0xf1a0	/* sub.w Rd, Rn, #imm */
+		   && (inst2 & 0x8000) == 0x0000)
+	    {
+	      unsigned int imm = ((bits (insn, 10, 10) << 11)
+				  | (bits (inst2, 12, 14) << 8)
+				  | bits (inst2, 0, 7));
+
+	      regs[bits (inst2, 8, 11)]
+		= pv_add_constant (regs[bits (insn, 0, 3)],
+				   - (CORE_ADDR) thumb_expand_immediate (imm));
+	    }
+
+	  else if ((insn & 0xfbf0) == 0xf2a0	/* subw Rd, Rn, #imm */
+		   && (inst2 & 0x8000) == 0x0000)
+	    {
+	      unsigned int imm = ((bits (insn, 10, 10) << 11)
+				  | (bits (inst2, 12, 14) << 8)
+				  | bits (inst2, 0, 7));
+
+	      regs[bits (inst2, 8, 11)]
+		= pv_add_constant (regs[bits (insn, 0, 3)], - (CORE_ADDR) imm);
+	    }
+
+	  else if ((insn & 0xfbff) == 0xf04f)	/* mov.w Rd, #const */
+	    {
+	      unsigned int imm = ((bits (insn, 10, 10) << 11)
+				  | (bits (inst2, 12, 14) << 8)
+				  | bits (inst2, 0, 7));
+
+	      regs[bits (inst2, 8, 11)]
+		= pv_constant (thumb_expand_immediate (imm));
+	    }
+
+	  else if ((insn & 0xfbf0) == 0xf240)	/* movw Rd, #const */
+	    {
+	      unsigned int imm
+		= EXTRACT_MOVW_MOVT_IMM_T (insn, inst2);
+
+	      regs[bits (inst2, 8, 11)] = pv_constant (imm);
+	    }
+
+	  else if (insn == 0xea5f		/* mov.w Rd,Rm */
+		   && (inst2 & 0xf0f0) == 0)
+	    {
+	      int dst_reg = (inst2 & 0x0f00) >> 8;
+	      int src_reg = inst2 & 0xf;
+	      regs[dst_reg] = regs[src_reg];
+	    }
+
+	  else if ((insn & 0xff7f) == 0xf85f)	/* ldr.w Rt,<label> */
+	    {
+	      /* Constant pool loads.  */
+	      unsigned int constant;
+	      CORE_ADDR loc;
+
+	      offset = bits (insn, 0, 11);
+	      if (insn & 0x0080)
+		loc = start + 4 + offset;
+	      else
+		loc = start + 4 - offset;
+
+	      constant = read_memory_unsigned_integer (loc, 4, byte_order);
+	      regs[bits (inst2, 12, 15)] = pv_constant (constant);
+	    }
+
+	  else if ((insn & 0xff7f) == 0xe95f)	/* ldrd Rt,Rt2,<label> */
+	    {
+	      /* Constant pool loads.  */
+	      unsigned int constant;
+	      CORE_ADDR loc;
+
+	      offset = bits (insn, 0, 7) << 2;
+	      if (insn & 0x0080)
+		loc = start + 4 + offset;
+	      else
+		loc = start + 4 - offset;
+
+	      constant = read_memory_unsigned_integer (loc, 4, byte_order);
+	      regs[bits (inst2, 12, 15)] = pv_constant (constant);
+
+	      constant = read_memory_unsigned_integer (loc + 4, 4, byte_order);
+	      regs[bits (inst2, 8, 11)] = pv_constant (constant);
+	    }
+
+	  else if (thumb2_instruction_changes_pc (insn, inst2))
+	    {
+	      /* Don't scan past anything that might change control flow.  */
+	      break;
+	    }
 	  else
 	    {
-	      /* We don't know what this instruction is.  We're finished
-		 scanning.  NOTE: Recognizing more safe-to-ignore
-		 instructions here will improve support for optimized
-		 code.  */
-	      break;
+	      /* The optimizer might shove anything into the prologue,
+		 so we just skip what we don't recognize.  */
+	      unrecognized_pc = start;
 	    }
 
 	  start += 2;
 	}
+      else if (thumb_instruction_changes_pc (insn))
+	{
+	  /* Don't scan past anything that might change control flow.  */
+	  break;
+	}
       else
 	{
-	  /* We don't know what this instruction is.  We're finished
-	     scanning.  NOTE: Recognizing more safe-to-ignore
-	     instructions here will improve support for optimized
-	     code.  */
-	  break;
+	  /* The optimizer might shove anything into the prologue,
+	     so we just skip what we don't recognize.  */
+	  unrecognized_pc = start;
 	}
 
       start += 2;
@@ -718,10 +1100,13 @@
     fprintf_unfiltered (gdb_stdlog, "Prologue scan stopped at %s\n",
 			paddress (gdbarch, start));
 
+  if (unrecognized_pc == 0)
+    unrecognized_pc = start;
+
   if (cache == NULL)
     {
       do_cleanups (back_to);
-      return start;
+      return unrecognized_pc;
     }
 
   if (pv_is_register (regs[ARM_FP_REGNUM], ARM_SP_REGNUM))
@@ -754,7 +1139,191 @@
       cache->saved_regs[i].addr = offset;
 
   do_cleanups (back_to);
-  return start;
+  return unrecognized_pc;
+}
+
+
+/* Try to analyze the instructions starting from PC, which load symbol
+   __stack_chk_guard.  Return the address of instruction after loading this
+   symbol, set the dest register number to *BASEREG, and set the size of
+   instructions for loading symbol in OFFSET.  Return 0 if instructions are
+   not recognized.  */
+
+static CORE_ADDR
+arm_analyze_load_stack_chk_guard(CORE_ADDR pc, struct gdbarch *gdbarch,
+				 unsigned int *destreg, int *offset)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  int is_thumb = arm_pc_is_thumb (pc);
+  unsigned int low, high, address;
+
+  address = 0;
+  if (is_thumb)
+    {
+      unsigned short insn1
+	= read_memory_unsigned_integer (pc, 2, byte_order_for_code);
+
+      if ((insn1 & 0xf800) == 0x4800) /* ldr Rd, #immed */
+	{
+	  *destreg = bits (insn1, 8, 10);
+	  *offset = 2;
+	  address = bits (insn1, 0, 7);
+	}
+      else if ((insn1 & 0xfbf0) == 0xf240) /* movw Rd, #const */
+	{
+	  unsigned short insn2
+	    = read_memory_unsigned_integer (pc + 2, 2, byte_order_for_code);
+
+	  low = EXTRACT_MOVW_MOVT_IMM_T (insn1, insn2);
+
+	  insn1
+	    = read_memory_unsigned_integer (pc + 4, 2, byte_order_for_code);
+	  insn2
+	    = read_memory_unsigned_integer (pc + 6, 2, byte_order_for_code);
+
+	  /* movt Rd, #const */
+	  if ((insn1 & 0xfbc0) == 0xf2c0)
+	    {
+	      high = EXTRACT_MOVW_MOVT_IMM_T (insn1, insn2);
+	      *destreg = bits (insn2, 8, 11);
+	      *offset = 8;
+	      address = (high << 16 | low);
+	    }
+	}
+    }
+  else
+    {
+      unsigned int insn
+	= read_memory_unsigned_integer (pc, 4, byte_order_for_code);
+
+      if ((insn & 0x0e5f0000) == 0x041f0000) /* ldr Rd, #immed */
+	{
+	  address = bits (insn, 0, 11);
+	  *destreg = bits (insn, 12, 15);
+	  *offset = 4;
+	}
+      else if ((insn & 0x0ff00000) == 0x03000000) /* movw Rd, #const */
+	{
+	  low = EXTRACT_MOVW_MOVT_IMM_A (insn);
+
+	  insn
+	    = read_memory_unsigned_integer (pc + 4, 4, byte_order_for_code);
+
+	  if ((insn & 0x0ff00000) == 0x03400000) /* movt Rd, #const */
+	    {
+	      high = EXTRACT_MOVW_MOVT_IMM_A (insn);
+	      *destreg = bits (insn, 12, 15);
+	      *offset = 8;
+	      address = (high << 16 | low);
+	    }
+	}
+    }
+
+  return address;
+}
+
+/* Try to skip a sequence of instructions used for stack protector.  If PC
+   points to the first instruction of this sequence, return the address of first
+   instruction after this sequence, otherwise, return original PC.
+
+   On arm, this sequence of instructions is composed of mainly three steps,
+     Step 1: load symbol __stack_chk_guard,
+     Step 2: load from address of __stack_chk_guard,
+     Step 3: store it to somewhere else.
+
+   Usually, instructions on step 2 and step 3 are the same on various ARM
+   architectures.  On step 2, it is one instruction 'ldr Rx, [Rn, #0]', and
+   on step 3, it is also one instruction 'str Rx, [r7, #immd]'.  However,
+   instructions in step 1 vary from different ARM architectures.  On ARMv7,
+   they are,
+
+	movw	Rn, #:lower16:__stack_chk_guard
+	movt	Rn, #:upper16:__stack_chk_guard
+
+   On ARMv5t, it is,
+
+	ldr	Rn, .Label
+	....
+	.Lable:
+	.word	__stack_chk_guard
+
+   Since ldr/str is a very popular instruction, we can't use them as
+   'fingerprint' or 'signature' of stack protector sequence.  Here we choose
+   sequence {movw/movt, ldr}/ldr/str plus symbol __stack_chk_guard, if not
+   stripped, as the 'fingerprint' of a stack protector cdoe sequence.  */
+
+static CORE_ADDR
+arm_skip_stack_protector(CORE_ADDR pc, struct gdbarch *gdbarch)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  unsigned int address, basereg;
+  struct minimal_symbol *stack_chk_guard;
+  int offset;
+  int is_thumb = arm_pc_is_thumb (pc);
+  CORE_ADDR addr;
+
+  /* Try to parse the instructions in Step 1.  */
+  addr = arm_analyze_load_stack_chk_guard (pc, gdbarch,
+					   &basereg, &offset);
+  if (!addr)
+    return pc;
+
+  stack_chk_guard = lookup_minimal_symbol_by_pc (addr);
+  /* If name of symbol doesn't start with '__stack_chk_guard', this
+     instruction sequence is not for stack protector.  If symbol is
+     removed, we conservatively think this sequence is for stack protector.  */
+  if (stack_chk_guard
+      && strncmp (SYMBOL_LINKAGE_NAME (stack_chk_guard), "__stack_chk_guard",
+		  strlen ("__stack_chk_guard")) != 0)
+   return pc;
+
+  if (is_thumb)
+    {
+      unsigned int destreg;
+      unsigned short insn
+	= read_memory_unsigned_integer (pc + offset, 2, byte_order_for_code);
+
+      /* Step 2: ldr Rd, [Rn, #immed], encoding T1.  */
+      if ((insn & 0xf800) != 0x6800)
+	return pc;
+      if (bits (insn, 3, 5) != basereg)
+	return pc;
+      destreg = bits (insn, 0, 2);
+
+      insn = read_memory_unsigned_integer (pc + offset + 2, 2,
+					   byte_order_for_code);
+      /* Step 3: str Rd, [Rn, #immed], encoding T1.  */
+      if ((insn & 0xf800) != 0x6000)
+	return pc;
+      if (destreg != bits (insn, 0, 2))
+	return pc;
+    }
+  else
+    {
+      unsigned int destreg;
+      unsigned int insn
+	= read_memory_unsigned_integer (pc + offset, 4, byte_order_for_code);
+
+      /* Step 2: ldr Rd, [Rn, #immed], encoding A1.  */
+      if ((insn & 0x0e500000) != 0x04100000)
+	return pc;
+      if (bits (insn, 16, 19) != basereg)
+	return pc;
+      destreg = bits (insn, 12, 15);
+      /* Step 3: str Rd, [Rn, #immed], encoding A1.  */
+      insn = read_memory_unsigned_integer (pc + offset + 4,
+					   4, byte_order_for_code);
+      if ((insn & 0x0e500000) != 0x04000000)
+	return pc;
+      if (bits (insn, 12, 15) != destreg)
+	return pc;
+    }
+  /* The size of total two instructions ldr/str is 4 on Thumb-2, while 8
+     on arm.  */
+  if (is_thumb)
+    return pc + offset + 4;
+  else
+    return pc + offset + 8;
 }
 
 /* Advance the PC across any function entry prologue instructions to
@@ -790,6 +1359,11 @@
 	= skip_prologue_using_sal (gdbarch, func_addr);
       struct symtab *s = find_pc_symtab (func_addr);
 
+      if (post_prologue_pc)
+	post_prologue_pc
+	  = arm_skip_stack_protector (post_prologue_pc, gdbarch);
+
+
       /* GCC always emits a line note before the prologue and another
 	 one after, even if the two are at the same address or on the
 	 same line.  Take advantage of this so that we do not need to
@@ -938,12 +1512,12 @@
   if (find_pc_partial_function (block_addr, NULL, &prologue_start,
 				&prologue_end))
     {
-      struct symtab_and_line sal = find_pc_line (prologue_start, 0);
-
-      if (sal.line == 0)		/* no line info, use current PC  */
-	prologue_end = prev_pc;
-      else if (sal.end < prologue_end)	/* next line begins after fn end */
-	prologue_end = sal.end;		/* (probably means no prologue)  */
+      /* See comment in arm_scan_prologue for an explanation of
+	 this heuristics.  */
+      if (prologue_end > prologue_start + 64)
+	{
+	  prologue_end = prologue_start + 64;
+	}
     }
   else
     /* We're in the boondocks: we have no idea where the start of the
@@ -1230,7 +1804,7 @@
 	     the stack.  */
 	  CORE_ADDR dest = BranchDest (current_pc, insn);
 
-	  if (skip_prologue_function (dest))
+	  if (skip_prologue_function (gdbarch, dest, 0))
 	    continue;
 	  else
 	    break;
@@ -1459,7 +2033,13 @@
   if (cache->prev_sp == 0)
     return;
 
+  /* Use function start address as part of the frame ID.  If we cannot
+     identify the start address (due to missing symbol information),
+     fall back to just using the current PC.  */
   func = get_frame_func (this_frame);
+  if (!func)
+    func = pc;
+
   id = frame_id_build (cache->prev_sp, func);
   *this_id = id;
 }
@@ -1529,6 +2109,744 @@
   default_frame_sniffer
 };
 
+/* Maintain a list of ARM exception table entries per objfile, similar to the
+   list of mapping symbols.  We only cache entries for standard ARM-defined
+   personality routines; the cache will contain only the frame unwinding
+   instructions associated with the entry (not the descriptors).  */
+
+static const struct objfile_data *arm_exidx_data_key;
+
+struct arm_exidx_entry
+{
+  bfd_vma addr;
+  gdb_byte *entry;
+};
+typedef struct arm_exidx_entry arm_exidx_entry_s;
+DEF_VEC_O(arm_exidx_entry_s);
+
+struct arm_exidx_data
+{
+  VEC(arm_exidx_entry_s) **section_maps;
+};
+
+static void
+arm_exidx_data_free (struct objfile *objfile, void *arg)
+{
+  struct arm_exidx_data *data = arg;
+  unsigned int i;
+
+  for (i = 0; i < objfile->obfd->section_count; i++)
+    VEC_free (arm_exidx_entry_s, data->section_maps[i]);
+}
+
+static inline int
+arm_compare_exidx_entries (const struct arm_exidx_entry *lhs,
+			   const struct arm_exidx_entry *rhs)
+{
+  return lhs->addr < rhs->addr;
+}
+
+static struct obj_section *
+arm_obj_section_from_vma (struct objfile *objfile, bfd_vma vma)
+{
+  struct obj_section *osect;
+
+  ALL_OBJFILE_OSECTIONS (objfile, osect)
+    if (bfd_get_section_flags (objfile->obfd,
+			       osect->the_bfd_section) & SEC_ALLOC)
+      {
+	bfd_vma start, size;
+	start = bfd_get_section_vma (objfile->obfd, osect->the_bfd_section);
+	size = bfd_get_section_size (osect->the_bfd_section);
+
+	if (start <= vma && vma < start + size)
+	  return osect;
+      }
+
+  return NULL;
+}
+
+/* Parse contents of exception table and exception index sections
+   of OBJFILE, and fill in the exception table entry cache.
+
+   For each entry that refers to a standard ARM-defined personality
+   routine, extract the frame unwinding instructions (from either
+   the index or the table section).  The unwinding instructions
+   are normalized by:
+    - extracting them from the rest of the table data
+    - converting to host endianness
+    - appending the implicit 0xb0 ("Finish") code
+
+   The extracted and normalized instructions are stored for later
+   retrieval by the arm_find_exidx_entry routine.  */
+ 
+static void
+arm_exidx_new_objfile (struct objfile *objfile)
+{
+  struct cleanup *cleanups = make_cleanup (null_cleanup, NULL);
+  struct arm_exidx_data *data;
+  asection *exidx, *extab;
+  bfd_vma exidx_vma = 0, extab_vma = 0;
+  bfd_size_type exidx_size = 0, extab_size = 0;
+  gdb_byte *exidx_data = NULL, *extab_data = NULL;
+  LONGEST i;
+
+  /* If we've already touched this file, do nothing.  */
+  if (!objfile || objfile_data (objfile, arm_exidx_data_key) != NULL)
+    return;
+
+  /* Read contents of exception table and index.  */
+  exidx = bfd_get_section_by_name (objfile->obfd, ".ARM.exidx");
+  if (exidx)
+    {
+      exidx_vma = bfd_section_vma (objfile->obfd, exidx);
+      exidx_size = bfd_get_section_size (exidx);
+      exidx_data = xmalloc (exidx_size);
+      make_cleanup (xfree, exidx_data);
+
+      if (!bfd_get_section_contents (objfile->obfd, exidx,
+				     exidx_data, 0, exidx_size))
+	{
+	  do_cleanups (cleanups);
+	  return;
+	}
+    }
+
+  extab = bfd_get_section_by_name (objfile->obfd, ".ARM.extab");
+  if (extab)
+    {
+      extab_vma = bfd_section_vma (objfile->obfd, extab);
+      extab_size = bfd_get_section_size (extab);
+      extab_data = xmalloc (extab_size);
+      make_cleanup (xfree, extab_data);
+
+      if (!bfd_get_section_contents (objfile->obfd, extab,
+				     extab_data, 0, extab_size))
+	{
+	  do_cleanups (cleanups);
+	  return;
+	}
+    }
+
+  /* Allocate exception table data structure.  */
+  data = OBSTACK_ZALLOC (&objfile->objfile_obstack, struct arm_exidx_data);
+  set_objfile_data (objfile, arm_exidx_data_key, data);
+  data->section_maps = OBSTACK_CALLOC (&objfile->objfile_obstack,
+				       objfile->obfd->section_count,
+				       VEC(arm_exidx_entry_s) *);
+
+  /* Fill in exception table.  */
+  for (i = 0; i < exidx_size / 8; i++)
+    {
+      struct arm_exidx_entry new_exidx_entry;
+      bfd_vma idx = bfd_h_get_32 (objfile->obfd, exidx_data + i * 8);
+      bfd_vma val = bfd_h_get_32 (objfile->obfd, exidx_data + i * 8 + 4);
+      bfd_vma addr = 0, word = 0;
+      int n_bytes = 0, n_words = 0;
+      struct obj_section *sec;
+      gdb_byte *entry = NULL;
+
+      /* Extract address of start of function.  */
+      idx = ((idx & 0x7fffffff) ^ 0x40000000) - 0x40000000;
+      idx += exidx_vma + i * 8;
+
+      /* Find section containing function and compute section offset.  */
+      sec = arm_obj_section_from_vma (objfile, idx);
+      if (sec == NULL)
+	continue;
+      idx -= bfd_get_section_vma (objfile->obfd, sec->the_bfd_section);
+
+      /* Determine address of exception table entry.  */
+      if (val == 1)
+	{
+	  /* EXIDX_CANTUNWIND -- no exception table entry present.  */
+	}
+      else if ((val & 0xff000000) == 0x80000000)
+	{
+	  /* Exception table entry embedded in .ARM.exidx
+	     -- must be short form.  */
+	  word = val;
+	  n_bytes = 3;
+	}
+      else if (!(val & 0x80000000))
+	{
+	  /* Exception table entry in .ARM.extab.  */
+	  addr = ((val & 0x7fffffff) ^ 0x40000000) - 0x40000000;
+	  addr += exidx_vma + i * 8 + 4;
+
+	  if (addr >= extab_vma && addr + 4 <= extab_vma + extab_size)
+	    {
+	      word = bfd_h_get_32 (objfile->obfd,
+				   extab_data + addr - extab_vma);
+	      addr += 4;
+
+	      if ((word & 0xff000000) == 0x80000000)
+		{
+		  /* Short form.  */
+		  n_bytes = 3;
+		}
+	      else if ((word & 0xff000000) == 0x81000000
+		       || (word & 0xff000000) == 0x82000000)
+		{
+		  /* Long form.  */
+		  n_bytes = 2;
+		  n_words = ((word >> 16) & 0xff);
+		}
+	      else if (!(word & 0x80000000))
+		{
+		  bfd_vma pers;
+		  struct obj_section *pers_sec;
+		  int gnu_personality = 0;
+
+		  /* Custom personality routine.  */
+		  pers = ((word & 0x7fffffff) ^ 0x40000000) - 0x40000000;
+		  pers = UNMAKE_THUMB_ADDR (pers + addr - 4);
+
+		  /* Check whether we've got one of the variants of the
+		     GNU personality routines.  */
+		  pers_sec = arm_obj_section_from_vma (objfile, pers);
+		  if (pers_sec)
+		    {
+		      static const char *personality[] = 
+			{
+			  "__gcc_personality_v0",
+			  "__gxx_personality_v0",
+			  "__gcj_personality_v0",
+			  "__gnu_objc_personality_v0",
+			  NULL
+			};
+
+		      CORE_ADDR pc = pers + obj_section_offset (pers_sec);
+		      int k;
+
+		      for (k = 0; personality[k]; k++)
+			if (lookup_minimal_symbol_by_pc_name
+			      (pc, personality[k], objfile))
+			  {
+			    gnu_personality = 1;
+			    break;
+			  }
+		    }
+
+		  /* If so, the next word contains a word count in the high
+		     byte, followed by the same unwind instructions as the
+		     pre-defined forms.  */
+		  if (gnu_personality
+		      && addr + 4 <= extab_vma + extab_size)
+		    {
+		      word = bfd_h_get_32 (objfile->obfd,
+					   extab_data + addr - extab_vma);
+		      addr += 4;
+		      n_bytes = 3;
+		      n_words = ((word >> 24) & 0xff);
+		    }
+		}
+	    }
+	}
+
+      /* Sanity check address.  */
+      if (n_words)
+	if (addr < extab_vma || addr + 4 * n_words > extab_vma + extab_size)
+	  n_words = n_bytes = 0;
+
+      /* The unwind instructions reside in WORD (only the N_BYTES least
+	 significant bytes are valid), followed by N_WORDS words in the
+	 extab section starting at ADDR.  */
+      if (n_bytes || n_words)
+	{
+	  gdb_byte *p = entry = obstack_alloc (&objfile->objfile_obstack,
+					       n_bytes + n_words * 4 + 1);
+
+	  while (n_bytes--)
+	    *p++ = (gdb_byte) ((word >> (8 * n_bytes)) & 0xff);
+
+	  while (n_words--)
+	    {
+	      word = bfd_h_get_32 (objfile->obfd,
+				   extab_data + addr - extab_vma);
+	      addr += 4;
+
+	      *p++ = (gdb_byte) ((word >> 24) & 0xff);
+	      *p++ = (gdb_byte) ((word >> 16) & 0xff);
+	      *p++ = (gdb_byte) ((word >> 8) & 0xff);
+	      *p++ = (gdb_byte) (word & 0xff);
+	    }
+
+	  /* Implied "Finish" to terminate the list.  */
+	  *p++ = 0xb0;
+	}
+
+      /* Push entry onto vector.  They are guaranteed to always
+	 appear in order of increasing addresses.  */
+      new_exidx_entry.addr = idx;
+      new_exidx_entry.entry = entry;
+      VEC_safe_push (arm_exidx_entry_s,
+		     data->section_maps[sec->the_bfd_section->index],
+		     &new_exidx_entry);
+    }
+
+  do_cleanups (cleanups);
+}
+
+/* Search for the exception table entry covering MEMADDR.  If one is found,
+   return a pointer to its data.  Otherwise, return 0.  If START is non-NULL,
+   set *START to the start of the region covered by this entry.  */
+
+static gdb_byte *
+arm_find_exidx_entry (CORE_ADDR memaddr, CORE_ADDR *start)
+{
+  struct obj_section *sec;
+
+  sec = find_pc_section (memaddr);
+  if (sec != NULL)
+    {
+      struct arm_exidx_data *data;
+      VEC(arm_exidx_entry_s) *map;
+      struct arm_exidx_entry map_key = { memaddr - obj_section_addr (sec), 0 };
+      unsigned int idx;
+
+      data = objfile_data (sec->objfile, arm_exidx_data_key);
+      if (data != NULL)
+	{
+	  map = data->section_maps[sec->the_bfd_section->index];
+	  if (!VEC_empty (arm_exidx_entry_s, map))
+	    {
+	      struct arm_exidx_entry *map_sym;
+
+	      idx = VEC_lower_bound (arm_exidx_entry_s, map, &map_key,
+				     arm_compare_exidx_entries);
+
+	      /* VEC_lower_bound finds the earliest ordered insertion
+		 point.  If the following symbol starts at this exact
+		 address, we use that; otherwise, the preceding
+		 exception table entry covers this address.  */
+	      if (idx < VEC_length (arm_exidx_entry_s, map))
+		{
+		  map_sym = VEC_index (arm_exidx_entry_s, map, idx);
+		  if (map_sym->addr == map_key.addr)
+		    {
+		      if (start)
+			*start = map_sym->addr + obj_section_addr (sec);
+		      return map_sym->entry;
+		    }
+		}
+
+	      if (idx > 0)
+		{
+		  map_sym = VEC_index (arm_exidx_entry_s, map, idx - 1);
+		  if (start)
+		    *start = map_sym->addr + obj_section_addr (sec);
+		  return map_sym->entry;
+		}
+	    }
+	}
+    }
+
+  return NULL;
+}
+
+/* Given the current frame THIS_FRAME, and its associated frame unwinding
+   instruction list from the ARM exception table entry ENTRY, allocate and
+   return a prologue cache structure describing how to unwind this frame.
+
+   Return NULL if the unwinding instruction list contains a "spare",
+   "reserved" or "refuse to unwind" instruction as defined in section
+   "9.3 Frame unwinding instructions" of the "Exception Handling ABI
+   for the ARM Architecture" document.  */
+
+static struct arm_prologue_cache *
+arm_exidx_fill_cache (struct frame_info *this_frame, gdb_byte *entry)
+{
+  CORE_ADDR vsp = 0;
+  int vsp_valid = 0;
+
+  struct arm_prologue_cache *cache;
+  cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
+  cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
+
+  for (;;)
+    {
+      gdb_byte insn;
+
+      /* Whenever we reload SP, we actually have to retrieve its
+	 actual value in the current frame.  */
+      if (!vsp_valid)
+	{
+	  if (trad_frame_realreg_p (cache->saved_regs, ARM_SP_REGNUM))
+	    {
+	      int reg = cache->saved_regs[ARM_SP_REGNUM].realreg;
+	      vsp = get_frame_register_unsigned (this_frame, reg);
+	    }
+	  else
+	    {
+	      CORE_ADDR addr = cache->saved_regs[ARM_SP_REGNUM].addr;
+	      vsp = get_frame_memory_unsigned (this_frame, addr, 4);
+	    }
+
+	  vsp_valid = 1;
+	}
+
+      /* Decode next unwind instruction.  */
+      insn = *entry++;
+
+      if ((insn & 0xc0) == 0)
+	{
+	  int offset = insn & 0x3f;
+	  vsp += (offset << 2) + 4;
+	}
+      else if ((insn & 0xc0) == 0x40)
+	{
+	  int offset = insn & 0x3f;
+	  vsp -= (offset << 2) + 4;
+	}
+      else if ((insn & 0xf0) == 0x80)
+	{
+	  int mask = ((insn & 0xf) << 8) | *entry++;
+	  int i;
+
+	  /* The special case of an all-zero mask identifies
+	     "Refuse to unwind".  We return NULL to fall back
+	     to the prologue analyzer.  */
+	  if (mask == 0)
+	    return NULL;
+
+	  /* Pop registers r4..r15 under mask.  */
+	  for (i = 0; i < 12; i++)
+	    if (mask & (1 << i))
+	      {
+	        cache->saved_regs[4 + i].addr = vsp;
+		vsp += 4;
+	      }
+
+	  /* Special-case popping SP -- we need to reload vsp.  */
+	  if (mask & (1 << (ARM_SP_REGNUM - 4)))
+	    vsp_valid = 0;
+	}
+      else if ((insn & 0xf0) == 0x90)
+	{
+	  int reg = insn & 0xf;
+
+	  /* Reserved cases.  */
+	  if (reg == ARM_SP_REGNUM || reg == ARM_PC_REGNUM)
+	    return NULL;
+
+	  /* Set SP from another register and mark VSP for reload.  */
+	  cache->saved_regs[ARM_SP_REGNUM] = cache->saved_regs[reg];
+	  vsp_valid = 0;
+	}
+      else if ((insn & 0xf0) == 0xa0)
+	{
+	  int count = insn & 0x7;
+	  int pop_lr = (insn & 0x8) != 0;
+	  int i;
+
+	  /* Pop r4..r[4+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[4 + i].addr = vsp;
+	      vsp += 4;
+	    }
+
+	  /* If indicated by flag, pop LR as well.  */
+	  if (pop_lr)
+	    {
+	      cache->saved_regs[ARM_LR_REGNUM].addr = vsp;
+	      vsp += 4;
+	    }
+	}
+      else if (insn == 0xb0)
+	{
+	  /* We could only have updated PC by popping into it; if so, it
+	     will show up as address.  Otherwise, copy LR into PC.  */
+	  if (!trad_frame_addr_p (cache->saved_regs, ARM_PC_REGNUM))
+	    cache->saved_regs[ARM_PC_REGNUM]
+	      = cache->saved_regs[ARM_LR_REGNUM];
+
+	  /* We're done.  */
+	  break;
+	}
+      else if (insn == 0xb1)
+	{
+	  int mask = *entry++;
+	  int i;
+
+	  /* All-zero mask and mask >= 16 is "spare".  */
+	  if (mask == 0 || mask >= 16)
+	    return NULL;
+
+	  /* Pop r0..r3 under mask.  */
+	  for (i = 0; i < 4; i++)
+	    if (mask & (1 << i))
+	      {
+		cache->saved_regs[i].addr = vsp;
+		vsp += 4;
+	      }
+	}
+      else if (insn == 0xb2)
+	{
+	  ULONGEST offset = 0;
+	  unsigned shift = 0;
+
+	  do
+	    {
+	      offset |= (*entry & 0x7f) << shift;
+	      shift += 7;
+	    }
+	  while (*entry++ & 0x80);
+
+	  vsp += 0x204 + (offset << 2);
+	}
+      else if (insn == 0xb3)
+	{
+	  int start = *entry >> 4;
+	  int count = (*entry++) & 0xf;
+	  int i;
+
+	  /* Only registers D0..D15 are valid here.  */
+	  if (start + count >= 16)
+	    return NULL;
+
+	  /* Pop VFP double-precision registers D[start]..D[start+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_D0_REGNUM + start + i].addr = vsp;
+	      vsp += 8;
+	    }
+
+	  /* Add an extra 4 bytes for FSTMFDX-style stack.  */
+	  vsp += 4;
+	}
+      else if ((insn & 0xf8) == 0xb8)
+	{
+	  int count = insn & 0x7;
+	  int i;
+
+	  /* Pop VFP double-precision registers D[8]..D[8+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_D0_REGNUM + 8 + i].addr = vsp;
+	      vsp += 8;
+	    }
+
+	  /* Add an extra 4 bytes for FSTMFDX-style stack.  */
+	  vsp += 4;
+	}
+      else if (insn == 0xc6)
+	{
+	  int start = *entry >> 4;
+	  int count = (*entry++) & 0xf;
+	  int i;
+
+	  /* Only registers WR0..WR15 are valid.  */
+	  if (start + count >= 16)
+	    return NULL;
+
+	  /* Pop iwmmx registers WR[start]..WR[start+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_WR0_REGNUM + start + i].addr = vsp;
+	      vsp += 8;
+	    }
+	}
+      else if (insn == 0xc7)
+	{
+	  int mask = *entry++;
+	  int i;
+
+	  /* All-zero mask and mask >= 16 is "spare".  */
+	  if (mask == 0 || mask >= 16)
+	    return NULL;
+
+	  /* Pop iwmmx general-purpose registers WCGR0..WCGR3 under mask.  */
+	  for (i = 0; i < 4; i++)
+	    if (mask & (1 << i))
+	      {
+		cache->saved_regs[ARM_WCGR0_REGNUM + i].addr = vsp;
+		vsp += 4;
+	      }
+	}
+      else if ((insn & 0xf8) == 0xc0)
+	{
+	  int count = insn & 0x7;
+	  int i;
+
+	  /* Pop iwmmx registers WR[10]..WR[10+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_WR0_REGNUM + 10 + i].addr = vsp;
+	      vsp += 8;
+	    }
+	}
+      else if (insn == 0xc8)
+	{
+	  int start = *entry >> 4;
+	  int count = (*entry++) & 0xf;
+	  int i;
+
+	  /* Only registers D0..D31 are valid.  */
+	  if (start + count >= 16)
+	    return NULL;
+
+	  /* Pop VFP double-precision registers
+	     D[16+start]..D[16+start+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_D0_REGNUM + 16 + start + i].addr = vsp;
+	      vsp += 8;
+	    }
+	}
+      else if (insn == 0xc9)
+	{
+	  int start = *entry >> 4;
+	  int count = (*entry++) & 0xf;
+	  int i;
+
+	  /* Pop VFP double-precision registers D[start]..D[start+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_D0_REGNUM + start + i].addr = vsp;
+	      vsp += 8;
+	    }
+	}
+      else if ((insn & 0xf8) == 0xd0)
+	{
+	  int count = insn & 0x7;
+	  int i;
+
+	  /* Pop VFP double-precision registers D[8]..D[8+count].  */
+	  for (i = 0; i <= count; i++)
+	    {
+	      cache->saved_regs[ARM_D0_REGNUM + 8 + i].addr = vsp;
+	      vsp += 8;
+	    }
+	}
+      else
+	{
+	  /* Everything else is "spare".  */
+	  return NULL;
+	}
+    }
+
+  /* If we restore SP from a register, assume this was the frame register.
+     Otherwise just fall back to SP as frame register.  */
+  if (trad_frame_realreg_p (cache->saved_regs, ARM_SP_REGNUM))
+    cache->framereg = cache->saved_regs[ARM_SP_REGNUM].realreg;
+  else
+    cache->framereg = ARM_SP_REGNUM;
+
+  /* Determine offset to previous frame.  */
+  cache->framesize
+    = vsp - get_frame_register_unsigned (this_frame, cache->framereg);
+
+  /* We already got the previous SP.  */
+  cache->prev_sp = vsp;
+
+  return cache;
+}
+
+/* Unwinding via ARM exception table entries.  Note that the sniffer
+   already computes a filled-in prologue cache, which is then used
+   with the same arm_prologue_this_id and arm_prologue_prev_register
+   routines also used for prologue-parsing based unwinding.  */
+
+static int
+arm_exidx_unwind_sniffer (const struct frame_unwind *self,
+			  struct frame_info *this_frame,
+			  void **this_prologue_cache)
+{
+  struct gdbarch *gdbarch = get_frame_arch (this_frame);
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  CORE_ADDR addr_in_block, exidx_region, func_start;
+  struct arm_prologue_cache *cache;
+  gdb_byte *entry;
+
+  /* See if we have an ARM exception table entry covering this address.  */
+  addr_in_block = get_frame_address_in_block (this_frame);
+  entry = arm_find_exidx_entry (addr_in_block, &exidx_region);
+  if (!entry)
+    return 0;
+
+  /* The ARM exception table does not describe unwind information
+     for arbitrary PC values, but is guaranteed to be correct only
+     at call sites.  We have to decide here whether we want to use
+     ARM exception table information for this frame, or fall back
+     to using prologue parsing.  (Note that if we have DWARF CFI,
+     this sniffer isn't even called -- CFI is always preferred.)
+
+     Before we make this decision, however, we check whether we
+     actually have *symbol* information for the current frame.
+     If not, prologue parsing would not work anyway, so we might
+     as well use the exception table and hope for the best.  */
+  if (find_pc_partial_function (addr_in_block, NULL, &func_start, NULL))
+    {
+      int exc_valid = 0;
+
+      /* If the next frame is "normal", we are at a call site in this
+	 frame, so exception information is guaranteed to be valid.  */
+      if (get_next_frame (this_frame)
+	  && get_frame_type (get_next_frame (this_frame)) == NORMAL_FRAME)
+	exc_valid = 1;
+
+      /* We also assume exception information is valid if we're currently
+	 blocked in a system call.  The system library is supposed to
+	 ensure this, so that e.g. pthread cancellation works.  */
+      if (arm_frame_is_thumb (this_frame))
+	{
+	  LONGEST insn;
+
+	  if (safe_read_memory_integer (get_frame_pc (this_frame) - 2, 2,
+					byte_order_for_code, &insn)
+	      && (insn & 0xff00) == 0xdf00 /* svc */)
+	    exc_valid = 1;
+	}
+      else
+	{
+	  LONGEST insn;
+
+	  if (safe_read_memory_integer (get_frame_pc (this_frame) - 4, 4,
+					byte_order_for_code, &insn)
+	      && (insn & 0x0f000000) == 0x0f000000 /* svc */)
+	    exc_valid = 1;
+	}
+	
+      /* Bail out if we don't know that exception information is valid.  */
+      if (!exc_valid)
+	return 0;
+
+     /* The ARM exception index does not mark the *end* of the region
+	covered by the entry, and some functions will not have any entry.
+	To correctly recognize the end of the covered region, the linker
+	should have inserted dummy records with a CANTUNWIND marker.
+
+	Unfortunately, current versions of GNU ld do not reliably do
+	this, and thus we may have found an incorrect entry above.
+	As a (temporary) sanity check, we only use the entry if it
+	lies *within* the bounds of the function.  Note that this check
+	might reject perfectly valid entries that just happen to cover
+	multiple functions; therefore this check ought to be removed
+	once the linker is fixed.  */
+      if (func_start > exidx_region)
+	return 0;
+    }
+
+  /* Decode the list of unwinding instructions into a prologue cache.
+     Note that this may fail due to e.g. a "refuse to unwind" code.  */
+  cache = arm_exidx_fill_cache (this_frame, entry);
+  if (!cache)
+    return 0;
+
+  *this_prologue_cache = cache;
+  return 1;
+}
+
+struct frame_unwind arm_exidx_unwind = {
+  NORMAL_FRAME,
+  arm_prologue_this_id,
+  arm_prologue_prev_register,
+  NULL,
+  arm_exidx_unwind_sniffer
+};
+
 static struct arm_prologue_cache *
 arm_make_stub_cache (struct frame_info *this_frame)
 {
@@ -1686,6 +3004,203 @@
     }
 }
 
+/* Return true if we are in the function's epilogue, i.e. after the
+   instruction that destroyed the function's stack frame.  */
+
+static int
+thumb_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  unsigned int insn, insn2;
+  int found_return = 0, found_stack_adjust = 0;
+  CORE_ADDR func_start, func_end;
+  CORE_ADDR scan_pc;
+  gdb_byte buf[4];
+
+  if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+    return 0;
+
+  /* The epilogue is a sequence of instructions along the following lines:
+
+    - add stack frame size to SP or FP
+    - [if frame pointer used] restore SP from FP
+    - restore registers from SP [may include PC]
+    - a return-type instruction [if PC wasn't already restored]
+
+    In a first pass, we scan forward from the current PC and verify the
+    instructions we find as compatible with this sequence, ending in a
+    return instruction.
+
+    However, this is not sufficient to distinguish indirect function calls
+    within a function from indirect tail calls in the epilogue in some cases.
+    Therefore, if we didn't already find any SP-changing instruction during
+    forward scan, we add a backward scanning heuristic to ensure we actually
+    are in the epilogue.  */
+
+  scan_pc = pc;
+  while (scan_pc < func_end && !found_return)
+    {
+      if (target_read_memory (scan_pc, buf, 2))
+	break;
+
+      scan_pc += 2;
+      insn = extract_unsigned_integer (buf, 2, byte_order_for_code);
+
+      if ((insn & 0xff80) == 0x4700)  /* bx <Rm> */
+	found_return = 1;
+      else if (insn == 0x46f7)  /* mov pc, lr */
+	found_return = 1;
+      else if (insn == 0x46bd)  /* mov sp, r7 */
+	found_stack_adjust = 1;
+      else if ((insn & 0xff00) == 0xb000)  /* add sp, imm or sub sp, imm  */
+	found_stack_adjust = 1;
+      else if ((insn & 0xfe00) == 0xbc00)  /* pop <registers> */
+	{
+	  found_stack_adjust = 1;
+	  if (insn & 0x0100)  /* <registers> include PC.  */
+	    found_return = 1;
+	}
+      else if ((insn & 0xe000) == 0xe000)  /* 32-bit Thumb-2 instruction */
+	{
+	  if (target_read_memory (scan_pc, buf, 2))
+	    break;
+
+	  scan_pc += 2;
+	  insn2 = extract_unsigned_integer (buf, 2, byte_order_for_code);
+
+	  if (insn == 0xe8bd)  /* ldm.w sp!, <registers> */
+	    {
+	      found_stack_adjust = 1;
+	      if (insn2 & 0x8000)  /* <registers> include PC.  */
+		found_return = 1;
+	    }
+	  else if (insn == 0xf85d  /* ldr.w <Rt>, [sp], #4 */
+		   && (insn2 & 0x0fff) == 0x0b04)
+	    {
+	      found_stack_adjust = 1;
+	      if ((insn2 & 0xf000) == 0xf000) /* <Rt> is PC.  */
+		found_return = 1;
+	    }
+	  else if ((insn & 0xffbf) == 0xecbd  /* vldm sp!, <list> */
+		   && (insn2 & 0x0e00) == 0x0a00)
+	    found_stack_adjust = 1;
+	  else
+	    break;
+	}
+      else
+	break;
+    }
+
+  if (!found_return)
+    return 0;
+
+  /* Since any instruction in the epilogue sequence, with the possible
+     exception of return itself, updates the stack pointer, we need to
+     scan backwards for at most one instruction.  Try either a 16-bit or
+     a 32-bit instruction.  This is just a heuristic, so we do not worry
+     too much about false positives.*/
+
+  if (!found_stack_adjust)
+    {
+      if (pc - 4 < func_start)
+	return 0;
+      if (target_read_memory (pc - 4, buf, 4))
+	return 0;
+
+      insn = extract_unsigned_integer (buf, 2, byte_order_for_code);
+      insn2 = extract_unsigned_integer (buf + 2, 2, byte_order_for_code);
+
+      if (insn2 == 0x46bd)  /* mov sp, r7 */
+	found_stack_adjust = 1;
+      else if ((insn2 & 0xff00) == 0xb000)  /* add sp, imm or sub sp, imm  */
+	found_stack_adjust = 1;
+      else if ((insn2 & 0xff00) == 0xbc00)  /* pop <registers> without PC */
+	found_stack_adjust = 1;
+      else if (insn == 0xe8bd)  /* ldm.w sp!, <registers> */
+	found_stack_adjust = 1;
+      else if (insn == 0xf85d  /* ldr.w <Rt>, [sp], #4 */
+	       && (insn2 & 0x0fff) == 0x0b04)
+	found_stack_adjust = 1;
+      else if ((insn & 0xffbf) == 0xecbd  /* vldm sp!, <list> */
+	       && (insn2 & 0x0e00) == 0x0a00)
+	found_stack_adjust = 1;
+    }
+
+  return found_stack_adjust;
+}
+
+/* Return true if we are in the function's epilogue, i.e. after the
+   instruction that destroyed the function's stack frame.  */
+
+static int
+arm_in_function_epilogue_p (struct gdbarch *gdbarch, CORE_ADDR pc)
+{
+  enum bfd_endian byte_order_for_code = gdbarch_byte_order_for_code (gdbarch);
+  unsigned int insn;
+  int found_return, found_stack_adjust;
+  CORE_ADDR func_start, func_end;
+
+  if (arm_pc_is_thumb (pc))
+    return thumb_in_function_epilogue_p (gdbarch, pc);
+
+  if (!find_pc_partial_function (pc, NULL, &func_start, &func_end))
+    return 0;
+
+  /* We are in the epilogue if the previous instruction was a stack
+     adjustment and the next instruction is a possible return (bx, mov
+     pc, or pop).  We could have to scan backwards to find the stack
+     adjustment, or forwards to find the return, but this is a decent
+     approximation.  First scan forwards.  */
+
+  found_return = 0;
+  insn = read_memory_unsigned_integer (pc, 4, byte_order_for_code);
+  if (bits (insn, 28, 31) != INST_NV)
+    {
+      if ((insn & 0x0ffffff0) == 0x012fff10)
+	/* BX.  */
+	found_return = 1;
+      else if ((insn & 0x0ffffff0) == 0x01a0f000)
+	/* MOV PC.  */
+	found_return = 1;
+      else if ((insn & 0x0fff0000) == 0x08bd0000
+	  && (insn & 0x0000c000) != 0)
+	/* POP (LDMIA), including PC or LR.  */
+	found_return = 1;
+    }
+
+  if (!found_return)
+    return 0;
+
+  /* Scan backwards.  This is just a heuristic, so do not worry about
+     false positives from mode changes.  */
+
+  if (pc < func_start + 4)
+    return 0;
+
+  insn = read_memory_unsigned_integer (pc - 4, 4, byte_order_for_code);
+  if (bits (insn, 28, 31) != INST_NV)
+    {
+      if ((insn & 0x0df0f000) == 0x0080d000)
+	/* ADD SP (register or immediate).  */
+	found_stack_adjust = 1;
+      else if ((insn & 0x0df0f000) == 0x0040d000)
+	/* SUB SP (register or immediate).  */
+	found_stack_adjust = 1;
+      else if ((insn & 0x0ffffff0) == 0x01a0d000)
+	/* MOV SP.  */
+	found_return = 1;
+      else if ((insn & 0x0fff0000) == 0x08bd0000)
+	/* POP (LDMIA).  */
+	found_stack_adjust = 1;
+    }
+
+  if (found_stack_adjust)
+    return 1;
+
+  return 0;
+}
+
+
 /* When arguments must be pushed onto the stack, they go on in reverse
    order.  The code below implements a FILO (stack) to do this.  */
 
@@ -3004,6 +4519,15 @@
       else
 	nextpc = get_frame_register_unsigned (frame, bits (inst1, 3, 6));
     }
+  else if ((inst1 & 0xff87) == 0x4687)	/* mov pc, REG */
+    {
+      if (bits (inst1, 3, 6) == 0x0f)
+	nextpc = pc_val;
+      else
+	nextpc = get_frame_register_unsigned (frame, bits (inst1, 3, 6));
+
+      nextpc = MAKE_THUMB_ADDR (nextpc);
+    }
   else if ((inst1 & 0xf500) == 0xb100)
     {
       /* CBNZ or CBZ.  */
@@ -6412,6 +7936,22 @@
   return osabi;
 }
 
+static int
+arm_register_reggroup_p (struct gdbarch *gdbarch, int regnum,
+			  struct reggroup *group)
+{
+  /* FPS register's type is INT, but belongs to float_reggroup.  Beside
+     this, FPS register belongs to save_regroup, restore_reggroup, and
+     all_reggroup, of course.  */
+  if (regnum == ARM_FPS_REGNUM)
+    return (group == float_reggroup
+	    || group == save_reggroup
+	    || group == restore_reggroup
+	    || group == all_reggroup);
+  else
+    return default_register_reggroup_p (gdbarch, regnum, group);
+}
+
 
 /* Initialize the current architecture based on INFO.  If possible,
    re-use an architecture from ARCHES, which is a list of
@@ -6818,6 +8358,9 @@
   /* Advance PC across function entry code.  */
   set_gdbarch_skip_prologue (gdbarch, arm_skip_prologue);
 
+  /* Detect whether PC is in function epilogue.  */
+  set_gdbarch_in_function_epilogue_p (gdbarch, arm_in_function_epilogue_p);
+
   /* Skip trampolines.  */
   set_gdbarch_skip_trampoline_code (gdbarch, arm_skip_stub);
 
@@ -6830,11 +8373,11 @@
 					 arm_remote_breakpoint_from_pc);
 
   /* Information about registers, etc.  */
-  set_gdbarch_deprecated_fp_regnum (gdbarch, ARM_FP_REGNUM);	/* ??? */
   set_gdbarch_sp_regnum (gdbarch, ARM_SP_REGNUM);
   set_gdbarch_pc_regnum (gdbarch, ARM_PC_REGNUM);
   set_gdbarch_num_regs (gdbarch, ARM_NUM_REGS);
   set_gdbarch_register_type (gdbarch, arm_register_type);
+  set_gdbarch_register_reggroup_p (gdbarch, arm_register_reggroup_p);
 
   /* This "info float" is FPA-specific.  Use the generic version if we
      do not have FPA.  */
@@ -6874,6 +8417,7 @@
   /* Add some default predicates.  */
   frame_unwind_append_unwinder (gdbarch, &arm_stub_unwind);
   dwarf2_append_unwinders (gdbarch);
+  frame_unwind_append_unwinder (gdbarch, &arm_exidx_unwind);
   frame_unwind_append_unwinder (gdbarch, &arm_prologue_unwind);
 
   /* Now we have tuned the configuration, set a few final things,
@@ -6884,6 +8428,9 @@
   if (tdep->arm_abi == ARM_ABI_AUTO)
     tdep->arm_abi = ARM_ABI_APCS;
 
+  /* Watchpoints are not steppable.  */
+  set_gdbarch_have_nonsteppable_watchpoint (gdbarch, 1);
+
   /* We used to default to FPA for generic ARM, but almost nobody
      uses that now, and we now provide a way for the user to force
      the model.  So default to the most useful variant.  */
@@ -6976,6 +8523,11 @@
   arm_objfile_data_key
     = register_objfile_data_with_cleanup (NULL, arm_objfile_data_free);
 
+  /* Add ourselves to objfile event chain.  */
+  observer_attach_new_objfile (arm_exidx_new_objfile);
+  arm_exidx_data_key
+    = register_objfile_data_with_cleanup (NULL, arm_exidx_data_free);
+
   /* Register an ELF OS ABI sniffer for ARM binaries.  */
   gdbarch_register_osabi_sniffer (bfd_arch_arm,
 				  bfd_target_elf_flavour,

=== modified file 'gdb/arm-tdep.h'
--- a/gdb/arm-tdep.h	2010-08-30 15:33:03 +0000
+++ b/gdb/arm-tdep.h	2011-02-21 15:28:07 +0000
@@ -307,6 +307,10 @@
 				      struct displaced_step_closure *,
 				      CORE_ADDR, CORE_ADDR, struct regcache *);
 
+/* Is the instruction at the given memory address a Thumb or ARM
+   instruction?  */
+extern int arm_pc_is_thumb (CORE_ADDR);
+
 /* Functions exported from armbsd-tdep.h.  */
 
 /* Return the appropriate register set for the core section identified

=== modified file 'gdb/breakpoint.c'
--- a/gdb/breakpoint.c	2010-07-28 18:00:01 +0000
+++ b/gdb/breakpoint.c	2011-02-21 15:26:42 +0000
@@ -1313,11 +1313,6 @@
   if (!watchpoint_in_thread_scope (b))
     return;
 
-  /* We don't free locations.  They are stored in bp_location array and
-     update_global_locations will eventually delete them and remove
-     breakpoints if needed.  */
-  b->loc = NULL;
-
   if (b->disposition == disp_del_at_next_stop)
     return;
  
@@ -1328,7 +1323,15 @@
     within_current_scope = 1;
   else
     {
-      struct frame_info *fi;
+      struct frame_info *fi = get_current_frame ();
+      struct gdbarch *frame_arch = get_frame_arch (fi);
+      CORE_ADDR frame_pc = get_frame_pc (fi);
+
+      /* If we're in a function epilogue, unwinding may not work
+	 properly, so do not attempt to recreate locations at this
+	 point.  See similar comments in watchpoint_check.  */
+      if (gdbarch_in_function_epilogue_p (frame_arch, frame_pc))
+	return;
 
       /* Save the current frame's ID so we can restore it after
          evaluating the watchpoint expression on its own frame.  */
@@ -1344,6 +1347,11 @@
 	select_frame (fi);
     }
 
+  /* We don't free locations.  They are stored in the bp_location array
+     and update_global_location_list will eventually delete them and
+     remove breakpoints if needed.  */
+  b->loc = NULL;
+
   if (within_current_scope && reparse)
     {
       char *s;

=== modified file 'gdb/dwarf2read.c'
--- a/gdb/dwarf2read.c	2010-08-27 18:37:16 +0000
+++ b/gdb/dwarf2read.c	2011-02-04 18:14:04 +0000
@@ -4184,10 +4184,22 @@
 	  return 0;
 	}
 
+      if (range_beginning > range_end)
+	{
+	  /* Inverted range entries are invalid.  */
+	  complaint (&symfile_complaints,
+		     _("Invalid .debug_ranges data (inverted range)"));
+	  return 0;
+	}
+
+      /* Empty range entries have no effect.  */
+      if (range_beginning == range_end)
+	continue;
+
       range_beginning += base;
       range_end += base;
 
-      if (ranges_pst != NULL && range_beginning < range_end)
+      if (ranges_pst != NULL)
 	addrmap_set_empty (objfile->psymtabs_addrmap,
 			   range_beginning + baseaddr, range_end - 1 + baseaddr,
 			   ranges_pst);
@@ -4468,6 +4480,19 @@
                   return;
                 }
 
+	      if (start > end)
+		{
+		  /* Inverted range entries are invalid.  */
+		  complaint (&symfile_complaints,
+			     _("Invalid .debug_ranges data "
+			       "(inverted range)"));
+		  return;
+		}
+
+	      /* Empty range entries have no effect.  */
+	      if (start == end)
+		continue;
+
               record_block_range (block,
                                   baseaddr + base + start,
                                   baseaddr + base + end - 1);
@@ -7330,9 +7355,6 @@
     }
 
   /* Set default names for some unnamed DIEs.  */
-  if (part_die->name == NULL && (part_die->tag == DW_TAG_structure_type
-				 || part_die->tag == DW_TAG_class_type))
-    part_die->name = "(anonymous class)";
 
   if (part_die->name == NULL && part_die->tag == DW_TAG_namespace)
     part_die->name = "(anonymous namespace)";

=== modified file 'gdb/features/arm-core.xml'
--- a/gdb/features/arm-core.xml	2010-01-01 07:31:28 +0000
+++ b/gdb/features/arm-core.xml	2011-02-03 14:26:13 +0000
@@ -7,19 +7,19 @@
 
 <!DOCTYPE feature SYSTEM "gdb-target.dtd">
 <feature name="org.gnu.gdb.arm.core">
-  <reg name="r0" bitsize="32"/>
-  <reg name="r1" bitsize="32"/>
-  <reg name="r2" bitsize="32"/>
-  <reg name="r3" bitsize="32"/>
-  <reg name="r4" bitsize="32"/>
-  <reg name="r5" bitsize="32"/>
-  <reg name="r6" bitsize="32"/>
-  <reg name="r7" bitsize="32"/>
-  <reg name="r8" bitsize="32"/>
-  <reg name="r9" bitsize="32"/>
-  <reg name="r10" bitsize="32"/>
-  <reg name="r11" bitsize="32"/>
-  <reg name="r12" bitsize="32"/>
+  <reg name="r0" bitsize="32" type="uint32"/>
+  <reg name="r1" bitsize="32" type="uint32"/>
+  <reg name="r2" bitsize="32" type="uint32"/>
+  <reg name="r3" bitsize="32" type="uint32"/>
+  <reg name="r4" bitsize="32" type="uint32"/>
+  <reg name="r5" bitsize="32" type="uint32"/>
+  <reg name="r6" bitsize="32" type="uint32"/>
+  <reg name="r7" bitsize="32" type="uint32"/>
+  <reg name="r8" bitsize="32" type="uint32"/>
+  <reg name="r9" bitsize="32" type="uint32"/>
+  <reg name="r10" bitsize="32" type="uint32"/>
+  <reg name="r11" bitsize="32" type="uint32"/>
+  <reg name="r12" bitsize="32" type="uint32"/>
   <reg name="sp" bitsize="32" type="data_ptr"/>
   <reg name="lr" bitsize="32"/>
   <reg name="pc" bitsize="32" type="code_ptr"/>

=== modified file 'gdb/features/arm-with-iwmmxt.c'
--- a/gdb/features/arm-with-iwmmxt.c	2009-06-23 16:59:42 +0000
+++ b/gdb/features/arm-with-iwmmxt.c	2011-02-03 14:26:13 +0000
@@ -1,6 +1,7 @@
 /* THIS FILE IS GENERATED.  Original: arm-with-iwmmxt.xml */
 
 #include "defs.h"
+#include "osabi.h"
 #include "target-descriptions.h"
 
 struct target_desc *tdesc_arm_with_iwmmxt;
@@ -14,19 +15,19 @@
   set_tdesc_architecture (result, bfd_scan_arch ("iwmmxt"));
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
-  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");

=== modified file 'gdb/features/arm-with-neon.c'
--- a/gdb/features/arm-with-neon.c	2009-07-28 18:26:49 +0000
+++ b/gdb/features/arm-with-neon.c	2011-02-03 14:26:13 +0000
@@ -1,7 +1,7 @@
 /* THIS FILE IS GENERATED.  Original: arm-with-neon.xml */
 
 #include "defs.h"
-#include "gdbtypes.h"
+#include "osabi.h"
 #include "target-descriptions.h"
 
 struct target_desc *tdesc_arm_with_neon;
@@ -10,22 +10,22 @@
 {
   struct target_desc *result = allocate_target_description ();
   struct tdesc_feature *feature;
-  struct type *field_type, *type;
+  struct tdesc_type *field_type, *type;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
-  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");

=== modified file 'gdb/features/arm-with-vfpv2.c'
--- a/gdb/features/arm-with-vfpv2.c	2009-07-28 18:26:49 +0000
+++ b/gdb/features/arm-with-vfpv2.c	2011-02-03 14:26:13 +0000
@@ -1,7 +1,7 @@
 /* THIS FILE IS GENERATED.  Original: arm-with-vfpv2.xml */
 
 #include "defs.h"
-#include "gdbtypes.h"
+#include "osabi.h"
 #include "target-descriptions.h"
 
 struct target_desc *tdesc_arm_with_vfpv2;
@@ -10,22 +10,22 @@
 {
   struct target_desc *result = allocate_target_description ();
   struct tdesc_feature *feature;
-  struct type *field_type, *type;
+  struct tdesc_type *field_type, *type;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
-  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");

=== modified file 'gdb/features/arm-with-vfpv3.c'
--- a/gdb/features/arm-with-vfpv3.c	2009-07-28 18:26:49 +0000
+++ b/gdb/features/arm-with-vfpv3.c	2011-02-03 14:26:13 +0000
@@ -1,7 +1,7 @@
 /* THIS FILE IS GENERATED.  Original: arm-with-vfpv3.xml */
 
 #include "defs.h"
-#include "gdbtypes.h"
+#include "osabi.h"
 #include "target-descriptions.h"
 
 struct target_desc *tdesc_arm_with_vfpv3;
@@ -10,22 +10,22 @@
 {
   struct target_desc *result = allocate_target_description ();
   struct tdesc_feature *feature;
-  struct type *field_type, *type;
+  struct tdesc_type *field_type, *type;
 
   feature = tdesc_create_feature (result, "org.gnu.gdb.arm.core");
-  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "int");
-  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "int");
+  tdesc_create_reg (feature, "r0", 0, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r1", 1, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r2", 2, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r3", 3, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r4", 4, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r5", 5, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r6", 6, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r7", 7, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r8", 8, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r9", 9, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r10", 10, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r11", 11, 1, NULL, 32, "uint32");
+  tdesc_create_reg (feature, "r12", 12, 1, NULL, 32, "uint32");
   tdesc_create_reg (feature, "sp", 13, 1, NULL, 32, "data_ptr");
   tdesc_create_reg (feature, "lr", 14, 1, NULL, 32, "int");
   tdesc_create_reg (feature, "pc", 15, 1, NULL, 32, "code_ptr");

=== modified file 'gdb/inflow.c'
--- a/gdb/inflow.c	2010-05-14 21:25:50 +0000
+++ b/gdb/inflow.c	2011-03-04 19:26:12 +0000
@@ -202,10 +202,9 @@
       struct inferior *inf = current_inferior ();
       struct terminal_info *tinfo = get_inflow_inferior_data (inf);
 
-      /* We could just as well copy our_ttystate (if we felt like
-         adding a new function serial_copy_tty_state()).  */
       xfree (tinfo->ttystate);
-      tinfo->ttystate = serial_get_tty_state (stdin_serial);
+      tinfo->ttystate = serial_copy_tty_state (stdin_serial,
+					       our_terminal_info.ttystate);
 
 #ifdef PROCESS_GROUP_TYPE
       tinfo->process_group = pgrp;
@@ -227,8 +226,6 @@
 {
   if (gdb_has_a_terminal ())
     {
-      /* We could just as well copy our_ttystate (if we felt like adding
-         a new function serial_copy_tty_state).  */
       xfree (our_terminal_info.ttystate);
       our_terminal_info.ttystate = serial_get_tty_state (stdin_serial);
     }
@@ -472,6 +469,7 @@
   if (info != NULL)
     {
       xfree (info->run_terminal);
+      xfree (info->ttystate);
       xfree (info);
     }
 }
@@ -509,6 +507,7 @@
   if (info != NULL)
     {
       xfree (info->run_terminal);
+      xfree (info->ttystate);
       xfree (info);
       set_inferior_data (inf, inflow_inferior_data, NULL);
     }
@@ -521,10 +520,19 @@
 
   tinfo_to = get_inflow_inferior_data (to);
   tinfo_from = get_inflow_inferior_data (from);
+
+  xfree (tinfo_to->run_terminal);
+  xfree (tinfo_to->ttystate);
+
   *tinfo_to = *tinfo_from;
+
   if (tinfo_from->run_terminal)
     tinfo_to->run_terminal
       = xstrdup (tinfo_from->run_terminal);
+
+  if (tinfo_from->ttystate)
+    tinfo_to->ttystate
+      = serial_copy_tty_state (stdin_serial, tinfo_from->ttystate);
 }
 
 void

=== modified file 'gdb/infrun.c'
--- a/gdb/infrun.c	2010-08-31 19:31:22 +0000
+++ b/gdb/infrun.c	2010-09-13 14:38:38 +0000
@@ -1549,6 +1549,25 @@
 
   QUIT;
 
+  /* Don't try to single-step a vfork parent that is waiting for
+     the child to get out of the shared memory region (by exec'ing
+     or exiting).  This is particularly important on software
+     single-step archs, as the child process would trip on the
+     software single step breakpoint inserted for the parent
+     process.  Since the parent will not actually execute any
+     instruction until the child is out of the shared region (such
+     are vfork's semantics), it is safe to simply continue it.
+     Eventually, we'll see a TARGET_WAITKIND_VFORK_DONE event for
+     the parent, and tell it to `keep_going', which automatically
+     re-sets it stepping.  */
+  if (current_inferior ()->waiting_for_vfork_done)
+    {
+      if (debug_infrun)
+	fprintf_unfiltered (gdb_stdlog,
+			    "infrun: resume : clear step\n");
+      step = 0;
+    }
+
   if (debug_infrun)
     fprintf_unfiltered (gdb_stdlog,
                         "infrun: resume (step=%d, signal=%d), "
@@ -1576,11 +1595,16 @@
      We can't use displaced stepping when we have a signal to deliver;
      the comments for displaced_step_prepare explain why.  The
      comments in the handle_inferior event for dealing with 'random
-     signals' explain what we do instead.  */
+     signals' explain what we do instead.
+
+     We can't use displaced stepping when we are waiting for vfork_done
+     event, displaced stepping breaks the vfork child similarly as single
+     step software breakpoint.  */
   if (use_displaced_stepping (gdbarch)
       && (tp->trap_expected
 	  || (step && gdbarch_software_single_step_p (gdbarch)))
-      && sig == TARGET_SIGNAL_0)
+      && sig == TARGET_SIGNAL_0
+      && !current_inferior ()->waiting_for_vfork_done)
     {
       struct displaced_step_inferior_state *displaced;
 

=== modified file 'gdb/ser-base.c'
--- a/gdb/ser-base.c	2010-05-16 23:49:57 +0000
+++ b/gdb/ser-base.c	2011-03-04 19:26:12 +0000
@@ -461,6 +461,13 @@
   return (serial_ttystate) XMALLOC (int);
 }
 
+serial_ttystate
+ser_base_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
+{
+  /* Allocate another dummy.  */
+  return (serial_ttystate) XMALLOC (int);
+}
+
 int
 ser_base_set_tty_state (struct serial *scb, serial_ttystate ttystate)
 {

=== modified file 'gdb/ser-base.h'
--- a/gdb/ser-base.h	2010-04-29 22:51:00 +0000
+++ b/gdb/ser-base.h	2011-03-04 19:26:12 +0000
@@ -31,6 +31,8 @@
 extern int ser_base_send_break (struct serial *scb);
 extern void ser_base_raw (struct serial *scb);
 extern serial_ttystate ser_base_get_tty_state (struct serial *scb);
+extern serial_ttystate ser_base_copy_tty_state (struct serial *scb,
+						serial_ttystate ttystate);
 extern int ser_base_set_tty_state (struct serial *scb,
 				   serial_ttystate ttystate);
 extern void ser_base_print_tty_state (struct serial *scb,

=== modified file 'gdb/ser-go32.c'
--- a/gdb/ser-go32.c	2010-05-16 23:49:57 +0000
+++ b/gdb/ser-go32.c	2011-03-04 19:26:12 +0000
@@ -652,6 +652,17 @@
   return (serial_ttystate) state;
 }
 
+static serial_ttystate
+dos_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
+{
+  struct dos_ttystate *state;
+
+  state = (struct dos_ttystate *) xmalloc (sizeof *state);
+  *state = *(struct dos_ttystate *) ttystate;
+
+  return (serial_ttystate) state;
+}
+
 static int
 dos_set_tty_state (struct serial *scb, serial_ttystate ttystate)
 {
@@ -850,6 +861,7 @@
   dos_sendbreak,
   dos_raw,
   dos_get_tty_state,
+  dos_copy_tty_state,
   dos_set_tty_state,
   dos_print_tty_state,
   dos_noflush_set_tty_state,

=== modified file 'gdb/ser-mingw.c'
--- a/gdb/ser-mingw.c	2010-05-16 23:49:57 +0000
+++ b/gdb/ser-mingw.c	2011-03-04 19:26:12 +0000
@@ -1185,6 +1185,7 @@
   /* These are only used for stdin; we do not need them for serial
      ports, so supply the standard dummies.  */
   ops->get_tty_state = ser_base_get_tty_state;
+  ops->copy_tty_state = ser_base_copy_tty_state;
   ops->set_tty_state = ser_base_set_tty_state;
   ops->print_tty_state = ser_base_print_tty_state;
   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
@@ -1213,6 +1214,7 @@
 
   ops->close = ser_console_close;
   ops->get_tty_state = ser_console_get_tty_state;
+  ops->copy_tty_state = ser_base_copy_tty_state;
   ops->set_tty_state = ser_base_set_tty_state;
   ops->print_tty_state = ser_base_print_tty_state;
   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
@@ -1237,6 +1239,7 @@
   ops->send_break = ser_base_send_break;
   ops->go_raw = ser_base_raw;
   ops->get_tty_state = ser_base_get_tty_state;
+  ops->copy_tty_state = ser_base_copy_tty_state;
   ops->set_tty_state = ser_base_set_tty_state;
   ops->print_tty_state = ser_base_print_tty_state;
   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;
@@ -1271,6 +1274,7 @@
   ops->send_break = ser_tcp_send_break;
   ops->go_raw = ser_base_raw;
   ops->get_tty_state = ser_base_get_tty_state;
+  ops->copy_tty_state = ser_base_copy_tty_state;
   ops->set_tty_state = ser_base_set_tty_state;
   ops->print_tty_state = ser_base_print_tty_state;
   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;

=== modified file 'gdb/ser-pipe.c'
--- a/gdb/ser-pipe.c	2010-05-25 16:00:07 +0000
+++ b/gdb/ser-pipe.c	2011-03-04 19:26:12 +0000
@@ -191,6 +191,7 @@
   ops->send_break = ser_base_send_break;
   ops->go_raw = ser_base_raw;
   ops->get_tty_state = ser_base_get_tty_state;
+  ops->copy_tty_state = ser_base_copy_tty_state;
   ops->set_tty_state = ser_base_set_tty_state;
   ops->print_tty_state = ser_base_print_tty_state;
   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;

=== modified file 'gdb/ser-tcp.c'
--- a/gdb/ser-tcp.c	2010-05-26 22:40:21 +0000
+++ b/gdb/ser-tcp.c	2011-03-04 19:26:12 +0000
@@ -388,6 +388,7 @@
   ops->send_break = ser_tcp_send_break;
   ops->go_raw = ser_base_raw;
   ops->get_tty_state = ser_base_get_tty_state;
+  ops->copy_tty_state = ser_base_copy_tty_state;
   ops->set_tty_state = ser_base_set_tty_state;
   ops->print_tty_state = ser_base_print_tty_state;
   ops->noflush_set_tty_state = ser_base_noflush_set_tty_state;

=== modified file 'gdb/ser-unix.c'
--- a/gdb/ser-unix.c	2010-05-16 23:49:57 +0000
+++ b/gdb/ser-unix.c	2011-03-04 19:26:12 +0000
@@ -188,6 +188,17 @@
   return (serial_ttystate) state;
 }
 
+static serial_ttystate
+hardwire_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
+{
+  struct hardwire_ttystate *state;
+
+  state = (struct hardwire_ttystate *) xmalloc (sizeof *state);
+  *state = *(struct hardwire_ttystate *) ttystate;
+
+  return (serial_ttystate) state;
+}
+
 static int
 hardwire_set_tty_state (struct serial *scb, serial_ttystate ttystate)
 {
@@ -905,6 +916,7 @@
   ops->send_break = hardwire_send_break;
   ops->go_raw = hardwire_raw;
   ops->get_tty_state = hardwire_get_tty_state;
+  ops->copy_tty_state = hardwire_copy_tty_state;
   ops->set_tty_state = hardwire_set_tty_state;
   ops->print_tty_state = hardwire_print_tty_state;
   ops->noflush_set_tty_state = hardwire_noflush_set_tty_state;

=== modified file 'gdb/serial.c'
--- a/gdb/serial.c	2010-05-16 23:49:57 +0000
+++ b/gdb/serial.c	2011-03-04 19:26:12 +0000
@@ -476,6 +476,12 @@
   return scb->ops->get_tty_state (scb);
 }
 
+serial_ttystate
+serial_copy_tty_state (struct serial *scb, serial_ttystate ttystate)
+{
+  return scb->ops->copy_tty_state (scb, ttystate);
+}
+
 int
 serial_set_tty_state (struct serial *scb, serial_ttystate ttystate)
 {

=== modified file 'gdb/serial.h'
--- a/gdb/serial.h	2010-05-02 21:14:54 +0000
+++ b/gdb/serial.h	2011-03-04 19:26:12 +0000
@@ -116,6 +116,12 @@
 
 extern serial_ttystate serial_get_tty_state (struct serial *scb);
 
+/* Return a pointer to a newly malloc'd ttystate containing a copy
+   of the state in TTYSTATE.  */
+
+extern serial_ttystate serial_copy_tty_state (struct serial *scb,
+					      serial_ttystate ttystate);
+
 /* Set the state of the tty to TTYSTATE.  The change is immediate.
    When changing to or from raw mode, input might be discarded.
    Returns 0 for success, negative value for error (in which case
@@ -231,6 +237,7 @@
     int (*send_break) (struct serial *);
     void (*go_raw) (struct serial *);
     serial_ttystate (*get_tty_state) (struct serial *);
+    serial_ttystate (*copy_tty_state) (struct serial *, serial_ttystate);
     int (*set_tty_state) (struct serial *, serial_ttystate);
     void (*print_tty_state) (struct serial *, serial_ttystate,
 			     struct ui_file *);

=== modified file 'gdb/testsuite/gdb.asm/asm-source.exp'
--- a/gdb/testsuite/gdb.asm/asm-source.exp	2010-06-10 19:48:18 +0000
+++ b/gdb/testsuite/gdb.asm/asm-source.exp	2011-02-03 17:12:24 +0000
@@ -40,10 +40,7 @@
         set asm-flags "-no-mdebug -I${srcdir}/${subdir} -I${objdir}/${subdir}"
 	set debug-flags "-gdwarf-2"
     }
-    "*arm-*-*" {
-        set asm-arch arm
-    }
-    "xscale-*-*" {
+    "arm*-*-*" {
         set asm-arch arm
     }
     "frv-*-*" {

=== modified file 'gdb/testsuite/gdb.base/break-interp.exp'
--- a/gdb/testsuite/gdb.base/break-interp.exp	2010-07-05 18:04:32 +0000
+++ b/gdb/testsuite/gdb.base/break-interp.exp	2010-10-12 18:46:03 +0000
@@ -108,45 +108,87 @@
     }
 }
 
+# Implementation of reach.
+
+proc reach_1 {func command displacement} {
+    global gdb_prompt expect_out
+
+    if {$func == "_dl_debug_state"} {
+	# Breakpoint on _dl_debug_state can have problems due to its overlap
+	# with the existing internal breakpoint from GDB.
+	gdb_test_no_output "set stop-on-solib-events 1"
+    } elseif {! [gdb_breakpoint $func allow-pending]} {
+	return
+    }
+
+    set test "reach"
+    set test_displacement "seen displacement message as $displacement"
+    set debug_state_count 0
+    gdb_test_multiple $command $test {
+	-re "Using PIE \\(Position Independent Executable\\) displacement (0x\[0-9a-f\]+) " {
+	    # Missing "$gdb_prompt $" is intentional.
+	    if {$expect_out(1,string) == "0x0"} {
+		set case "ZERO"
+	    } else {
+		set case "NONZERO"
+	    }
+	    if {$displacement == $case || $displacement == "PRESENT"} {
+		pass $test_displacement
+		set displacement "FOUND-$displacement"
+	    } else {
+		fail $test_displacement
+	    }
+	    exp_continue
+	}
+	-re "Breakpoint \[0-9\]+, \\.?$func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" {
+	    if {$func == "_dl_debug_state"} {
+		fail $test
+	    } else {
+		pass $test
+	    }
+	}
+	-re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in \\.?$func \\(\\).*\r\n$gdb_prompt $" {
+	    if {$func == "_dl_debug_state"} {
+		fail $test
+	    } else {
+		pass $test
+	    }
+	}
+	-re "Stopped due to shared library event\r\n$gdb_prompt $" {
+	    if {$func == "_dl_debug_state"} {
+		if {$debug_state_count == 0} {
+		    # First stop does not yet relocate the _start function
+		    # descriptor on ppc64.
+		    set debug_state_count 1
+		    send_gdb "continue\n"
+		    exp_continue
+		} else {
+		    pass $test
+		}
+	    } else {
+		fail $test
+	    }
+	}
+    }
+    if ![regexp {^(NONE|FOUND-.*)$} $displacement] {
+	fail $test_displacement
+    }
+
+    if {$func == "_dl_debug_state"} {
+	gdb_test_no_output "set stop-on-solib-events 0"
+    }
+}
+
 # `runto' does not check we stopped really at the function we specified.
-# DISPLACEMENT can be "NONE", "ZERO" or "NONZERO"
+# DISPLACEMENT can be "NONE" for no message to be present, "ZERO" for
+# displacement of 0 bytes to be present, "NONZERO" for displacement of non-0
+# bytes to be present and "PRESENT" if both "ZERO" and "NONZERO" are valid.
 proc reach {func command displacement} {
-    global gdb_prompt expect_out
-
     global pf_prefix
     set old_ldprefix $pf_prefix
     lappend pf_prefix "reach-$func:"
 
-    if [gdb_breakpoint $func allow-pending] {
-	set test "reach"
-	set test_displacement "seen displacement message as $displacement"
-	gdb_test_multiple $command $test {
-	    -re "Using PIE \\(Position Independent Executable\\) displacement (0x\[0-9a-f\]+) " {
-		# Missing "$gdb_prompt $" is intentional.
-		if {$expect_out(1,string) == "0x0"} {
-		    set case "ZERO"
-		} else {
-		    set case "NONZERO"
-		}
-		if {$displacement == $case} {
-		    pass $test_displacement
-		    set displacement "FOUND-$displacement"
-		} else {
-		    fail $test_displacement
-		}
-		exp_continue
-	    }
-	    -re "Breakpoint \[0-9\]+, $func \\(.*\\) at .*:\[0-9\]+\r\n.*$gdb_prompt $" {
-		pass $test
-	    }
-	    -re "Breakpoint \[0-9\]+, \[0-9xa-f\]+ in $func \\(\\).*\r\n$gdb_prompt $" {
-		pass $test
-	    }
-	}
-	if ![regexp {^(NONE|FOUND-.*)$} $displacement] {
-	    fail $test_displacement
-	}
-    }
+    reach_1 $func $command $displacement
 
     set pf_prefix $old_ldprefix
 }
@@ -184,7 +226,7 @@
 	    } else {
 		set case "NONZERO"
 	    }
-	    if {$displacement == $case} {
+	    if {$displacement == $case || $displacement == "PRESENT"} {
 		pass $test_displacement
 		set displacement "FOUND-$displacement"
 	    } else {
@@ -241,7 +283,7 @@
 	    } else {
 		set case "NONZERO"
 	    }
-	    if {$displacement == $case} {
+	    if {$displacement == $case || $displacement == "PRESENT"} {
 		pass $test_displacement
 		set displacement "FOUND-$displacement"
 	    } else {
@@ -342,9 +384,18 @@
     # prevents that from happening.  So turn it off.
     gdb_test "set disable-randomization off"
 
-    reach "dl_main" "run segv" $displacement
-
-    gdb_test "bt" "#0 +\[^\r\n\]*\\mdl_main\\M.*" "dl bt"
+    if $ifmain {
+	gdb_test_no_output "set args segv"
+    } else {
+	global objdir binfile_test
+
+	# ld.so needs some executable to run to reach _dl_debug_state.
+	gdb_test_no_output "set args ${objdir}/${subdir}/$binfile_test"
+    }
+
+    reach "_dl_debug_state" "run" $displacement
+
+    gdb_test "bt" "#0 +\[^\r\n\]*\\m_dl_debug_state\\M.*" "dl bt"
 
     if $ifmain {
 	reach "main" continue "NONE"
@@ -356,7 +407,7 @@
 
     # Try re-run if the new PIE displacement takes effect.
     gdb_test "kill" "" "kill" {Kill the program being debugged\? \(y or n\) } "y"
-    reach "dl_main" "run segv" $displacement
+    reach "_dl_debug_state" "run" $displacement
 
     if $ifmain {
 	test_core $file $displacement
@@ -389,14 +440,32 @@
     gdb_test "exec-file $file" "exec-file $escapedfile" "load"
 
     if $ifmain {
-	reach "dl_main" run $displacement
+	reach "_dl_debug_state" run $displacement
 
+	# Use two separate gdb_test_multiple statements to avoid timeouts due
+	# to slow processing of wildcard capturing long output
 	set test "info files"
 	set entrynohex ""
 	gdb_test_multiple $test $test {
-	    -re "\r\n\[\t \]*Entry point:\[\t \]*0x(\[0-9a-f\]+)\r\n.*$gdb_prompt $" {
+	    -re "\r\n\[\t \]*Entry point:\[\t \]*0x(\[0-9a-f\]+)\r\n" {
 		set entrynohex $expect_out(1,string)
-		pass $test
+		gdb_test_multiple "" $test {
+		    -re "\r\n$gdb_prompt $" {
+			pass $test
+		    }
+		}
+	    }
+	}
+
+	# `info sym' cannot be tested for .opd as the binary may not have
+	# symbols.
+	if {[istarget powerpc64-*] && [is_lp64_target]} {
+	    set test "convert entry point"
+	    gdb_test_multiple "p *(void(*)(void) *) 0x$entrynohex" $test {
+		-re " =( \\(\[^0-9\]*\\))? 0x(\[0-9a-f\]+)( < \[^\r\n\]*)?\r\n$gdb_prompt $" {
+		    set entrynohex $expect_out(2,string)
+		    pass $test
+		}
 	    }
 	}
 	if {$entrynohex != ""} {
@@ -417,7 +486,7 @@
 		} else {
 		    set case "NONZERO"
 		}
-		if {$displacement == $case} {
+		if {$displacement == $case || $displacement == "PRESENT"} {
 		    pass $test_displacement
 		    set displacement "FOUND-$displacement"
 		} else {
@@ -522,7 +591,10 @@
 	if {$ldprelink == "NO"} {
 	    set displacement "NONZERO"
 	} else {
-	    set displacement "ZERO"
+	    # x86* kernel loads prelinked PIE binary at its prelinked address
+	    # but ppc* kernel loads it at a random address.  prelink normally
+	    # skips PIE binaries during the system scan.
+	    set displacement "PRESENT"
 	}
 	test_ld $interp 0 [expr {$ldsepdebug == "NO"}] $displacement
 
@@ -571,7 +643,11 @@
 		    } elseif {$binprelink == "NO"} {
 			set displacement "NONZERO"
 		    } else {
-			set displacement "ZERO"
+			# x86* kernel loads prelinked PIE binary at its
+			# prelinked address but ppc* kernel loads it at
+			# a random address.  prelink normally skips PIE
+			# binaries during the system scan.
+			set displacement "PRESENT"
 		    }
 
 		    if {[prelink$binprelink $relink_args [file tail $exec]]

=== modified file 'gdb/testsuite/gdb.base/dup-sect.exp'
--- a/gdb/testsuite/gdb.base/dup-sect.exp	2010-03-25 20:29:27 +0000
+++ b/gdb/testsuite/gdb.base/dup-sect.exp	2011-02-03 17:12:24 +0000
@@ -27,7 +27,8 @@
 if {![istarget *-*-linux*]
     && ![istarget *-*-gnu*]
     && ![istarget *-*-elf*]
-    && ![istarget arm-*-eabi*]
+    && ![istarget arm*-*-eabi*]
+    && ![istarget arm*-*-symbianelf*]
     && ![istarget powerpc-*-eabi*]} {
     return 0
 }

=== modified file 'gdb/testsuite/gdb.base/foll-fork.exp'
--- a/gdb/testsuite/gdb.base/foll-fork.exp	2010-06-01 21:29:21 +0000
+++ b/gdb/testsuite/gdb.base/foll-fork.exp	2010-10-19 21:37:15 +0000
@@ -122,7 +122,7 @@
 
     set bp_after_fork [gdb_get_line_number "set breakpoint here"]
 
-    gdb_test "catch fork" "Catchpoint .*(fork).*" \
+    gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" \
 	"explicit child follow, set catch fork"
 
     # Verify that the catchpoint is mentioned in an "info breakpoints",
@@ -136,7 +136,7 @@
     }
 
     gdb_test "continue" \
-	"Catchpoint.*(forked process.*),.*in .*(fork|__kernel_v?syscall).*" \
+	"Catchpoint \[0-9\]* \\(forked process \[0-9\]*\\),.*" \
 	"explicit child follow, catch fork"
 
     # Verify that the catchpoint is mentioned in an "info breakpoints",
@@ -184,7 +184,7 @@
 	"unpatch child, set catch fork"
 
     gdb_test "continue" \
-	"Catchpoint.*\\(forked process.*\\).*,.*in .*(fork|__kernel_v?syscall).*" \
+	"Catchpoint \[0-9\]* \\(forked process \[0-9\]*\\),.*" \
 	"unpatch child, catch fork"
 
     # Delete all breakpoints and catchpoints.
@@ -225,14 +225,15 @@
 
     set bp_after_fork [gdb_get_line_number "set breakpoint here"]
 
-    gdb_test "catch fork" "Catchpoint .*(fork).*" \
+    gdb_test "catch fork" "Catchpoint \[0-9\]* \\(fork\\)" \
 	"explicit parent follow, set tcatch fork"
 
 # ??rehrauer: I don't yet know how to get the id of the tcatch
 # via this script, so that I can add a -do list to it.  For now,
 # do the follow stuff after the catch happens.
 
-    gdb_test "continue" "in .*(fork|__kernel_v?syscall).*" \
+    gdb_test "continue" \
+	"Catchpoint \[0-9\]* \\(forked process \[0-9\]*\\),.*" \
 	"explicit parent follow, tcatch fork"
 
     gdb_test_no_output "set follow-fork parent"

=== modified file 'gdb/testsuite/gdb.base/hbreak.exp'
--- a/gdb/testsuite/gdb.base/hbreak.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.base/hbreak.exp	2011-02-21 15:21:16 +0000
@@ -13,12 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Arch not supporting hw watchpoints does not imply no_hardware_watchpoints set.
-if {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]
-     && ![istarget "ia64-*-*"])
-    || [target_info exists gdb,no_hardware_watchpoints]} then {
-    verbose "Skipping hbreak test."
-    return
+if {[skip_hw_breakpoint_tests]} {
+    return 0
 }
 
 set test hbreak

=== modified file 'gdb/testsuite/gdb.base/maint.exp'
--- a/gdb/testsuite/gdb.base/maint.exp	2010-06-10 19:48:18 +0000
+++ b/gdb/testsuite/gdb.base/maint.exp	2010-09-14 18:23:44 +0000
@@ -149,14 +149,18 @@
 	set timeout [expr $timeout + 500]
 }
 
-gdb_test_multiple "maint print statistics" "maint print statistics" {
-    -re "Statistics for.*break.*Number of \"minimal\" symbols read.*Number of \"partial\" symbols read.*Number of \"types\" defined.*Number of psym tables \\(not yet expanded\\).*Number of symbol tables.*Number of symbol tables with line tables.*Number of symbol tables with blockvectors.*Total memory used for psymbol obstack.*Total memory used for psymbol cache.*Total memory used for symbol obstack.*Total memory used for type obstack.*$gdb_prompt $" { 
-	# Old output for gdb 6.0 and earlier
-	pass "maint print statistics" 
-    }
-    -re "Statistics for.*break.*Number of \"minimal\" symbols read.*Number of \"partial\" symbols read.*Number of \"types\" defined.*Number of psym tables \\(not yet expanded\\).*Number of symbol tables.*Number of symbol tables with line tables.*Number of symbol tables with blockvectors.*Total memory used for objfile obstack.*Total memory used for psymbol cache.*Total memory used for macro cache.*$gdb_prompt $" {
-	pass "maint print statistics"
-    }
+send_gdb "maint print statistics\n"
+gdb_expect  {
+    -re "Statistics for\[^\n\r\]*break\[^\n\r\]*:\r\n  Number of \"minimal\" symbols read: $decimal\r\n  Number of \"partial\" symbols read: $decimal\r\n  Number of \"full\" symbols read: $decimal\r\n  Number of \"types\" defined: $decimal\r\n  Number of psym tables \\(not yet expanded\\): $decimal\r\n  Number of symbol tables: $decimal\r\n  Number of symbol tables with line tables: $decimal\r\n  Number of symbol tables with blockvectors: $decimal\r\n  Total memory used for objfile obstack: $decimal\r\n  Total memory used for psymbol cache: $decimal\r\n  Total memory used for macro cache: $decimal\r\n  Total memory used for file name cache: $decimal\r\n" {
+	gdb_expect {
+	    -re "$gdb_prompt $" {
+		pass "maint print statistics"
+	    }
+	    timeout { fail "(timeout) maint print statistics" }
+	}
+    }
+    -re ".*$gdb_prompt $"     { fail "maint print statistics" }
+    timeout         { fail "(timeout) maint print statistics" }
 }
 
 # There aren't any ...

=== modified file 'gdb/testsuite/gdb.base/pr11022.exp'
--- a/gdb/testsuite/gdb.base/pr11022.exp	2010-06-01 21:29:21 +0000
+++ b/gdb/testsuite/gdb.base/pr11022.exp	2011-02-21 15:21:16 +0000
@@ -17,10 +17,8 @@
     strace $tracelevel
 }
 
-if [target_info exists gdb,no_hardware_watchpoints] {
-    # This test requires HW watchpoints
-    untested pr11022.exp
-    return -1
+if {[skip_hw_watchpoint_tests]} {
+    return 0
 }
 
 set testfile "pr11022"

=== modified file 'gdb/testsuite/gdb.base/printcmds.exp'
--- a/gdb/testsuite/gdb.base/printcmds.exp	2010-08-19 15:50:00 +0000
+++ b/gdb/testsuite/gdb.base/printcmds.exp	2011-02-03 14:26:13 +0000
@@ -85,6 +85,18 @@
     gdb_test "p 0b1111" " = 15"
     gdb_test "p 0B1111" " = 15"
     gdb_test "p -0b1111" " = -15"
+
+    # Test hexadecimal floating point.
+    set test "p 0x1.1"
+    gdb_test_multiple $test $test {
+	-re " = 1\\.0625\r\n$gdb_prompt $" {
+	    pass $test
+	}
+	-re "Invalid number \"0x1\\.1\"\\.\r\n$gdb_prompt $" {
+	    # Older glibc does not support hex float, newer does.
+	    xfail $test
+	}
+    }
 }
 
 proc test_character_literals_accepted {} {
@@ -128,7 +140,6 @@
     test_print_reject "p 123DEADBEEF"
     test_print_reject "p 123foobar.bazfoo3"
     test_print_reject "p 123EEEEEEEEEEEEEEEEE33333k333"
-    test_print_reject "p 0x1.1"
     gdb_test "p 123.4+56.7" "180.(099\[0-9]*|100\[0-9\]*)" "check for floating addition"
 
     # Test various octal values.

=== modified file 'gdb/testsuite/gdb.base/watch-read.exp'
--- a/gdb/testsuite/gdb.base/watch-read.exp	2010-02-22 23:35:15 +0000
+++ b/gdb/testsuite/gdb.base/watch-read.exp	2011-02-21 15:21:16 +0000
@@ -27,9 +27,8 @@
 set testfile "watch-read"
 set srcfile ${testfile}.c
 
-if { [target_info exists gdb,no_hardware_watchpoints] } {
-    untested ${testfile}.exp
-    return -1
+if {[skip_hw_watchpoint_access_tests]} {
+    return 0
 }
 
 if { [prepare_for_testing ${testfile}.exp ${testfile} ${srcfile}] } {

=== modified file 'gdb/testsuite/gdb.base/watch_thread_num.exp'
--- a/gdb/testsuite/gdb.base/watch_thread_num.exp	2010-06-03 23:54:17 +0000
+++ b/gdb/testsuite/gdb.base/watch_thread_num.exp	2011-02-21 15:21:16 +0000
@@ -23,6 +23,12 @@
 	strace $tracelevel
 }
 
+# This test verifies that a watchpoint is detected in the proper thread
+# so the test is only meaningful on a system with hardware watchpoints.
+if {[skip_hw_watchpoint_tests]} {
+    return 0
+}
+
 set testfile watch_thread_num
 set srcfile ${testfile}.c
 set binfile ${objdir}/${subdir}/${testfile}
@@ -47,11 +53,6 @@
    return
 }
 
-# Disable hardware watchpoints if necessary.
-if [target_info exists gdb,no_hardware_watchpoints] {
-    gdb_test_no_output "set can-use-hw-watchpoints 0" ""
-}
-
 gdb_test "watch shared_var thread 0" "Unknown thread 0\." "Watchpoint on invalid thread"
 gdb_test "watch shared_var thread" "A syntax error in expression, near `thread'\." "Invalid watch syntax"
 
@@ -71,14 +72,14 @@
 set thread_num "$expect_out(1,string)"
 
 gdb_test_no_output "disable 2" "Disable breakpoint 2"
-gdb_test "watch shared_var thread $thread_num" "atchpoint 3: shared_var" "Watchpoint on shared variable"
+gdb_test "watch shared_var thread $thread_num" "Hardware watchpoint 3: shared_var" "Watchpoint on shared variable"
 gdb_test "info breakpoint 3" "stop only in thread $thread_num"
 
 for {set i 1} {$i <= 10} {incr i 1} {
     set watchpoint "Watchpoint triggered iteration $i"
     set check "Check thread that triggered iteration $i"
 
-    gdb_test "continue" "atchpoint 3: shared_var.*" $watchpoint
+    gdb_test "continue" "Hardware watchpoint 3: shared_var.*" $watchpoint
     gdb_test "thread" ".*Current thread is $thread_num .*" $check
 }
 

=== modified file 'gdb/testsuite/gdb.base/watchpoint-hw-hit-once.exp'
--- a/gdb/testsuite/gdb.base/watchpoint-hw-hit-once.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.base/watchpoint-hw-hit-once.exp	2011-02-21 15:21:16 +0000
@@ -13,12 +13,8 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Arch not supporting hw watchpoints does not imply no_hardware_watchpoints set.
-if {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]
-     && ![istarget "ia64-*-*"])
-    || [target_info exists gdb,no_hardware_watchpoints]} then {
-    verbose "Skipping watchpoint-hw-hit-once test."
-    return
+if {[skip_hw_watchpoint_access_tests]} {
+    return 0
 }
 
 set test watchpoint-hw-hit-once

=== modified file 'gdb/testsuite/gdb.base/watchpoint-hw.exp'
--- a/gdb/testsuite/gdb.base/watchpoint-hw.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.base/watchpoint-hw.exp	2011-02-21 15:21:16 +0000
@@ -13,12 +13,9 @@
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
 
-# Arch not supporting hw watchpoints does not imply no_hardware_watchpoints set.
-if {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]
-     && ![istarget "ia64-*-*"] && ![istarget "s390*-*-*"])
-    || [target_info exists gdb,no_hardware_watchpoints]} then {
-    verbose "Skipping watchpoint-hw test."
-    return
+
+if {[skip_hw_watchpoint_tests]} {
+    return 0
 }
 
 set testfile watchpoint-hw

=== modified file 'gdb/testsuite/gdb.dwarf2/callframecfa.exp'
--- a/gdb/testsuite/gdb.dwarf2/callframecfa.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/callframecfa.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test DW_OP_call_frame_cfa.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 # This test can only be run on x86 targets.

=== modified file 'gdb/testsuite/gdb.dwarf2/dup-psym.exp'
--- a/gdb/testsuite/gdb.dwarf2/dup-psym.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dup-psym.exp	2011-02-03 17:12:24 +0000
@@ -12,16 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Minimal DWARF-2 unit test
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-anonymous-func.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-anonymous-func.exp	2010-03-18 18:35:52 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-anonymous-func.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Minimal DWARF-2 unit test
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp	2010-03-31 18:13:37 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-bad-parameter-type.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-basic.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-basic.exp	2010-06-02 21:46:44 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-basic.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Minimal DWARF-2 unit test
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-compressed.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-compressed.exp	2010-06-02 21:46:44 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-compressed.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Minimal DWARF-2 unit test
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-cu-size.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-cu-size.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-cu-size.exp	2011-02-03 17:12:24 +0000
@@ -12,6 +12,7 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test inter-cu references where the referenced DIE is within
 # initial_length_size bytes of the end of the CU.
@@ -19,13 +20,7 @@
 # in the length of the CU.  */
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.exp	2010-03-22 16:53:19 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-empty-namespace.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test G++ 4.1 producing DW_TAG_namespace with DW_AT_name "::".
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-inheritance.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-inheritance.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-inheritance.exp	2011-02-03 17:12:24 +0000
@@ -12,18 +12,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test DW_TAG_inheritance using constant DW_AT_data_member_location
 # introduced by GCC PR debug/40659.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-intercu.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-intercu.exp	2010-06-02 21:46:44 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-intercu.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Minimal DWARF-2 unit test
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-intermix.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-intermix.exp	2010-06-02 21:46:44 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-intermix.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Intermixed 32-bit and 64-bit DWARF format tests.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.exp	2010-05-08 04:55:31 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-modula2-self-type.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-noloc.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-noloc.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-noloc.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-op-call.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp	2010-06-07 19:55:33 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-op-call.exp	2011-02-03 17:12:24 +0000
@@ -12,18 +12,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test DW_OP_call2 and DW_OP_call4, PR gdb/10640.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
-    return 0  
+if {![dwarf2_support]} {
+    return 0   
 }
 
 set testfile "dw2-op-call"

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-producer.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-producer.exp	2010-06-02 21:46:44 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-producer.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-ranges.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-ranges.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ranges.exp	2011-02-03 17:12:24 +0000
@@ -12,18 +12,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test DW_TAG_compile_unit with no children and with neither DW_AT_low_pc nor
 # DW_AT_high_pc but with DW_AT_ranges instead.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     verbose "Skipping DW_AT_ranges test."
     return 0  
 }

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-ref-missing-frame.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-ref-missing-frame.exp	2010-06-25 15:34:45 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-ref-missing-frame.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-strp.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-strp.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-strp.exp	2011-02-03 17:12:24 +0000
@@ -12,18 +12,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test printint string variables that are optimized out because they
 # are unreferenced in code, and whose contents appear in .debug_str.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/dw2-unresolved.exp'
--- a/gdb/testsuite/gdb.dwarf2/dw2-unresolved.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/dw2-unresolved.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/mac-fileno.exp'
--- a/gdb/testsuite/gdb.dwarf2/mac-fileno.exp	2010-06-02 21:46:44 +0000
+++ b/gdb/testsuite/gdb.dwarf2/mac-fileno.exp	2011-02-03 17:12:24 +0000
@@ -12,18 +12,13 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Check that GDB can gracefully handle macro information that has
 # bogus file numbers.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp'
--- a/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp	2010-02-02 16:47:13 +0000
+++ b/gdb/testsuite/gdb.dwarf2/member-ptr-forwardref.exp	2011-02-03 17:12:24 +0000
@@ -12,15 +12,10 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.dwarf2/pieces.exp'
--- a/gdb/testsuite/gdb.dwarf2/pieces.exp	2010-06-11 15:36:01 +0000
+++ b/gdb/testsuite/gdb.dwarf2/pieces.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,11 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
-
+load_lib dwarf.exp
 # Test some DWARF piece operators.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 # This test can only be run on x86 targets.

=== modified file 'gdb/testsuite/gdb.dwarf2/valop.exp'
--- a/gdb/testsuite/gdb.dwarf2/valop.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.dwarf2/valop.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 # Test DW_OP_stack_value and DW_OP_implicit_value.
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if {![dwarf2_support]} {
     return 0  
 }
 # This test can only be run on x86 targets.

=== modified file 'gdb/testsuite/gdb.dwarf2/watch-notconst.exp'
--- a/gdb/testsuite/gdb.dwarf2/watch-notconst.exp	2010-06-16 18:30:26 +0000
+++ b/gdb/testsuite/gdb.dwarf2/watch-notconst.exp	2011-02-03 17:12:24 +0000
@@ -12,17 +12,12 @@
 #
 # You should have received a copy of the GNU General Public License
 # along with this program.  If not, see <http://www.gnu.org/licenses/>.
+load_lib dwarf.exp
 
 set test "watch-notconst"
 
 # This test can only be run on targets which support DWARF-2 and use gas.
-# For now pick a sampling of likely targets.
-if {![istarget *-*-linux*]
-    && ![istarget *-*-gnu*]
-    && ![istarget *-*-elf*]
-    && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
-    && ![istarget powerpc-*-eabi*]} {
+if ![dwarf2_support] {
     return 0  
 }
 

=== modified file 'gdb/testsuite/gdb.python/py-section-script.exp'
--- a/gdb/testsuite/gdb.python/py-section-script.exp	2010-04-23 16:20:08 +0000
+++ b/gdb/testsuite/gdb.python/py-section-script.exp	2011-02-03 17:12:24 +0000
@@ -22,7 +22,8 @@
     && ![istarget *-*-gnu*]
     && ![istarget *-*-elf*]
     && ![istarget *-*-openbsd*]
-    && ![istarget arm-*-eabi*]
+    && ![istarget arm*-*-eabi*]
+    && ![istarget arm*-*-symbianelf*]
     && ![istarget powerpc-*-eabi*]} {
     verbose "Skipping py-section-script.exp because of lack of support."
     return

=== modified file 'gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp'
--- a/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp	2010-06-03 23:54:17 +0000
+++ b/gdb/testsuite/gdb.threads/local-watch-wrong-thread.exp	2011-02-21 15:21:16 +0000
@@ -19,8 +19,8 @@
 # thread other than the thread the local watchpoint was set in stops
 # for a breakpoint.
 
-if [target_info exists gdb,no_hardware_watchpoints] {
-    return 0;
+if {[skip_hw_watchpoint_multi_tests]} {
+    return 0
 }
 
 set testfile "local-watch-wrong-thread"

=== modified file 'gdb/testsuite/gdb.threads/threxit-hop-specific.exp'
--- a/gdb/testsuite/gdb.threads/threxit-hop-specific.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.threads/threxit-hop-specific.exp	2010-09-14 18:30:37 +0000
@@ -52,7 +52,7 @@
 set bpexitline [gdb_get_line_number "set exit breakpoint here"]
 gdb_breakpoint "$bpexitline"
 
-gdb_test "next" \
+gdb_test "continue" \
     ".*set exit breakpoint here.*" \
     "get past the thread specific breakpoint"
 

=== modified file 'gdb/testsuite/gdb.threads/watchthreads-reorder.exp'
--- a/gdb/testsuite/gdb.threads/watchthreads-reorder.exp	2010-01-01 07:31:28 +0000
+++ b/gdb/testsuite/gdb.threads/watchthreads-reorder.exp	2011-02-21 15:21:16 +0000
@@ -25,9 +25,8 @@
 # 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 {(![istarget "i?86-*-*"] && ![istarget "x86_64-*-*"]
-     && ![istarget "ia64-*-*"])
-    || [target_info exists gdb,no_hardware_watchpoints]
+if {[skip_hw_watchpoint_access_tests]
+    || [skip_hw_watchpoint_multi_tests]
     || ![istarget *-*-linux*]} {
     return 0
 }

=== modified file 'gdb/testsuite/gdb.threads/watchthreads.exp'
--- a/gdb/testsuite/gdb.threads/watchthreads.exp	2010-06-03 23:54:17 +0000
+++ b/gdb/testsuite/gdb.threads/watchthreads.exp	2011-02-21 15:21:16 +0000
@@ -24,8 +24,8 @@
 
 # This test verifies that a watchpoint is detected in the proper thread
 # so the test is only meaningful on a system with hardware watchpoints.
-if [target_info exists gdb,no_hardware_watchpoints] {
-    return 0;
+if {[skip_hw_watchpoint_multi_tests]} {
+    return 0
 }
 
 proc target_no_stopped_data { } {

=== modified file 'gdb/testsuite/gdb.threads/watchthreads2.exp'
--- a/gdb/testsuite/gdb.threads/watchthreads2.exp	2010-06-03 23:54:17 +0000
+++ b/gdb/testsuite/gdb.threads/watchthreads2.exp	2011-02-21 15:21:16 +0000
@@ -28,8 +28,8 @@
 
 # This test verifies that a watchpoint is detected in the proper thread
 # so the test is only meaningful on a system with hardware watchpoints.
-if [target_info exists gdb,no_hardware_watchpoints] {
-    return 0;
+if {[skip_hw_watchpoint_tests]} {
+    return 0
 }
 
 set testfile "watchthreads2"

=== modified file 'gdb/testsuite/gdb.xml/tdesc-regs.exp'
--- a/gdb/testsuite/gdb.xml/tdesc-regs.exp	2010-03-01 17:19:21 +0000
+++ b/gdb/testsuite/gdb.xml/tdesc-regs.exp	2011-02-03 17:12:24 +0000
@@ -27,10 +27,7 @@
 set regdir ""
 set architecture ""
 switch -glob -- [istarget] {
-    "*arm-*-*" {
-        set core-regs {arm-core.xml}
-    }
-    "xscale-*-*" {
+    "arm*-*-*" {
         set core-regs {arm-core.xml}
     }
     "*m68k-*-*" {

=== added file 'gdb/testsuite/lib/dwarf.exp'
--- a/gdb/testsuite/lib/dwarf.exp	1970-01-01 00:00:00 +0000
+++ b/gdb/testsuite/lib/dwarf.exp	2011-02-03 17:12:24 +0000
@@ -0,0 +1,30 @@
+# Copyright 2010 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/>.
+
+# Return true if the target supports DWARF-2 and uses gas.
+# For now pick a sampling of likely targets.
+proc dwarf2_support {} {
+    if {[istarget *-*-linux*]
+	|| [istarget *-*-gnu*]
+	|| [istarget *-*-elf*]
+	|| [istarget *-*-openbsd*]
+	|| [istarget arm*-*-eabi*]
+	|| [istarget arm*-*-symbianelf*]
+	|| [istarget powerpc-*-eabi*]} {
+	return 1
+    }
+
+    return 0
+}

=== modified file 'gdb/testsuite/lib/gdb.exp'
--- a/gdb/testsuite/lib/gdb.exp	2010-07-20 22:22:56 +0000
+++ b/gdb/testsuite/lib/gdb.exp	2011-02-21 15:27:39 +0000
@@ -1673,6 +1673,79 @@
     return 0
 }
 
+# Return a 1 if we should skip tests that require hardware breakpoints
+
+proc skip_hw_breakpoint_tests {} {
+    # Skip tests if requested by the board (note that no_hardware_watchpoints
+    # disables both watchpoints and breakpoints)
+    if { [target_info exists gdb,no_hardware_watchpoints]} {
+	return 1
+    }
+
+    # These targets support hardware breakpoints natively
+    if { [istarget "i?86-*-*"] 
+	 || [istarget "x86_64-*-*"]
+	 || [istarget "ia64-*-*"] 
+	 || [istarget "arm*-*-*"]} {
+	return 0
+    }
+
+    return 1
+}
+
+# Return a 1 if we should skip tests that require hardware watchpoints
+
+proc skip_hw_watchpoint_tests {} {
+    # Skip tests if requested by the board
+    if { [target_info exists gdb,no_hardware_watchpoints]} {
+	return 1
+    }
+
+    # These targets support hardware watchpoints natively
+    if { [istarget "i?86-*-*"] 
+	 || [istarget "x86_64-*-*"]
+	 || [istarget "ia64-*-*"] 
+	 || [istarget "arm*-*-*"]
+	 || [istarget "powerpc*-*-linux*"]
+	 || [istarget "s390*-*-*"] } {
+	return 0
+    }
+
+    return 1
+}
+
+# Return a 1 if we should skip tests that require *multiple* hardware
+# watchpoints to be active at the same time
+
+proc skip_hw_watchpoint_multi_tests {} {
+    if { [skip_hw_watchpoint_tests] } {
+	return 1
+    }
+
+    # These targets support just a single hardware watchpoint
+    if { [istarget "arm*-*-*"]
+	 || [istarget "powerpc*-*-linux*"] } {
+	return 1
+    }
+
+    return 0
+}
+
+# Return a 1 if we should skip tests that require read/access watchpoints
+
+proc skip_hw_watchpoint_access_tests {} {
+    if { [skip_hw_watchpoint_tests] } {
+	return 1
+    }
+
+    # These targets support just write watchpoints
+    if { [istarget "s390*-*-*"] } {
+	return 1
+    }
+
+    return 0
+}
+
 set compiler_info		"unknown"
 set gcc_compiled		0
 set hp_cc_compiler		0

=== modified file 'libiberty/pex-common.c'
--- a/libiberty/pex-common.c	2009-04-13 10:48:27 +0000
+++ b/libiberty/pex-common.c	2010-10-06 12:48:13 +0000
@@ -505,6 +505,7 @@
   if (o < 0 || o == STDIN_FILE_NO)
     return NULL;
   obj->read_err = obj->funcs->fdopenr (obj, o, binary);
+  obj->stderr_pipe = -1;
   return obj->read_err;    
 }
 
@@ -597,8 +598,17 @@
 void
 pex_free (struct pex_obj *obj)
 {
+  /* Close pipe file descriptors corresponding to child's stdout and
+     stderr so that the child does not hang trying to output something
+     while we're waiting for it.  */
   if (obj->next_input >= 0 && obj->next_input != STDIN_FILE_NO)
     obj->funcs->close (obj, obj->next_input);
+  if (obj->stderr_pipe >= 0 && obj->stderr_pipe != STDIN_FILE_NO)
+    obj->funcs->close (obj, obj->stderr_pipe);
+  if (obj->read_output != NULL)
+    fclose (obj->read_output);
+  if (obj->read_err != NULL)
+    fclose (obj->read_err);
 
   /* If the caller forgot to wait for the children, we do it here, to
      avoid zombies.  */
@@ -619,10 +629,6 @@
     free (obj->status);
   if (obj->time != NULL)
     free (obj->time);
-  if (obj->read_output != NULL)
-    fclose (obj->read_output);
-  if (obj->read_err != NULL)
-    fclose (obj->read_err);
 
   if (obj->remove_count > 0)
     {

