summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Jacobowitz <dan@debian.org>2005-03-25 22:02:38 +0000
committerDaniel Jacobowitz <dan@debian.org>2005-03-25 22:02:38 +0000
commita4cb8d1b61965e487dfca5471fdf56cf94634452 (patch)
tree9e966298f69da5f8494c0c8b267f6070f1b7deee
parent543439cda945fd22a78023845d8ab9b7ae8ea818 (diff)
downloadgdb-a4cb8d1b61965e487dfca5471fdf56cf94634452.tar.gz
* 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.csl34
-rw-r--r--gdb/arm-linux-tdep.c34
-rw-r--r--gdb/arm-tdep.c187
-rw-r--r--gdb/arm-tdep.h8
-rw-r--r--gdb/configure.tgt2
-rw-r--r--gdb/defs.h2
-rw-r--r--gdb/osabi.c2
-rw-r--r--gdb/testsuite/gdb.base/long_long.exp13
8 files changed, 252 insertions, 30 deletions
diff --git a/ChangeLog.csl b/ChangeLog.csl
index 9c902fe48a6..fa7a530a178 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 d4b2899f61e..bcade171134 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 fc7e8feef43..e4958b02dbf 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 bb30455a314..6631501221b 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 9f7508756b3..1b0e08aa41a 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*) ;;
diff --git a/gdb/defs.h b/gdb/defs.h
index fa012a4d28b..40ac4413616 100644
--- a/gdb/defs.h
+++ b/gdb/defs.h
@@ -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 698e941c0c5..a60c3908609 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 b36b30b32b2..0b05d624c33 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 {