This is the mail archive of the
gdb-patches@sources.redhat.com
mailing list for the GDB project.
PATCH ARM - multi-arch multi-abi breakpoint handling
- From: Richard Earnshaw <rearnsha at arm dot com>
- To: gdb-patches at sources dot redhat dot com
- Cc: Richard dot Earnshaw at arm dot com
- Date: Fri, 15 Feb 2002 16:15:35 +0000
- Subject: PATCH ARM - multi-arch multi-abi breakpoint handling
- Organization: ARM Ltd.
- Reply-to: Richard dot Earnshaw at arm dot com
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 ----