From patchwork Fri Nov 14 16:51:33 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Joel Brobecker X-Patchwork-Id: 3742 Received: (qmail 19248 invoked by alias); 14 Nov 2014 16:51:45 -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 19237 invoked by uid 89); 14 Nov 2014 16:51:45 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-1.7 required=5.0 tests=AWL, BAYES_00, SPF_PASS, T_RP_MATCHES_RCVD autolearn=ham version=3.3.2 X-HELO: rock.gnat.com Received: from rock.gnat.com (HELO rock.gnat.com) (205.232.38.15) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (AES256-SHA encrypted) ESMTPS; Fri, 14 Nov 2014 16:51:44 +0000 Received: from localhost (localhost.localdomain [127.0.0.1]) by filtered-rock.gnat.com (Postfix) with ESMTP id 4DD451163FB for ; Fri, 14 Nov 2014 11:51:41 -0500 (EST) Received: from rock.gnat.com ([127.0.0.1]) by localhost (rock.gnat.com [127.0.0.1]) (amavisd-new, port 10024) with LMTP id WfCjSyryITwX for ; Fri, 14 Nov 2014 11:51:41 -0500 (EST) Received: from joel.gnat.com (localhost.localdomain [127.0.0.1]) by rock.gnat.com (Postfix) with ESMTP id D87A91163E2 for ; Fri, 14 Nov 2014 11:51:40 -0500 (EST) Received: by joel.gnat.com (Postfix, from userid 1000) id 50EAE40F79; Fri, 14 Nov 2014 20:51:39 +0400 (RET) From: Joel Brobecker To: gdb-patches@sourceware.org Subject: [RFA/commit] [gdbserver/lynx] spurious failure to write in inferior memory Date: Fri, 14 Nov 2014 20:51:33 +0400 Message-Id: <1415983893-26935-1-git-send-email-brobecker@adacore.com> Hello, We noticed the following error on ppc-lynx178, using just about any program: (gdb) tar remote mytarget:4444 Remote debugging using mytarget:4444 0x000100c8 in _start () (gdb) b try Breakpoint 1 at 0x10844: file try.adb, line 11. (gdb) cont Continuing. !!!-> Cannot remove breakpoints because program is no longer writable. !!!-> Further execution is probably impossible. Breakpoint 1, try () at try.adb:11 11 Local : Integer := 18; And, of course, trying to continue yielded the expected outcome: (gdb) c Continuing. warning: Error removing breakpoint 1 Cannot remove breakpoints because program is no longer writable. Further execution is probably impossible. It turns out that the problem is caused by an intentional test against a variable with an undefined value. After GDB receives notification of the inferior stopping, it tries to remove the breakpoint by sending a memory-write packet ("X10844,4:9 "). This leads us to lynx_write_memory, where it tries to split the memory-write into chunks of 4 bytes. And, in order to handle writes which are not aligned on word boundaries, we have the following code: if (skip > 0 || truncate > 0) /* We need to read the memory at this address in order to preserve the data that we are not overwriting. */ lynx_read_memory (addr, (unsigned char *) &buf, xfer_size); if (errno) return errno; (the comment explains what the code is about). Unfortunately, the not-so-glaring error that we've made here is that we're checking ERRNO regardless of whether we've called lynx_read_memory. In our case, because we are writing 4 bytes aligned on a word boundary, we do not call lynx_read_memory and therefore test an ERRNO with an undefined value. gdb/gdbserver/ChangeLog: * lynx-low.c (lynx_write_memory): Put lynx_read_memory and corresponding ERRNO check in same block. One wonders how we got lucky for so long. In any case, tested on ppc-lynx5 and ppc-lynx178 using AdaCore's testsuite. It's a fairly obvious fix to me, but I will let it sit for a few days... or an approval ;-). Thank you, diff --git a/gdb/gdbserver/lynx-low.c b/gdb/gdbserver/lynx-low.c index 96dea03..6178e03 100644 --- a/gdb/gdbserver/lynx-low.c +++ b/gdb/gdbserver/lynx-low.c @@ -688,11 +688,13 @@ lynx_write_memory (CORE_ADDR memaddr, const unsigned char *myaddr, int len) if (addr + xfer_size > memaddr + len) truncate = addr + xfer_size - memaddr - len; if (skip > 0 || truncate > 0) - /* We need to read the memory at this address in order to preserve - the data that we are not overwriting. */ - lynx_read_memory (addr, (unsigned char *) &buf, xfer_size); - if (errno) - return errno; + { + /* We need to read the memory at this address in order to preserve + the data that we are not overwriting. */ + lynx_read_memory (addr, (unsigned char *) &buf, xfer_size); + if (errno) + return errno; + } memcpy ((gdb_byte *) &buf + skip, myaddr + (addr - memaddr) + skip, xfer_size - skip - truncate); errno = 0;