This is the mail archive of the gdb-patches@sources.redhat.com mailing list for the GDB project.


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

PATCH ARM - multi-arch multi-abi breakpoint handling


This patch adds a multi-arch, multi-abi way of handling breakpoints on the 
ARM.

Partially arched ARM configs can currently override the default settings 
of the breakpoint values.

R.

(I've also remembered to "cvs add" armnbsd-tdep.c this time :^)

2002-02-15  Richard Earnshaw  <rearnsha@arm.com>

	* arm-tdep.h (struct gdbarch_tdep): Add fields for breakpoint
	descriptions.
	* arm-tdep.c (arm_default_arm_le_breakpoint)
	(arm_default_arm_be_breakpoint, arm_default_thumb_le_breakpoint)
	(arm_default_thumb_be_breakpoint): New.  Initialize them from
	traditional breakpoint defines.
	(arm_breakpoint_from_pc): Use new gdbarch_tdep entries.
	(arm_gdbarch_init): Initialize new breakpoint variables.
	* arm-linux-tdep.c (arm_linux_arm_le_breakpoint): New.
	(arm_linux_init_abi): Initialize linux-specific breakpoint.
	* armnbsd-tdep.c (arm_nbsd_arm_le_breakpoint): New.
	(arm_netbsd_aout_init_abi, arm_netbsd_elf_init_abi): Split common
	code out to ...
	(arm_netbsd_init_abi_common): ... here; new function.
	* config/arm/tm-arm.h (ARM_LE_BREAKPOINT, ARM_BE_BREAKPOINT)
	(THUMB_LE_BREAKPOINT, THUMB_BE_BREAKPOINT): Delete.
	* config/arm/tm-linux.h (ARM_LE_BREAKPOINT): Delete.
	* config/arm/tm-nbsd.h (ARM_LE_BREAKPOINT): Delete.


? gdbarch.log
Index: arm-linux-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-linux-tdep.c,v
retrieving revision 1.15
diff -p -r1.15 arm-linux-tdep.c
*** arm-linux-tdep.c	2002/02/15 13:35:25	1.15
--- arm-linux-tdep.c	2002/02/15 16:09:13
***************
*** 35,40 ****
--- 35,49 ----
  #include "symfile.h"
  #include "objfiles.h"
  
+ /* Under ARM Linux the traditional way of performing a breakpoint is to
+    execute a particular software interrupt, rather than use a particular
+    undefined instruction to provoke a trap.  Upon exection of the software
+    interrupt the kernel stops the inferior with a SIGTRAP, and wakes the
+    debugger.  Since ARM Linux is little endian, and doesn't support Thumb
+    at the moment we only override the ARM little-endian breakpoint.  */
+ 
+ static const char arm_linux_arm_le_breakpoint[] = {0x01,0x00,0x9f,0xef};
+ 
  /* CALL_DUMMY_WORDS:
     This sequence of words is the instructions
  
*************** arm_linux_init_abi (struct gdbarch_info 
*** 537,542 ****
--- 546,553 ----
    struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
  
    tdep->lowest_pc = 0x8000;
+   tdep->arm_breakpoint = arm_linux_arm_le_breakpoint;
+   tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint);
  }
  
  void
Index: arm-tdep.c
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.c,v
retrieving revision 1.42
diff -p -r1.42 arm-tdep.c
*** arm-tdep.c	2002/02/15 13:35:25	1.42
--- arm-tdep.c	2002/02/15 16:09:15
*************** gdb_print_insn_arm (bfd_vma memaddr, dis
*** 2044,2049 ****
--- 2044,2099 ----
      return print_insn_little_arm (memaddr, info);
  }
  
+ /* The following define instruction sequences that will cause ARM
+    cpu's to take an undefined instruction trap.  These are used to
+    signal a breakpoint to GDB.
+    
+    The newer ARMv4T cpu's are capable of operating in ARM or Thumb
+    modes.  A different instruction is required for each mode.  The ARM
+    cpu's can also be big or little endian.  Thus four different
+    instructions are needed to support all cases.
+    
+    Note: ARMv4 defines several new instructions that will take the
+    undefined instruction trap.  ARM7TDMI is nominally ARMv4T, but does
+    not in fact add the new instructions.  The new undefined
+    instructions in ARMv4 are all instructions that had no defined
+    behaviour in earlier chips.  There is no guarantee that they will
+    raise an exception, but may be treated as NOP's.  In practice, it
+    may only safe to rely on instructions matching:
+    
+    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 
+    1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
+    C C C C 0 1 1 x x x x x x x x x x x x x x x x x x x x 1 x x x x
+    
+    Even this may only true if the condition predicate is true. The
+    following use a condition predicate of ALWAYS so it is always TRUE.
+    
+    There are other ways of forcing a breakpoint.  GNU/Linux, RISC iX,
+    and NetBSD all use a software interrupt rather than an undefined
+    instruction to force a trap.  This can be handled by by the
+    abi-specific code during establishment of the gdbarch vector.  */
+ 
+ 
+ /* XXX for now we allow a non-multi-arch gdb to override these
+    definitions.  */
+ #ifndef ARM_LE_BREAKPOINT
+ #define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7}
+ #endif
+ #ifndef ARM_BE_BREAKPOINT
+ #define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
+ #endif
+ #ifndef THUMB_LE_BREAKPOINT
+ #define THUMB_LE_BREAKPOINT {0xfe,0xdf}
+ #endif
+ #ifndef THUMB_BE_BREAKPOINT
+ #define THUMB_BE_BREAKPOINT {0xdf,0xfe}
+ #endif
+ 
+ static const char arm_default_arm_le_breakpoint[] = ARM_LE_BREAKPOINT;
+ static const char arm_default_arm_be_breakpoint[] = ARM_BE_BREAKPOINT;
+ static const char arm_default_thumb_le_breakpoint[] = THUMB_LE_BREAKPOINT;
+ static const char arm_default_thumb_be_breakpoint[] = THUMB_BE_BREAKPOINT;
+ 
  /* Determine the type and size of breakpoint to insert at PCPTR.  Uses
     the program counter value to determine whether a 16-bit or 32-bit
     breakpoint should be used.  It returns a pointer to a string of
*************** gdb_print_insn_arm (bfd_vma memaddr, dis
*** 2060,2096 ****
  unsigned char *
  arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
  {
    if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
      {
!       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
! 	{
! 	  static char thumb_breakpoint[] = THUMB_BE_BREAKPOINT;
! 	  *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
! 	  *lenptr = sizeof (thumb_breakpoint);
! 	  return thumb_breakpoint;
! 	}
!       else
! 	{
! 	  static char thumb_breakpoint[] = THUMB_LE_BREAKPOINT;
! 	  *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
! 	  *lenptr = sizeof (thumb_breakpoint);
! 	  return thumb_breakpoint;
! 	}
      }
    else
      {
!       if (TARGET_BYTE_ORDER == BFD_ENDIAN_BIG)
! 	{
! 	  static char arm_breakpoint[] = ARM_BE_BREAKPOINT;
! 	  *lenptr = sizeof (arm_breakpoint);
! 	  return arm_breakpoint;
! 	}
!       else
! 	{
! 	  static char arm_breakpoint[] = ARM_LE_BREAKPOINT;
! 	  *lenptr = sizeof (arm_breakpoint);
! 	  return arm_breakpoint;
! 	}
      }
  }
  
--- 2110,2127 ----
  unsigned char *
  arm_breakpoint_from_pc (CORE_ADDR *pcptr, int *lenptr)
  {
+   struct gdbarch_tdep *tdep = gdbarch_tdep (current_gdbarch);
+ 
    if (arm_pc_is_thumb (*pcptr) || arm_pc_is_thumb_dummy (*pcptr))
      {
!       *pcptr = UNMAKE_THUMB_ADDR (*pcptr);
!       *lenptr = tdep->thumb_breakpoint_size;
!       return tdep->thumb_breakpoint;
      }
    else
      {
!       *lenptr = tdep->arm_breakpoint_size;
!       return tdep->arm_breakpoint;
      }
  }
  
*************** arm_gdbarch_init (struct gdbarch_info in
*** 2710,2730 ****
        tdep->abi_name = "<invalid>";
      }
  
!   /* Floating point sizes and format.  */
    switch (info.byte_order)
      {
      case BFD_ENDIAN_BIG:
        set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
        set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
        set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
        break;
  
      case BFD_ENDIAN_LITTLE:
        set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
        set_gdbarch_double_format (gdbarch,
  				 &floatformat_ieee_double_littlebyte_bigword);
        set_gdbarch_long_double_format (gdbarch,
  				 &floatformat_ieee_double_littlebyte_bigword);
        break;
  
      default:
--- 2741,2773 ----
        tdep->abi_name = "<invalid>";
      }
  
!   /* Breakpoints and floating point sizes and format.  */
    switch (info.byte_order)
      {
      case BFD_ENDIAN_BIG:
+       tdep->arm_breakpoint = arm_default_arm_be_breakpoint;
+       tdep->arm_breakpoint_size = sizeof (arm_default_arm_be_breakpoint);
+       tdep->thumb_breakpoint = arm_default_thumb_be_breakpoint;
+       tdep->thumb_breakpoint_size = sizeof (arm_default_thumb_be_breakpoint);
+ 
        set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_big);
        set_gdbarch_double_format (gdbarch, &floatformat_ieee_double_big);
        set_gdbarch_long_double_format (gdbarch, &floatformat_ieee_double_big);
+       
        break;
  
      case BFD_ENDIAN_LITTLE:
+       tdep->arm_breakpoint = arm_default_arm_le_breakpoint;
+       tdep->arm_breakpoint_size = sizeof (arm_default_arm_le_breakpoint);
+       tdep->thumb_breakpoint = arm_default_thumb_le_breakpoint;
+       tdep->thumb_breakpoint_size = sizeof (arm_default_thumb_le_breakpoint);
+ 
        set_gdbarch_float_format (gdbarch, &floatformat_ieee_single_little);
        set_gdbarch_double_format (gdbarch,
  				 &floatformat_ieee_double_littlebyte_bigword);
        set_gdbarch_long_double_format (gdbarch,
  				 &floatformat_ieee_double_littlebyte_bigword);
+ 
        break;
  
      default:
Index: arm-tdep.h
===================================================================
RCS file: /cvs/src/src/gdb/arm-tdep.h,v
retrieving revision 1.3
diff -p -r1.3 arm-tdep.h
*** arm-tdep.h	2002/02/15 13:35:26	1.3
--- arm-tdep.h	2002/02/15 16:09:15
*************** struct gdbarch_tdep
*** 123,128 ****
--- 123,132 ----
    const char *abi_name;		/* Name of the above.  */
    CORE_ADDR lowest_pc;		/* Lowest address at which instructions 
  				   will appear.  */
+   const char *arm_breakpoint;
+   int arm_breakpoint_size;
+   const char *thumb_breakpoint;
+   int thumb_breakpoint_size;
  };
  
  #ifndef LOWEST_PC
Index: armnbsd-tdep.c
===================================================================
RCS file: armnbsd-tdep.c
diff -N armnbsd-tdep.c
*** /dev/null	Tue May  5 13:32:27 1998
--- armnbsd-tdep.c	Fri Feb 15 08:09:15 2002
***************
*** 0 ****
--- 1,59 ----
+ /* Target-specific functions for ARM running under NetBSD.
+    Copyright 2002 Free Software Foundation, Inc.
+ 
+    This file is part of GDB.
+ 
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+ 
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+ 
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 59 Temple Place - Suite 330,
+    Boston, MA 02111-1307, USA.  */
+ 
+ #include "defs.h"
+ 
+ #include "arm-tdep.h"
+ 
+ /* For compatibility with previous implemenations of GDB on arm/NetBSD,
+    override the default little-endian breakpoint.  */
+ static const char arm_nbsd_arm_le_breakpoint[] = {0x11, 0x00, 0x00, 0xe6};
+ 
+ static void
+ arm_netbsd_init_abi_common (struct gdbarch_info info,
+ 			    struct gdbarch *gdbarch)
+ {
+   struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ 
+   tdep->lowest_pc = 0x8000;
+   tdep->arm_breakpoint = arm_nbsd_arm_le_breakpoint;
+   tdep->arm_breakpoint_size = sizeof (arm_nbsd_arm_le_breakpoint);
+ }
+   
+ static void
+ arm_netbsd_aout_init_abi (struct gdbarch_info info, 
+ 			  struct gdbarch *gdbarch)
+ {
+   arm_netbsd_init_abi_common (info, gdbarch);
+ }
+ 
+ static void
+ arm_netbsd_elf_init_abi (struct gdbarch_info info, 
+ 			 struct gdbarch *gdbarch)
+ {
+   arm_netbsd_init_abi_common (info, gdbarch);
+ }
+ 
+ void
+ _initialize_arm_netbsd_tdep (void)
+ {
+   arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_AOUT, arm_netbsd_aout_init_abi);
+   arm_gdbarch_register_os_abi (ARM_ABI_NETBSD_ELF, arm_netbsd_elf_init_abi);
+ }
Index: config/arm/tm-arm.h
===================================================================
RCS file: /cvs/src/src/gdb/config/arm/tm-arm.h,v
retrieving revision 1.29
diff -p -r1.29 tm-arm.h
*** tm-arm.h	2002/02/15 13:35:27	1.29
--- tm-arm.h	2002/02/15 16:09:15
***************
*** 26,66 ****
  #define GDB_MULTI_ARCH 1
  #endif
  
- /* The following define instruction sequences that will cause ARM
-    cpu's to take an undefined instruction trap.  These are used to
-    signal a breakpoint to GDB.
-    
-    The newer ARMv4T cpu's are capable of operating in ARM or Thumb
-    modes.  A different instruction is required for each mode.  The ARM
-    cpu's can also be big or little endian.  Thus four different
-    instructions are needed to support all cases.
-    
-    Note: ARMv4 defines several new instructions that will take the
-    undefined instruction trap.  ARM7TDMI is nominally ARMv4T, but does
-    not in fact add the new instructions.  The new undefined
-    instructions in ARMv4 are all instructions that had no defined
-    behaviour in earlier chips.  There is no guarantee that they will
-    raise an exception, but may be treated as NOP's.  In practice, it
-    may only safe to rely on instructions matching:
-    
-    3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 
-    1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0
-    C C C C 0 1 1 x x x x x x x x x x x x x x x x x x x x 1 x x x x
-    
-    Even this may only true if the condition predicate is true. The
-    following use a condition predicate of ALWAYS so it is always TRUE.
-    
-    There are other ways of forcing a breakpoint.  ARM Linux, RISC iX,
-    and NetBSD will all use a software interrupt rather than an
-    undefined instruction to force a trap.  This can be handled by
-    redefining some or all of the following in a target dependent
-    fashion.  */
- 
- #define ARM_LE_BREAKPOINT {0xFE,0xDE,0xFF,0xE7}
- #define ARM_BE_BREAKPOINT {0xE7,0xFF,0xDE,0xFE}
- #define THUMB_LE_BREAKPOINT {0xfe,0xdf}
- #define THUMB_BE_BREAKPOINT {0xdf,0xfe}
- 
  /* Specify that for the native compiler variables for a particular
     lexical context are listed after the beginning LBRAC instead of
     before in the executables list of symbols.  */
--- 26,31 ----
Index: config/arm/tm-linux.h
===================================================================
RCS file: /cvs/src/src/gdb/config/arm/tm-linux.h,v
retrieving revision 1.11
diff -p -r1.11 tm-linux.h
*** tm-linux.h	2002/02/12 00:58:20	1.11
--- tm-linux.h	2002/02/15 16:09:15
***************
*** 34,49 ****
  extern struct link_map_offsets *arm_linux_svr4_fetch_link_map_offsets (void);
  #define SVR4_FETCH_LINK_MAP_OFFSETS() arm_linux_svr4_fetch_link_map_offsets ()
  
- /* Under ARM Linux the traditional way of performing a breakpoint is to
-    execute a particular software interrupt, rather than use a particular
-    undefined instruction to provoke a trap.  Upon exection of the software
-    interrupt the kernel stops the inferior with a SIGTRAP, and wakes the
-    debugger.  Since ARM Linux is little endian, and doesn't support Thumb
-    at the moment we redefined ARM_LE_BREAKPOINT to use the correct software
-    interrupt.  */
- #undef ARM_LE_BREAKPOINT
- #define ARM_LE_BREAKPOINT	{0x01,0x00,0x9f,0xef}
- 
  #undef CALL_DUMMY_WORDS
  #define CALL_DUMMY_WORDS arm_linux_call_dummy_words
  extern LONGEST arm_linux_call_dummy_words[];
--- 34,39 ----
Index: config/arm/tm-nbsd.h
===================================================================
RCS file: /cvs/src/src/gdb/config/arm/tm-nbsd.h,v
retrieving revision 1.4
diff -p -r1.4 tm-nbsd.h
*** tm-nbsd.h	2002/02/15 13:35:27	1.4
--- tm-nbsd.h	2002/02/15 16:09:15
*************** get_longjmp_target (CORE_ADDR *);
*** 42,52 ****
  
  #define GET_LONGJMP_TARGET(ADDR) get_longjmp_target(ADDR)
  
- /* For compatibility with previous implemenations of GDB on arm/NetBSD,
-    override the default little-endian breakpoint.  */
- #undef ARM_LE_BREAKPOINT
- #define ARM_LE_BREAKPOINT {0x11, 0x00, 0x00, 0xe6}
- 
  /* By convention, NetBSD uses the "other" register names. */
  #define DEFAULT_REGISTER_NAMES additional_register_names
  
--- 42,47 ----

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