From patchwork Thu Jun 21 09:38:02 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Alan Hayward X-Patchwork-Id: 27977 Received: (qmail 16173 invoked by alias); 21 Jun 2018 09:39: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 16107 invoked by uid 89); 21 Jun 2018 09:39:07 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-24.2 required=5.0 tests=AWL, BAYES_00, GIT_PATCH_0, GIT_PATCH_1, GIT_PATCH_2, GIT_PATCH_3, RCVD_IN_DNSWL_NONE, SPF_HELO_PASS, SPF_PASS, UNSUBSCRIBE_BODY autolearn=ham version=3.3.2 spammy= X-HELO: EUR01-HE1-obe.outbound.protection.outlook.com Received: from mail-he1eur01on0064.outbound.protection.outlook.com (HELO EUR01-HE1-obe.outbound.protection.outlook.com) (104.47.0.64) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with ESMTP; Thu, 21 Jun 2018 09:39:05 +0000 Authentication-Results: spf=none (sender IP is ) smtp.mailfrom=Alan.Hayward@arm.com; Received: from C02TF0U7HF1T.manchester.arm.com (217.140.96.140) by AM4PR0802MB2131.eurprd08.prod.outlook.com (2603:10a6:200:5c::22) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.863.16; Thu, 21 Jun 2018 09:38:53 +0000 From: Alan Hayward To: gdb-patches@sourceware.org Cc: nd@arm.com, Alan Hayward Subject: [PATCH v2 3/3] Use partial register read/writes in transfer_regset Date: Thu, 21 Jun 2018 10:38:02 +0100 Message-Id: <20180621093802.79342-4-alan.hayward@arm.com> In-Reply-To: <20180621093802.79342-1-alan.hayward@arm.com> References: <20180621093802.79342-1-alan.hayward@arm.com> MIME-Version: 1.0 X-ClientProxiedBy: CWLP265CA0232.GBRP265.PROD.OUTLOOK.COM (2603:10a6:401:4f::28) To AM4PR0802MB2131.eurprd08.prod.outlook.com (2603:10a6:200:5c::22) X-MS-PublicTrafficType: Email X-MS-Office365-Filtering-HT: Tenant X-MS-Office365-Filtering-Correlation-Id: 789ac77e-a80f-4de0-5e66-08d5d75acd6a X-MS-TrafficTypeDiagnostic: AM4PR0802MB2131: NoDisclaimer: True X-Exchange-Antispam-Report-Test: UriScan:(180628864354917); X-MS-Exchange-SenderADCheck: 1 X-Forefront-PRVS: 07106EF9B9 Received-SPF: None (protection.outlook.com: arm.com does not designate permitted sender hosts) SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: arm.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 21 Jun 2018 09:38:53.4420 (UTC) X-MS-Exchange-CrossTenant-Network-Message-Id: 789ac77e-a80f-4de0-5e66-08d5d75acd6a X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: f34e5979-57d9-4aaa-ad4d-b122a662184d X-MS-Exchange-Transport-CrossTenantHeadersStamped: AM4PR0802MB2131 X-IsSubscribed: yes This avoids assert failures when the register is bigger than the slot size. This happens on Aarch64 when truncating Z registers into an fpsimd structure. Also, when the register is smaller then the slot size, then zero pad when writing to the slot, and truncate when writing to the regcache. This happens on Aarch64 with the CPSR register. Continue to ensure registers are invalidated when both buffers are null. 2018-06-21 Alan Hayward * regcache.c (reg_buffer::raw_collect_part): New function. (reg_buffer::raw_supply_part): Likewise. (regcache::transfer_regset): Call new functions. * regcache.h (reg_buffer::raw_collect_part): New declaration. (reg_buffer::raw_supply_part): Likewise. --- gdb/regcache.c | 93 +++++++++++++++++++++++++++++++++++++++++++++++++++++----- gdb/regcache.h | 10 +++++++ 2 files changed, 95 insertions(+), 8 deletions(-) diff --git a/gdb/regcache.c b/gdb/regcache.c index fe4742c2ee..4939150c66 100644 --- a/gdb/regcache.c +++ b/gdb/regcache.c @@ -807,6 +807,38 @@ readable_regcache::read_part (int regnum, int offset, int len, /* See regcache.h. */ +void +reg_buffer::raw_collect_part (int regnum, int offset, int len, + gdb_byte *out) const +{ + int reg_size = register_size (arch (), regnum); + + gdb_assert (out != nullptr); + gdb_assert (offset >= 0 && len >= 0 && offset <= reg_size); + + if (offset == 0 && len == 0) + return; + + if (offset == 0 && len == reg_size) + return raw_collect (regnum, out); + + /* Read to buffer, then write out. */ + gdb_byte *reg = (gdb_byte *) alloca (reg_size); + raw_collect (regnum, reg); + + if (offset + len <= reg_size) + memcpy (out, reg + offset, len); + else + { + /* Requested region runs off the end of the register. Clear the + additional space. */ + memcpy (out, reg + offset, reg_size - offset); + memset (out + reg_size, 0, offset + len - reg_size); + } +} + +/* See regcache.h. */ + enum register_status regcache::write_part (int regnum, int offset, int len, const gdb_byte *in, bool is_raw) @@ -841,6 +873,38 @@ regcache::write_part (int regnum, int offset, int len, /* See regcache.h. */ +void +reg_buffer::raw_supply_part (int regnum, int offset, int len, + const gdb_byte *in) +{ + int reg_size = register_size (arch (), regnum); + + gdb_assert (in != nullptr); + gdb_assert (offset >= 0 && len >= 0 && offset <= reg_size); + + if (offset == 0 && len == 0) + return; + + if (offset + len > reg_size) + { + /* Truncate length to fit the size of the regcache register. */ + len = reg_size - offset; + } + + if (offset == 0 && len == reg_size) + return raw_supply (regnum, in); + + gdb_byte *reg = (gdb_byte *) alloca (reg_size); + + /* Read when needed. */ + if (offset > 0 || offset + len < reg_size) + raw_collect (regnum, reg); + + /* Write to buffer, then write out. */ + memcpy (reg + offset, in, len); + raw_supply (regnum, reg); +} + enum register_status readable_regcache::raw_read_part (int regnum, int offset, int len, gdb_byte *buf) @@ -1013,12 +1077,18 @@ regcache::transfer_regset (const struct regset *regset, if (offs + slot_size > size) break; + /* Use part versions to prevent possible overflow. */ if (out_buf) - raw_collect (regno, (gdb_byte *) out_buf + offs); + raw_collect_part (regno, 0, slot_size, + (gdb_byte *) out_buf + offs); + else if (in_buf) + out_regcache->raw_supply_part (regno, 0, slot_size, + (const gdb_byte *) in_buf + offs); else - out_regcache->raw_supply (regno, in_buf - ? (const gdb_byte *) in_buf + offs - : NULL); + { + /* Invalidate the register. */ + out_regcache->raw_supply (regno, nullptr); + } } else { @@ -1027,12 +1097,19 @@ regcache::transfer_regset (const struct regset *regset, if (offs + slot_size > size) return; + /* Use part versions to prevent possible overflow. */ if (out_buf) - raw_collect (regnum, (gdb_byte *) out_buf + offs); + raw_collect_part (regnum, 0, slot_size, + (gdb_byte *) out_buf + offs); + else if (in_buf) + out_regcache->raw_supply_part (regnum, 0, slot_size, + (const gdb_byte *) in_buf + offs); else - out_regcache->raw_supply (regnum, in_buf - ? (const gdb_byte *) in_buf + offs - : NULL); + { + /* Invalidate the register. */ + out_regcache->raw_supply (regnum, nullptr); + } + return; } } diff --git a/gdb/regcache.h b/gdb/regcache.h index c17ce09dee..a69b67d513 100644 --- a/gdb/regcache.h +++ b/gdb/regcache.h @@ -162,6 +162,11 @@ public: void raw_collect_integer (int regnum, gdb_byte *addr, int addr_len, bool is_signed) const; + /* Collect register REGNUM from REGCACHE, starting at offset in REGCACHE, + reading only LEN. If this runs off the end of the register, then fill the + additional space with zeros. */ + void raw_collect_part (int regnum, int offset, int len, gdb_byte *out) const; + /* See common/common-regcache.h. */ void raw_supply (int regnum, const void *buf) override; @@ -183,6 +188,11 @@ public: unavailable). */ void raw_supply_zeroed (int regnum); + /* Supply register REGNUM to REGCACHE, starting at offset in REGCACHE, writing + only LEN, without editing the rest of the register. If the length of the + supplied value would overflow the register, then truncate. */ + void raw_supply_part (int regnum, int offset, int len, const gdb_byte *in); + void invalidate (int regnum); virtual ~reg_buffer () = default;