diff options
author | Daniel Jacobowitz <drow@false.org> | 2005-03-25 22:02:38 +0000 |
---|---|---|
committer | Daniel Jacobowitz <drow@false.org> | 2005-03-25 22:02:38 +0000 |
commit | 625aec4a7789f6ee21925d706a3fbf018ef202bd (patch) | |
tree | 590ecda09786f9dc8028f8ccecf1299883a45ea8 | |
parent | 840e5921506ae7ea96a11d035e58642204888579 (diff) | |
download | binutils-625aec4a7789f6ee21925d706a3fbf018ef202bd.zip binutils-625aec4a7789f6ee21925d706a3fbf018ef202bd.tar.gz binutils-625aec4a7789f6ee21925d706a3fbf018ef202bd.tar.bz2 |
* gdb/configure.tgt: Add default OSABI setting for
arm*-*-linux-gnueabi.
* gdb/arm-tdep.c (arm_type_align): New function.
(arm_push_dummy_call): Use it. Ensure proper argument alignment.
Don't try to align the stack.
(arm_frame_align): New function.
(arm_extract_struct_value_address): Remove.
(arm_use_struct_convention): Rename...
(arm_return_in_memory): ... To this. Return nonzero for all small
aggregates under the EABI.
(arm_return_value): New function.
(arm_elf_osabi_sniffer): Add EF_ARM_EABI_VER4 case. Handle
GDB_OSABI_ARM_EABI_V4_LINUX.
(arm_gdbarch_init): Set different FPU and ABI defaults for EABI
objects. Use set_gdbarch_return_value instead of obsolete functions.
Call set_gdbarch_frame_align.
(arm_init_abi_eabi_v4): New function.
(_initialize_arm_tdep): Register GDB_OSABI_ARM_EABI_V4.
* gdb/arm-linux-tdep.c (ARM_LINUX_EABI_JB_PC): Define.
(arm_linux_eabi_init_abi): New function.
(_initialize_arm_linux_tdep): Register GDB_OSABI_ARM_EABI_V4_LINUX.
* gdb/arm-tdep.h (enum arm_abi_variant): New.
(struct gdbarch_tdep): Add abi field.
* gdb/defs.h (enum gdb_osabi): Add GDB_OSABI_ARM_EABI_V4 and
GDB_OSABI_ARM_EABI_V4_LINUX.
* gdb/osabi.c (gdb_osabi_name): Add "ARM EABI v4" and
"ARM EABI v4 GNU/Linux".
* gdb/testsuite/gdb.base/long_long.exp: Don't expect FPA format for
ARM EABI targets.
-rw-r--r-- | ChangeLog.csl | 34 | ||||
-rw-r--r-- | gdb/arm-linux-tdep.c | 34 | ||||
-rw-r--r-- | gdb/arm-tdep.c | 187 | ||||
-rw-r--r-- | gdb/arm-tdep.h | 8 | ||||
-rw-r--r-- | gdb/configure.tgt | 2 | ||||
-rw-r--r-- | gdb/defs.h | 2 | ||||
-rw-r--r-- | gdb/osabi.c | 2 | ||||
-rw-r--r-- | gdb/testsuite/gdb.base/long_long.exp | 13 |
8 files changed, 252 insertions, 30 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl index 9c902fe..fa7a530 100644 --- a/ChangeLog.csl +++ b/ChangeLog.csl @@ -1,3 +1,37 @@ +2005-03-25 Paul Brook <paul@codesourcery.com> + Daniel Jacobowitz <dan@codesourcery.com> + + * gdb/configure.tgt: Add default OSABI setting for + arm*-*-linux-gnueabi. + * gdb/arm-tdep.c (arm_type_align): New function. + (arm_push_dummy_call): Use it. Ensure proper argument alignment. + Don't try to align the stack. + (arm_frame_align): New function. + (arm_extract_struct_value_address): Remove. + (arm_use_struct_convention): Rename... + (arm_return_in_memory): ... To this. Return nonzero for all small + aggregates under the EABI. + (arm_return_value): New function. + (arm_elf_osabi_sniffer): Add EF_ARM_EABI_VER4 case. Handle + GDB_OSABI_ARM_EABI_V4_LINUX. + (arm_gdbarch_init): Set different FPU and ABI defaults for EABI + objects. Use set_gdbarch_return_value instead of obsolete functions. + Call set_gdbarch_frame_align. + (arm_init_abi_eabi_v4): New function. + (_initialize_arm_tdep): Register GDB_OSABI_ARM_EABI_V4. + * gdb/arm-linux-tdep.c (ARM_LINUX_EABI_JB_PC): Define. + (arm_linux_eabi_init_abi): New function. + (_initialize_arm_linux_tdep): Register GDB_OSABI_ARM_EABI_V4_LINUX. + * gdb/arm-tdep.h (enum arm_abi_variant): New. + (struct gdbarch_tdep): Add abi field. + * gdb/defs.h (enum gdb_osabi): Add GDB_OSABI_ARM_EABI_V4 and + GDB_OSABI_ARM_EABI_V4_LINUX. + * gdb/osabi.c (gdb_osabi_name): Add "ARM EABI v4" and + "ARM EABI v4 GNU/Linux". + + * gdb/testsuite/gdb.base/long_long.exp: Don't expect FPA format for + ARM EABI targets. + 2005-03-25 Daniel Jacobowitz <dan@codesourcery.com> * gdb/arm-linux-nat.c (store_register, store_regs): Handle diff --git a/gdb/arm-linux-tdep.c b/gdb/arm-linux-tdep.c index d4b2899..bcade17 100644 --- a/gdb/arm-linux-tdep.c +++ b/gdb/arm-linux-tdep.c @@ -52,6 +52,7 @@ static const char arm_linux_thumb_le_breakpoint[] = {0x01, 0xde}; /* Description of the longjmp buffer. */ #define ARM_LINUX_JB_ELEMENT_SIZE INT_REGISTER_SIZE #define ARM_LINUX_JB_PC 21 +#define ARM_LINUX_EABI_JB_PC 27 /* Extract from an array REGBUF containing the (raw) register state a function return value of type TYPE, and copy that, in virtual format, @@ -497,9 +498,42 @@ arm_linux_init_abi (struct gdbarch_info info, set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); } +static void +arm_linux_eabi_init_abi (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); + + tdep->lowest_pc = 0x8000; + if (info.byte_order == BFD_ENDIAN_BIG) + { + tdep->arm_breakpoint = arm_linux_arm_be_breakpoint; + tdep->thumb_breakpoint = arm_linux_thumb_be_breakpoint; + } + else + { + tdep->arm_breakpoint = arm_linux_arm_le_breakpoint; + tdep->thumb_breakpoint = arm_linux_thumb_le_breakpoint; + } + tdep->arm_breakpoint_size = sizeof (arm_linux_arm_le_breakpoint); + tdep->thumb_breakpoint_size = sizeof (arm_linux_thumb_le_breakpoint); + + tdep->jb_pc = ARM_LINUX_EABI_JB_PC; + tdep->jb_elt_size = ARM_LINUX_JB_ELEMENT_SIZE; + + set_solib_svr4_fetch_link_map_offsets + (gdbarch, arm_linux_svr4_fetch_link_map_offsets); + + /* Shared library handling. */ + set_gdbarch_skip_trampoline_code (gdbarch, find_solib_trampoline_target); + set_gdbarch_skip_solib_resolver (gdbarch, glibc_skip_solib_resolver); +} + void _initialize_arm_linux_tdep (void) { gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_LINUX, arm_linux_init_abi); + gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V4_LINUX, + arm_linux_eabi_init_abi); } diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index fc7e8fe..e4958b0 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -1190,6 +1190,63 @@ pop_stack_item (struct stack_item *si) return si; } + +/* Return the alignment (in bytes) of the given type. */ + +static int +arm_type_align (struct type *t) +{ + int n; + int align; + int falign; + + switch (TYPE_CODE (t)) + { + case TYPE_CODE_UNDEF: + case TYPE_CODE_FUNC: + case TYPE_CODE_VOID: + case TYPE_CODE_STRING: + case TYPE_CODE_ERROR: + case TYPE_CODE_MEMBER: + case TYPE_CODE_METHOD: + case TYPE_CODE_TEMPLATE: + case TYPE_CODE_TEMPLATE_ARG: + case TYPE_CODE_NAMESPACE: + case TYPE_CODE_TYPEDEF: + default: + /* Should never happen, so make something up. */ + return 4; + + case TYPE_CODE_PTR: + case TYPE_CODE_ENUM: + case TYPE_CODE_INT: + case TYPE_CODE_FLT: + case TYPE_CODE_SET: + case TYPE_CODE_RANGE: + case TYPE_CODE_BITSTRING: + case TYPE_CODE_REF: + case TYPE_CODE_CHAR: + case TYPE_CODE_BOOL: + return TYPE_LENGTH (t); + + case TYPE_CODE_ARRAY: + case TYPE_CODE_COMPLEX: + /* TODO: What about vector types? */ + return arm_type_align (TYPE_TARGET_TYPE (t)); + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + align = 1; + for (n = 0; n < TYPE_NFIELDS (t); n++) + { + falign = arm_type_align (TYPE_FIELD_TYPE (t, n)); + if (falign > align) + align = falign; + } + return align; + } +} + /* We currently only support passing parameters in integer registers. This conforms with GCC's default model. Several other variants exist and we should probably support some of them based on the selected ABI. */ @@ -1218,11 +1275,6 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function, argreg = ARM_A1_REGNUM; nstack = 0; - /* Some platforms require a double-word aligned stack. Make sure sp - is correctly aligned before we start. We always do this even if - it isn't really needed -- it can never hurt things. */ - sp &= ~(CORE_ADDR)(2 * DEPRECATED_REGISTER_SIZE - 1); - /* The struct_return pointer occupies the first parameter passing register. */ if (struct_return) @@ -1241,6 +1293,7 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function, struct type *target_type; enum type_code typecode; bfd_byte *val; + int align; arg_type = check_typedef (value_type (args[argnum])); len = TYPE_LENGTH (arg_type); @@ -1248,6 +1301,35 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function, typecode = TYPE_CODE (arg_type); val = value_contents_writeable (args[argnum]); + if (gdbarch_tdep (gdbarch)->abi == ARM_ABI_APCS_GNU) + { + /* The old APCS ABI does not require doubleword alignment. */ + align = INT_REGISTER_SIZE; + } + else + { + align = arm_type_align (arg_type); + + /* Round alignment up to one or two words. */ + align = (align + INT_REGISTER_SIZE - 1) & ~(INT_REGISTER_SIZE - 1); + + gdb_assert (align == INT_REGISTER_SIZE + || align == INT_REGISTER_SIZE * 2); + } + + /* Push stack padding for dowubleword alignment. */ + if (nstack & (align - 1)) + { + si = push_stack_item (si, val, INT_REGISTER_SIZE); + nstack += INT_REGISTER_SIZE; + } + + /* Doubleword aligned quantities must go in even register pairs. */ + if (argreg <= ARM_LAST_ARG_REGNUM + && align > INT_REGISTER_SIZE + && argreg & 1) + argreg++; + /* If the argument is a pointer to a function, and it is a Thumb function, create a LOCAL copy of the value and set the THUMB bit in it. */ @@ -1314,6 +1396,13 @@ arm_push_dummy_call (struct gdbarch *gdbarch, struct value *function, return sp; } +static CORE_ADDR +arm_frame_align (struct gdbarch *gdbarch, CORE_ADDR sp) +{ + /* Align the stack to eight bytes. */ + return sp & ~ (CORE_ADDR) 7; +} + static void print_fpu_flags (int flags) { @@ -2083,24 +2172,13 @@ arm_extract_return_value (struct type *type, } } -/* Extract from an array REGBUF containing the (raw) register state - the address in which a function should return its structure value. */ - -static CORE_ADDR -arm_extract_struct_value_address (struct regcache *regcache) -{ - ULONGEST ret; - - regcache_cooked_read_unsigned (regcache, ARM_A1_REGNUM, &ret); - return ret; -} /* Will a function return an aggregate type in memory or in a register? Return 0 if an aggregate type can be returned in a register, 1 if it must be returned in memory. */ static int -arm_use_struct_convention (int gcc_p, struct type *type) +arm_return_in_memory (struct gdbarch *gdbarch, struct type *type) { int nRc; enum type_code code; @@ -2131,6 +2209,11 @@ arm_use_struct_convention (int gcc_p, struct type *type) return 1; } + /* The new EABI says all aggregates not larger than a word are returned + in a register. */ + if (gdbarch_tdep (gdbarch)->abi != ARM_ABI_APCS_GNU) + return 0; + /* The only aggregate types that can be returned in a register are structs and unions. Arrays must be returned in memory. */ code = TYPE_CODE (type); @@ -2280,6 +2363,33 @@ arm_store_return_value (struct type *type, struct regcache *regs, } } + +/* Handle function return values. */ + +static enum return_value_convention +arm_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, void *readbuf, + const void *writebuf) +{ + /* TODO: Only call for aggreagates. */ + if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || TYPE_CODE (valtype) == TYPE_CODE_ARRAY) + { + if (arm_return_in_memory (gdbarch, valtype)) + return RETURN_VALUE_STRUCT_CONVENTION; + } + + if (writebuf) + arm_store_return_value (valtype, regcache, writebuf); + + if (readbuf) + arm_extract_return_value (valtype, regcache, readbuf); + + return RETURN_VALUE_REGISTER_CONVENTION; +} + + static int arm_get_longjmp_target (CORE_ADDR *pc) { @@ -2565,6 +2675,10 @@ arm_elf_osabi_sniffer (bfd *abfd) osabi = GDB_OSABI_ARM_EABI_V2; break; + case EF_ARM_EABI_VER4: + osabi = GDB_OSABI_ARM_EABI_V4; + break; + case EF_ARM_EABI_UNKNOWN: /* Assume GNU tools. */ osabi = GDB_OSABI_ARM_APCS; @@ -2577,6 +2691,12 @@ arm_elf_osabi_sniffer: Unknown ARM EABI version 0x%x"), eflags); } } + else if (osabi == GDB_OSABI_LINUX) + { + eflags = EF_ARM_EABI_VERSION (elf_elfheader (abfd)->e_flags); + if (eflags == EF_ARM_EABI_VER4) + osabi = GDB_OSABI_ARM_EABI_V4_LINUX; + } break; case ELFOSABI_ARM: @@ -2653,10 +2773,20 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep = xmalloc (sizeof (struct gdbarch_tdep)); gdbarch = gdbarch_alloc (&info, tdep); - /* 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. */ - tdep->fp_model = ARM_FLOAT_SOFT_FPA; + if (info.osabi == GDB_OSABI_ARM_EABI_V4 || info.osabi == GDB_OSABI_ARM_EABI_V4_LINUX) + { + /* Default EABI targets to soft-vfp. */ + tdep->fp_model = ARM_FLOAT_SOFT_VFP; + tdep->abi = ARM_ABI_AAPCS; + } + else + { + /* 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. */ + tdep->fp_model = ARM_FLOAT_SOFT_FPA; + tdep->abi = ARM_ABI_APCS_GNU; + } /* Breakpoints. */ switch (info.byte_order) @@ -2690,6 +2820,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) tdep->jb_pc = -1; /* Longjump support not enabled by default. */ set_gdbarch_push_dummy_call (gdbarch, arm_push_dummy_call); + set_gdbarch_frame_align (gdbarch, arm_frame_align); set_gdbarch_write_pc (gdbarch, arm_write_pc); @@ -2733,10 +2864,7 @@ arm_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_name (gdbarch, arm_register_name); /* Returning results. */ - set_gdbarch_extract_return_value (gdbarch, arm_extract_return_value); - set_gdbarch_store_return_value (gdbarch, arm_store_return_value); - set_gdbarch_deprecated_use_struct_convention (gdbarch, arm_use_struct_convention); - set_gdbarch_deprecated_extract_struct_value_address (gdbarch, arm_extract_struct_value_address); + set_gdbarch_return_value (gdbarch, arm_return_value); /* Single stepping. */ /* XXX For an RDI target we should ask the target if it can single-step. */ @@ -2815,6 +2943,13 @@ arm_init_abi_eabi_v2 (struct gdbarch_info info, } static void +arm_init_abi_eabi_v4 (struct gdbarch_info info, + struct gdbarch *gdbarch) +{ + /* Place-holder. */ +} + +static void arm_init_abi_apcs (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -2849,6 +2984,8 @@ _initialize_arm_tdep (void) arm_init_abi_eabi_v1); gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V2, arm_init_abi_eabi_v2); + gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_EABI_V4, + arm_init_abi_eabi_v4); gdbarch_register_osabi (bfd_arch_arm, 0, GDB_OSABI_ARM_APCS, arm_init_abi_apcs); diff --git a/gdb/arm-tdep.h b/gdb/arm-tdep.h index bb30455..6631501 100644 --- a/gdb/arm-tdep.h +++ b/gdb/arm-tdep.h @@ -116,6 +116,12 @@ enum arm_float_model /* A method to the setting based on user's choice and ABI setting. */ enum arm_float_model arm_get_fp_model (struct gdbarch *); +enum arm_abi_variant +{ + ARM_ABI_APCS_GNU, + ARM_ABI_AAPCS +}; + /* Target-dependent structure in gdbarch. */ struct gdbarch_tdep { @@ -133,6 +139,8 @@ struct gdbarch_tdep If this is negative, longjmp support will be disabled. */ size_t jb_elt_size; /* And the size of each entry in the buf. */ + + enum arm_abi_variant abi; /* Which abi variant is in use. */ }; #ifndef LOWEST_PC diff --git a/gdb/configure.tgt b/gdb/configure.tgt index 9f75087..1b0e08a 100644 --- a/gdb/configure.tgt +++ b/gdb/configure.tgt @@ -209,6 +209,8 @@ esac # map target onto default OS ABI case "${target}" in +arm*-*-linux-gnueabi) + gdb_osabi=GDB_OSABI_ARM_EABI_V4_LINUX ;; *-*-linux*) gdb_osabi=GDB_OSABI_LINUX ;; *-*-nto*) gdb_osabi=GDB_OSABI_QNXNTO ;; m68*-*-openbsd* | m88*-*-openbsd* | vax-*-openbsd*) ;; @@ -954,6 +954,8 @@ enum gdb_osabi GDB_OSABI_ARM_EABI_V1, GDB_OSABI_ARM_EABI_V2, + GDB_OSABI_ARM_EABI_V4, + GDB_OSABI_ARM_EABI_V4_LINUX, GDB_OSABI_ARM_APCS, GDB_OSABI_QNXNTO, diff --git a/gdb/osabi.c b/gdb/osabi.c index 698e941..a60c390 100644 --- a/gdb/osabi.c +++ b/gdb/osabi.c @@ -73,6 +73,8 @@ static const char * const gdb_osabi_names[] = "ARM EABI v1", "ARM EABI v2", + "ARM EABI v4", + "ARM EABI v4 GNU/Linux", "ARM APCS", "QNX Neutrino", diff --git a/gdb/testsuite/gdb.base/long_long.exp b/gdb/testsuite/gdb.base/long_long.exp index b36b30b..0b05d62 100644 --- a/gdb/testsuite/gdb.base/long_long.exp +++ b/gdb/testsuite/gdb.base/long_long.exp @@ -201,13 +201,16 @@ gdb_test_ptr "p/a val.oct" "" "" "0x77053977" "0xa72ee53977053977" gdb_test "p/c val.oct" "'w'" if { $sizeof_double == 8 || $sizeof_long_double == 8 } { - # ARM floating point numbers are not strictly little endian or big endian, - # but a hybrid. They are in little endian format with the two words - # swapped in big endian format. + # ARM FPA floating point numbers are not strictly little endian or big + # endian, but a hybrid. They are in little endian format with the two + # words swapped in big endian format. + # EABI targets default to natural-endian VFP format - if { [istarget "arm*-*-*"] || \ + if { ([istarget "arm*-*-*"] || \ [istarget "xscale*-*-*"] || \ - [istarget "strongarm*-*-*"] } then { + [istarget "strongarm*-*-*"]) \ + && !([istarget "*-*-*eabi"] || \ + [istarget "*-*-symbianelf"]) } then { # assume the long long represents a floating point double in ARM format gdb_test "p/f val.oct" "2.1386676354387559e\\+265" } else { |