From patchwork Tue May 16 16:09:19 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Vladimir Mezentsev X-Patchwork-Id: 20467 Received: (qmail 93219 invoked by alias); 16 May 2017 16:16:48 -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 90992 invoked by uid 89); 16 May 2017 16:16:46 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-26.9 required=5.0 tests=BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RP_MATCHES_RCVD, SPF_PASS, UNPARSEABLE_RELAY autolearn=ham version=3.3.2 spammy=vladimir 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; Tue, 16 May 2017 16:16:44 +0000 Received: from aserv0022.oracle.com (aserv0022.oracle.com [141.146.126.234]) by userp1040.oracle.com (Sentrion-MTA-4.3.2/Sentrion-MTA-4.3.2) with ESMTP id v4GGGix7028525 (version=TLSv1.2 cipher=ECDHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 16 May 2017 16:16:45 GMT Received: from aserv0122.oracle.com (aserv0122.oracle.com [141.146.126.236]) by aserv0022.oracle.com (8.14.4/8.14.4) with ESMTP id v4GGGi4M002623 (version=TLSv1/SSLv3 cipher=DHE-RSA-AES256-GCM-SHA384 bits=256 verify=OK) for ; Tue, 16 May 2017 16:16:44 GMT Received: from abhmp0009.oracle.com (abhmp0009.oracle.com [141.146.116.15]) by aserv0122.oracle.com (8.14.4/8.14.4) with ESMTP id v4GGGipF019121 for ; Tue, 16 May 2017 16:16:44 GMT Received: from vmezents.us.oracle.com (/10.147.27.113) by default (Oracle Beehive Gateway v4.0) with ESMTP ; Tue, 16 May 2017 09:16:44 -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: Tue, 16 May 2017 11:09:19 -0500 Message-Id: <1494950959-42849-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. gdb/ChangeLog: 2017-05-12 Vladimir Mezentsev * 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. --- gdb/sparc-tdep.c | 72 +++++++++++++++++++++++++++++++++++++++------------ gdb/sparc64-tdep.c | 43 +++++++++++++++++++++++++++++- 2 files changed, 96 insertions(+), 19 deletions(-) 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;