diff options
author | Vladimir Mezentsev <vladimir.mezentsev@oracle.com> | 2017-05-19 03:06:19 -0700 |
---|---|---|
committer | Jose E. Marchesi <jose.marchesi@oracle.com> | 2017-05-19 03:06:19 -0700 |
commit | 1933fd8ee01ad2e74a9c6341bc40f54962a8f889 (patch) | |
tree | 4fa1d4f8a0b9c540d3efcc87c6fe499534ecdde3 | |
parent | eb026f09eb6fcb96a5de1e655cdde041ba44affb (diff) | |
download | fsf-binutils-gdb-1933fd8ee01ad2e74a9c6341bc40f54962a8f889.zip fsf-binutils-gdb-1933fd8ee01ad2e74a9c6341bc40f54962a8f889.tar.gz fsf-binutils-gdb-1933fd8ee01ad2e74a9c6341bc40f54962a8f889.tar.bz2 |
gdb: fix TYPE_CODE_ARRAY handling in sparc targets
gdb has a special type (TYPE_CODE_ARRAY) to support the gcc extension
(https://gcc.gnu.org/onlinedocs/gcc/Vector-Extensions.html).
TYPE_CODE_ARRAY is handled incorrectly for both (32- and 64-bit) modes
on Sparc machines.
Tested on sparc64-linux-gnu and sparc-solaris (32- and 64-bit mode).
6 tests ( from gdb/testsuite/gdb.base/gnu_vector.exp) failed on
sparc64-Linux and on sparc-Solaris in 32- and 64-bit mode. Now all
these tests passed. gdb/testsuite/gdb.base/gnu_vector.exp has 117
different cases for small (and not small) arrays and structures.
No regressions.
gdb/ChangeLog:
2017-05-19 Vladimir Mezentsev <vladimir.mezentsev@oracle.com>
* sparc-tdep.c (sparc_structure_return_p)
(sparc_arg_on_registers_p): New functions.
(sparc32_store_arguments): Use them.
* sparc64-tdep.c (sparc64_16_byte_align_p)
(sparc64_store_floating_fields, sparc64_extract_floating_fields):
Handle TYPE_CODE_ARRAY.
-rw-r--r-- | gdb/ChangeLog | 9 | ||||
-rw-r--r-- | gdb/sparc-tdep.c | 72 | ||||
-rw-r--r-- | gdb/sparc64-tdep.c | 43 |
3 files changed, 105 insertions, 19 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index fdc2a40..1273ed8 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,12 @@ +2017-05-19 Vladimir Mezentsev <vladimir.mezentsev@oracle.com> + + * sparc-tdep.c (sparc_structure_return_p) + (sparc_arg_on_registers_p): New functions. + (sparc32_store_arguments): Use them. + * sparc64-tdep.c (sparc64_16_byte_align_p) + (sparc64_store_floating_fields, sparc64_extract_floating_fields): + Handle TYPE_CODE_ARRAY. + 2017-05-17 Yao Qi <yao.qi@linaro.org> * cli/cli-decode.c (add_alias_cmd): New function. diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index d1e64b4..fa0e04e 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -298,6 +298,43 @@ sparc_structure_or_union_p (const struct type *type) return 0; } +/* Check whether TYPE is returned on registers. */ + +static bool +sparc_structure_return_p (const struct type *type) +{ + if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 8) + { + struct type *t = check_typedef (TYPE_TARGET_TYPE (type)); + + if (sparc_floating_p (t) && TYPE_LENGTH (t) == 8) + return true; + return false; + } + if (sparc_floating_p (type) && TYPE_LENGTH (type) == 16) + return true; + return sparc_structure_or_union_p (type); +} + +/* Check whether TYPE is passed on registers. */ + +static bool +sparc_arg_on_registers_p (const struct type *type) +{ + if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_LENGTH (type) <= 8) + { + struct type *t = check_typedef (TYPE_TARGET_TYPE (type)); + + if (sparc_floating_p (t) && TYPE_LENGTH (t) == 8) + return false; + return true; + } + if (sparc_structure_or_union_p (type) || sparc_complex_floating_p (type) + || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) + return false; + return true; +} + /* Register information. */ #define SPARC32_FPU_REGISTERS \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ @@ -570,9 +607,7 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, struct type *type = value_type (args[i]); int len = TYPE_LENGTH (type); - if (sparc_structure_or_union_p (type) - || (sparc_floating_p (type) && len == 16) - || sparc_complex_floating_p (type)) + if (!sparc_arg_on_registers_p (type)) { /* Structure, Union and Quad-Precision Arguments. */ sp -= len; @@ -594,11 +629,8 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, else { /* Integral and pointer arguments. */ - gdb_assert (sparc_integral_or_pointer_p (type)); - - if (len < 4) - args[i] = value_cast (builtin_type (gdbarch)->builtin_int32, - args[i]); + gdb_assert (sparc_integral_or_pointer_p (type) + || (TYPE_CODE (type) == TYPE_CODE_ARRAY && len <= 8)); num_elements += ((len + 3) / 4); } } @@ -620,6 +652,15 @@ sparc32_store_arguments (struct regcache *regcache, int nargs, const bfd_byte *valbuf = value_contents (args[i]); struct type *type = value_type (args[i]); int len = TYPE_LENGTH (type); + gdb_byte buf[4]; + + if (len < 4) + { + memset (buf, 0, 4 - len); + memcpy (buf + 4 - len, valbuf, len); + valbuf = buf; + len = 4; + } gdb_assert (len == 4 || len == 8); @@ -1345,10 +1386,10 @@ sparc32_extract_return_value (struct type *type, struct regcache *regcache, int len = TYPE_LENGTH (type); gdb_byte buf[32]; - gdb_assert (!sparc_structure_or_union_p (type)); - gdb_assert (!(sparc_floating_p (type) && len == 16)); + gdb_assert (!sparc_structure_return_p (type)); - if (sparc_floating_p (type) || sparc_complex_floating_p (type)) + if (sparc_floating_p (type) || sparc_complex_floating_p (type) + || TYPE_CODE (type) == TYPE_CODE_ARRAY) { /* Floating return values. */ regcache_cooked_read (regcache, SPARC_F0_REGNUM, buf); @@ -1397,11 +1438,9 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache, const gdb_byte *valbuf) { int len = TYPE_LENGTH (type); - gdb_byte buf[8]; + gdb_byte buf[32]; - gdb_assert (!sparc_structure_or_union_p (type)); - gdb_assert (!(sparc_floating_p (type) && len == 16)); - gdb_assert (len <= 8); + gdb_assert (!sparc_structure_return_p (type)); if (sparc_floating_p (type) || sparc_complex_floating_p (type)) { @@ -1457,8 +1496,7 @@ sparc32_return_value (struct gdbarch *gdbarch, struct value *function, guarantees that we can always find the return value, not just before the function returns. */ - if (sparc_structure_or_union_p (type) - || (sparc_floating_p (type) && TYPE_LENGTH (type) == 16)) + if (sparc_structure_return_p (type)) { ULONGEST sp; CORE_ADDR addr; diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c index 58f5bf0..9e0e6b5 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -669,6 +669,13 @@ static const struct frame_base sparc64_frame_base = static int sparc64_16_byte_align_p (struct type *type) { + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + struct type *t = check_typedef (TYPE_TARGET_TYPE (type)); + + if (sparc64_floating_p (t)) + return 1; + } if (sparc64_floating_p (type) && TYPE_LENGTH (type) == 16) return 1; @@ -703,7 +710,23 @@ sparc64_store_floating_fields (struct regcache *regcache, struct type *type, gdb_assert (element < 16); - if (sparc64_floating_p (type) + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + gdb_byte buf[8]; + int regnum = SPARC_F0_REGNUM + element * 2 + bitpos / 32; + + valbuf += bitpos / 8; + if (len < 8) + { + memset (buf, 0, 8 - len); + memcpy (buf + 8 - len, valbuf, len); + valbuf = buf; + len = 8; + } + for (int n = 0; n < (len + 3) / 4; n++) + regcache_cooked_write (regcache, regnum + n, valbuf + n * 4); + } + else if (sparc64_floating_p (type) || (sparc64_complex_floating_p (type) && len <= 16)) { int regnum; @@ -776,7 +799,23 @@ sparc64_extract_floating_fields (struct regcache *regcache, struct type *type, { struct gdbarch *gdbarch = get_regcache_arch (regcache); - if (sparc64_floating_p (type)) + if (TYPE_CODE (type) == TYPE_CODE_ARRAY) + { + int len = TYPE_LENGTH (type); + int regnum = SPARC_F0_REGNUM + bitpos / 32; + + valbuf += bitpos / 8; + if (len < 4) + { + gdb_byte buf[4]; + regcache_cooked_read (regcache, regnum, buf); + memcpy (valbuf, buf + 4 - len, len); + } + else + for (int i = 0; i < (len + 3) / 4; i++) + regcache_cooked_read (regcache, regnum + i, valbuf + i * 4); + } + else if (sparc64_floating_p (type)) { int len = TYPE_LENGTH (type); int regnum; |