diff options
Diffstat (limited to 'gdb')
-rw-r--r-- | gdb/ChangeLog | 21 | ||||
-rw-r--r-- | gdb/arm-linux-tdep.c | 11 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 97 | ||||
-rw-r--r-- | gdb/arm-tdep.h | 4 | ||||
-rw-r--r-- | gdb/armnbsd-tdep.c | 59 | ||||
-rw-r--r-- | gdb/config/arm/tm-arm.h | 35 | ||||
-rw-r--r-- | gdb/config/arm/tm-linux.h | 10 | ||||
-rw-r--r-- | gdb/config/arm/tm-nbsd.h | 5 |
8 files changed, 165 insertions, 77 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 5a1f695..b1eb77e 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,5 +1,26 @@ 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. + +2002-02-15 Richard Earnshaw <rearnsha@arm.com> + * arm-tdep.h (enum arm_abi): New enum. (struct gdbarch_tdep): New structure. (LOWEST_PC): Provide a default. diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index ac2f8e0..6049cf5 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -35,6 +35,15 @@ #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 @@ -537,6 +546,8 @@ arm_linux_init_abi (struct gdbarch_info info, 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 diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 9577f0a..a60f497 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -2044,6 +2044,56 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info) 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 @@ -2060,37 +2110,18 @@ gdb_print_insn_arm (bfd_vma memaddr, disassemble_info *info) 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)) { - 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; - } + *pcptr = UNMAKE_THUMB_ADDR (*pcptr); + *lenptr = tdep->thumb_breakpoint_size; + return tdep->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; - } + *lenptr = tdep->arm_breakpoint_size; + return tdep->arm_breakpoint; } } @@ -2710,21 +2741,33 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->abi_name = "<invalid>"; } - /* Floating point sizes and format. */ + /* 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: diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index 60bcf01..85d9e4f 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -123,6 +123,10 @@ struct gdbarch_tdep 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 diff --git a/gdb/armnbsd-tdep.c b/gdb/armnbsd-tdep.c new file mode 100644 index 0000000..25c2f16 --- /dev/null +++ b/gdb/armnbsd-tdep.c @@ -0,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); +} diff --git a/gdb/config/arm/tm-arm.h b/gdb/config/arm/tm-arm.h index 77cae55..6f48b60b 100644 --- a/gdb/config/arm/tm-arm.h +++ b/gdb/config/arm/tm-arm.h @@ -26,41 +26,6 @@ #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. */ diff --git a/gdb/config/arm/tm-linux.h b/gdb/config/arm/tm-linux.h index 7e3a80c..aa3fa52 100644 --- a/gdb/config/arm/tm-linux.h +++ b/gdb/config/arm/tm-linux.h @@ -34,16 +34,6 @@ 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[]; diff --git a/gdb/config/arm/tm-nbsd.h b/gdb/config/arm/tm-nbsd.h index c55cc5a..4dfc329 100644 --- a/gdb/config/arm/tm-nbsd.h +++ b/gdb/config/arm/tm-nbsd.h @@ -42,11 +42,6 @@ get_longjmp_target (CORE_ADDR *); #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 |