From patchwork Wed Mar 29 16:17:00 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Mezentsev X-Patchwork-Id: 19760 Received: (qmail 33593 invoked by alias); 29 Mar 2017 16:21:08 -0000 Mailing-List: contact gdb-patches-help@sourceware.org; run by ezmlm Precedence: bulk List-Id: List-Unsubscribe: List-Subscribe: List-Archive: List-Post: List-Help: , Sender: gdb-patches-owner@sourceware.org Delivered-To: mailing list gdb-patches@sourceware.org Received: (qmail 33579 invoked by uid 89); 29 Mar 2017 16:21:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.4 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_SORBS_SPAM, RP_MATCHES_RCVD, SPF_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 spammy= X-HELO: userp1040.oracle.com Received: from userp1040.oracle.com (HELO userp1040.oracle.com) (156.151.31.81) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Wed, 29 Mar 2017 16:21:05 +0000 Received: from aserv0021.oracle.com (aserv0021.oracle.com [141.146.126.233]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v2TGL4Ue019966 (version=TLSv1 cipher=DHE-RSA-AES256-SHA bits=256 verify=OK) for ; Wed, 29 Mar 2017 16:21:04 GMT Received: from aserv0121.oracle.com (aserv0121.oracle.com [141.146.126.235]) by aserv0021.oracle.com (8.13.8/8.14.4) with ESMTP id v2TGL3VL003183 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-SHA bits=256 verify=FAIL) for ; Wed, 29 Mar 2017 16:21:04 GMT Received: from abhmp0019.oracle.com (abhmp0019.oracle.com [141.146.116.25]) by aserv0121.oracle.com (8.13.8/8.13.8) with ESMTP id v2TGL1I6020194 for ; Wed, 29 Mar 2017 16:21:02 GMT Received: from vmezents.us.oracle.com (/10.147.27.113) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Wed, 29 Mar 2017 09:21:01 -0700 From: vladimir.mezentsev@oracle.com To: gdb-patches@sourceware.org Subject: [PATCH] gdb passes and returns incorrect values when dealing with small array on Sparc Date: Wed, 29 Mar 2017 10:17:00 -0600 Message-Id: <1490804220-92717-1-git-send-email-vladimir.mezentsev@oracle.com> From: Vladimir Mezentsev 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). No regressions. 2017-03-27 Vladimir Mezentsev * gdb/sparc-tdep.c (sparc_structure_return_p): New function. * gdb/sparc-tdep.c (sparc_arg_on_registers_p): Likewise. * gdb/sparc-tdep.c (sparc32_store_arguments): Use the new functions. * gdb/sparc64-tdep.c: (sparc64_16_byte_align_p): Handle TYPE_CODE_ARRAY * gdb/sparc64-tdep.c: (sparc64_store_floating_fields): Likewise * gdb/sparc64-tdep.c: (sparc64_extract_floating_fields): Likewise --- gdb/sparc-tdep.c | 68 +++++++++++++++++++++++++++++++++++++++------------- gdb/sparc64-tdep.c | 42 ++++++++++++++++++++++++++++++- 2 files changed, 91 insertions(+), 19 deletions(-) diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index d346aec..07808f3 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -297,6 +297,39 @@ sparc_structure_or_union_p (const struct type *type) return 0; } +static int +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 1; + return 0; + } + if (sparc_floating_p (type) && (TYPE_LENGTH (type) == 16)) + return 1; + return sparc_structure_or_union_p (type); +} + +static int +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 0; + return 1; + } + if (sparc_structure_or_union_p (type) || sparc_complex_floating_p (type) + || (sparc_floating_p (type) && (TYPE_LENGTH (type) == 16))) + return 0; + return 1; +} + /* Register information. */ #define SPARC32_FPU_REGISTERS \ "f0", "f1", "f2", "f3", "f4", "f5", "f6", "f7", \ @@ -569,9 +602,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; @@ -593,11 +624,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); } } @@ -619,6 +647,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); @@ -1344,10 +1381,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); @@ -1396,11 +1433,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)) { @@ -1456,8 +1491,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 bf0da18..0b1a0ee 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -669,6 +669,12 @@ 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 +709,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 +798,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;