X-Git-Url: http://drtracing.org/?a=blobdiff_plain;f=gdb%2Fppc-sysv-tdep.c;h=1c2644deb5f5c29803a7c4e7b2f2266a39f6c497;hb=b08b78e7d4bb56f395d3212eed6184ede236c760;hp=f6b24bf92a989918fd9ca6cdf563d0d94c5ee313;hpb=52f548e41f085550d7740c350c1c8a239532af77;p=deliverable%2Fbinutils-gdb.git diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index f6b24bf92a..1c2644deb5 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -1,7 +1,7 @@ /* Target-dependent code for PowerPC systems using the SVR4 ABI for GDB, the GNU debugger. - Copyright (C) 2000-2014 Free Software Foundation, Inc. + Copyright (C) 2000-2015 Free Software Foundation, Inc. This file is part of GDB. @@ -23,8 +23,6 @@ #include "inferior.h" #include "regcache.h" #include "value.h" -#include -#include "gdb_assert.h" #include "ppc-tdep.h" #include "target.h" #include "objfiles.h" @@ -610,7 +608,7 @@ ppc_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } /* Handle the return-value conventions for Decimal Floating Point values. */ -static int +static enum return_value_convention get_decimal_float_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) @@ -1076,12 +1074,12 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr) { struct obj_section *dot_fn_section; struct bound_minimal_symbol dot_fn; - struct minimal_symbol *fn; + struct bound_minimal_symbol fn; /* Find the minimal symbol that corresponds to CODE_ADDR (should have a name of the form ".FN"). */ dot_fn = lookup_minimal_symbol_by_pc (code_addr); - if (dot_fn.minsym == NULL || SYMBOL_LINKAGE_NAME (dot_fn.minsym)[0] != '.') + if (dot_fn.minsym == NULL || MSYMBOL_LINKAGE_NAME (dot_fn.minsym)[0] != '.') return 0; /* Get the section that contains CODE_ADDR. Need this for the "objfile" that it contains. */ @@ -1092,15 +1090,169 @@ convert_code_addr_to_desc_addr (CORE_ADDR code_addr, CORE_ADDR *desc_addr) address. Only look for the minimal symbol in ".FN"'s object file - avoids problems when two object files (i.e., shared libraries) contain a minimal symbol with the same name. */ - fn = lookup_minimal_symbol (SYMBOL_LINKAGE_NAME (dot_fn.minsym) + 1, NULL, + fn = lookup_minimal_symbol (MSYMBOL_LINKAGE_NAME (dot_fn.minsym) + 1, NULL, dot_fn_section->objfile); - if (fn == NULL) + if (fn.minsym == NULL) return 0; /* Found a descriptor. */ - (*desc_addr) = SYMBOL_VALUE_ADDRESS (fn); + (*desc_addr) = BMSYMBOL_VALUE_ADDRESS (fn); return 1; } +/* Walk down the type tree of TYPE counting consecutive base elements. + If *FIELD_TYPE is NULL, then set it to the first valid floating point + or vector type. If a non-floating point or vector type is found, or + if a floating point or vector type that doesn't match a non-NULL + *FIELD_TYPE is found, then return -1, otherwise return the count in the + sub-tree. */ + +static LONGEST +ppc64_aggregate_candidate (struct type *type, + struct type **field_type) +{ + type = check_typedef (type); + + switch (TYPE_CODE (type)) + { + case TYPE_CODE_FLT: + case TYPE_CODE_DECFLOAT: + if (!*field_type) + *field_type = type; + if (TYPE_CODE (*field_type) == TYPE_CODE (type) + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 1; + break; + + case TYPE_CODE_COMPLEX: + type = TYPE_TARGET_TYPE (type); + if (TYPE_CODE (type) == TYPE_CODE_FLT + || TYPE_CODE (type) == TYPE_CODE_DECFLOAT) + { + if (!*field_type) + *field_type = type; + if (TYPE_CODE (*field_type) == TYPE_CODE (type) + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 2; + } + break; + + case TYPE_CODE_ARRAY: + if (TYPE_VECTOR (type)) + { + if (!*field_type) + *field_type = type; + if (TYPE_CODE (*field_type) == TYPE_CODE (type) + && TYPE_LENGTH (*field_type) == TYPE_LENGTH (type)) + return 1; + } + else + { + LONGEST count, low_bound, high_bound; + + count = ppc64_aggregate_candidate + (TYPE_TARGET_TYPE (type), field_type); + if (count == -1) + return -1; + + if (!get_array_bounds (type, &low_bound, &high_bound)) + return -1; + count *= high_bound - low_bound; + + /* There must be no padding. */ + if (count == 0) + return TYPE_LENGTH (type) == 0 ? 0 : -1; + else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type)) + return -1; + + return count; + } + break; + + case TYPE_CODE_STRUCT: + case TYPE_CODE_UNION: + { + LONGEST count = 0; + int i; + + for (i = 0; i < TYPE_NFIELDS (type); i++) + { + LONGEST sub_count; + + if (field_is_static (&TYPE_FIELD (type, i))) + continue; + + sub_count = ppc64_aggregate_candidate + (TYPE_FIELD_TYPE (type, i), field_type); + if (sub_count == -1) + return -1; + + if (TYPE_CODE (type) == TYPE_CODE_STRUCT) + count += sub_count; + else + count = max (count, sub_count); + } + + /* There must be no padding. */ + if (count == 0) + return TYPE_LENGTH (type) == 0 ? 0 : -1; + else if (TYPE_LENGTH (type) != count * TYPE_LENGTH (*field_type)) + return -1; + + return count; + } + break; + + default: + break; + } + + return -1; +} + +/* If an argument of type TYPE is a homogeneous float or vector aggregate + that shall be passed in FP/vector registers according to the ELFv2 ABI, + return the homogeneous element type in *ELT_TYPE and the number of + elements in *N_ELTS, and return non-zero. Otherwise, return zero. */ + +static int +ppc64_elfv2_abi_homogeneous_aggregate (struct type *type, + struct type **elt_type, int *n_elts) +{ + /* Complex types at the top level are treated separately. However, + complex types can be elements of homogeneous aggregates. */ + if (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || (TYPE_CODE (type) == TYPE_CODE_ARRAY && !TYPE_VECTOR (type))) + { + struct type *field_type = NULL; + LONGEST field_count = ppc64_aggregate_candidate (type, &field_type); + + if (field_count > 0) + { + int n_regs = ((TYPE_CODE (field_type) == TYPE_CODE_FLT + || TYPE_CODE (field_type) == TYPE_CODE_DECFLOAT)? + (TYPE_LENGTH (field_type) + 7) >> 3 : 1); + + /* The ELFv2 ABI allows homogeneous aggregates to occupy + up to 8 registers. */ + if (field_count * n_regs <= 8) + { + if (elt_type) + *elt_type = field_type; + if (n_elts) + *n_elts = (int) field_count; + /* Note that field_count is LONGEST since it may hold the size + of an array, while *n_elts is int since its value is bounded + by the number of registers used for argument passing. The + cast cannot overflow due to the bounds checking above. */ + return 1; + } + } + } + + return 0; +} + /* Structure holding the next argument position. */ struct ppc64_sysv_argpos { @@ -1389,6 +1541,29 @@ ppc64_sysv_abi_push_param (struct gdbarch *gdbarch, if (TYPE_CODE (type) == TYPE_CODE_FLT) ppc64_sysv_abi_push_freg (gdbarch, type, val, argpos); } + + /* In the ELFv2 ABI, homogeneous floating-point or vector + aggregates are passed in a series of registers. */ + if (tdep->elf_abi == POWERPC_ELF_V2) + { + struct type *eltype; + int i, nelt; + + if (ppc64_elfv2_abi_homogeneous_aggregate (type, &eltype, &nelt)) + for (i = 0; i < nelt; i++) + { + const gdb_byte *elval = val + i * TYPE_LENGTH (eltype); + + if (TYPE_CODE (eltype) == TYPE_CODE_FLT + || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT) + ppc64_sysv_abi_push_freg (gdbarch, eltype, elval, argpos); + else if (TYPE_CODE (eltype) == TYPE_CODE_ARRAY + && TYPE_VECTOR (eltype) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (eltype) == 16) + ppc64_sysv_abi_push_vreg (gdbarch, elval, argpos); + } + } } } @@ -1717,7 +1892,8 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, } /* AltiVec vectors are returned in VRs starting at v2. */ - if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype) + if (TYPE_LENGTH (valtype) == 16 + && TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype) && tdep->vector_abi == POWERPC_VEC_ALTIVEC) { int regnum = tdep->ppc_vr0_regnum + 2 + index; @@ -1729,6 +1905,25 @@ ppc64_sysv_abi_return_value_base (struct gdbarch *gdbarch, struct type *valtype, return 1; } + /* Short vectors are returned in GPRs starting at r3. */ + if (TYPE_LENGTH (valtype) <= 8 + && TYPE_CODE (valtype) == TYPE_CODE_ARRAY && TYPE_VECTOR (valtype)) + { + int regnum = tdep->ppc_gp0_regnum + 3 + index; + int offset = 0; + + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG) + offset = 8 - TYPE_LENGTH (valtype); + + if (writebuf != NULL) + regcache_cooked_write_part (regcache, regnum, + offset, TYPE_LENGTH (valtype), writebuf); + if (readbuf != NULL) + regcache_cooked_read_part (regcache, regnum, + offset, TYPE_LENGTH (valtype), readbuf); + return 1; + } + return 0; } @@ -1818,6 +2013,7 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, /* Small character arrays are returned, right justified, in r3. */ if (TYPE_CODE (valtype) == TYPE_CODE_ARRAY + && !TYPE_VECTOR (valtype) && TYPE_LENGTH (valtype) <= 8 && TYPE_CODE (TYPE_TARGET_TYPE (valtype)) == TYPE_CODE_INT && TYPE_LENGTH (TYPE_TARGET_TYPE (valtype)) == 1) @@ -1834,6 +2030,78 @@ ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct value *function, return RETURN_VALUE_REGISTER_CONVENTION; } + /* In the ELFv2 ABI, homogeneous floating-point or vector + aggregates are returned in registers. */ + if (tdep->elf_abi == POWERPC_ELF_V2 + && ppc64_elfv2_abi_homogeneous_aggregate (valtype, &eltype, &nelt) + && (TYPE_CODE (eltype) == TYPE_CODE_FLT + || TYPE_CODE (eltype) == TYPE_CODE_DECFLOAT + || (TYPE_CODE (eltype) == TYPE_CODE_ARRAY + && TYPE_VECTOR (eltype) + && tdep->vector_abi == POWERPC_VEC_ALTIVEC + && TYPE_LENGTH (eltype) == 16))) + { + for (i = 0; i < nelt; i++) + { + ok = ppc64_sysv_abi_return_value_base (gdbarch, eltype, regcache, + readbuf, writebuf, i); + gdb_assert (ok); + + if (readbuf) + readbuf += TYPE_LENGTH (eltype); + if (writebuf) + writebuf += TYPE_LENGTH (eltype); + } + + return RETURN_VALUE_REGISTER_CONVENTION; + } + + /* In the ELFv2 ABI, aggregate types of up to 16 bytes are + returned in registers r3:r4. */ + if (tdep->elf_abi == POWERPC_ELF_V2 + && TYPE_LENGTH (valtype) <= 16 + && (TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || (TYPE_CODE (valtype) == TYPE_CODE_ARRAY + && !TYPE_VECTOR (valtype)))) + { + int n_regs = ((TYPE_LENGTH (valtype) + tdep->wordsize - 1) + / tdep->wordsize); + int i; + + for (i = 0; i < n_regs; i++) + { + gdb_byte regval[MAX_REGISTER_SIZE]; + int regnum = tdep->ppc_gp0_regnum + 3 + i; + int offset = i * tdep->wordsize; + int len = TYPE_LENGTH (valtype) - offset; + + if (len > tdep->wordsize) + len = tdep->wordsize; + + if (writebuf != NULL) + { + memset (regval, 0, sizeof regval); + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + && offset == 0) + memcpy (regval + tdep->wordsize - len, writebuf, len); + else + memcpy (regval, writebuf + offset, len); + regcache_cooked_write (regcache, regnum, regval); + } + if (readbuf != NULL) + { + regcache_cooked_read (regcache, regnum, regval); + if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_BIG + && offset == 0) + memcpy (readbuf, regval + tdep->wordsize - len, len); + else + memcpy (readbuf + offset, regval, len); + } + } + return RETURN_VALUE_REGISTER_CONVENTION; + } + /* Handle plain base types. */ if (ppc64_sysv_abi_return_value_base (gdbarch, valtype, regcache, readbuf, writebuf, 0))