From patchwork Thu Aug 27 11:54:23 2015 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ulrich Weigand X-Patchwork-Id: 8474 Received: (qmail 27937 invoked by alias); 27 Aug 2015 11:54:52 -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 27925 invoked by uid 89); 27 Aug 2015 11:54:51 -0000 Authentication-Results: sourceware.org; auth=none X-Virus-Found: No X-Spam-SWARE-Status: No, score=-2.9 required=5.0 tests=AWL, BAYES_00, RP_MATCHES_RCVD, SPF_PASS autolearn=ham version=3.3.2 X-HELO: e06smtp12.uk.ibm.com Received: from e06smtp12.uk.ibm.com (HELO e06smtp12.uk.ibm.com) (195.75.94.108) by sourceware.org (qpsmtpd/0.93/v0.84-503-g423c35a) with (CAMELLIA256-SHA encrypted) ESMTPS; Thu, 27 Aug 2015 11:54:50 +0000 Received: from /spool/local by e06smtp12.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 27 Aug 2015 12:54:46 +0100 Received: from d06dlp03.portsmouth.uk.ibm.com (9.149.20.15) by e06smtp12.uk.ibm.com (192.168.101.142) with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted; Thu, 27 Aug 2015 12:54:45 +0100 X-MailFrom: uweigand@de.ibm.com X-RcptTo: gdb-patches@sourceware.org Received: from b06cxnps4075.portsmouth.uk.ibm.com (d06relay12.portsmouth.uk.ibm.com [9.149.109.197]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id A998C1B08070 for ; Thu, 27 Aug 2015 12:56:17 +0100 (BST) Received: from d06av09.portsmouth.uk.ibm.com (d06av09.portsmouth.uk.ibm.com [9.149.37.250]) by b06cxnps4075.portsmouth.uk.ibm.com (8.14.9/8.14.9/NCO v10.0) with ESMTP id t7RBsg6629622460 for ; Thu, 27 Aug 2015 11:54:45 GMT Received: from d06av09.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id t7RBsWEZ032282 for ; Thu, 27 Aug 2015 05:54:32 -0600 Received: from oc7340732750.ibm.com (dyn-9-152-213-24.boeblingen.de.ibm.com [9.152.213.24]) by d06av09.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id t7RBsWlb031954; Thu, 27 Aug 2015 05:54:32 -0600 Received: by oc7340732750.ibm.com (Postfix, from userid 500) id 571F824DD; Thu, 27 Aug 2015 13:54:23 +0200 (CEST) Subject: [RFC] Fix SW breakpoint handling for Cell multi-arch To: palves@redhat.com Date: Thu, 27 Aug 2015 13:54:23 +0200 (CEST) From: "Ulrich Weigand" Cc: gdb-patches@sourceware.org MIME-Version: 1.0 Message-Id: <20150827115423.571F824DD@oc7340732750.ibm.com> X-TM-AS-MML: disable X-Content-Scanned: Fidelis XPS MAILER x-cbid: 15082711-0009-0000-0000-000005592BEA Hi Pedro, a second major issue with Cell multi-arch debugging right now is related to the new target-side SW breakpoint handling. Cell uses linux-nat as primary target for the PowerPC side, which now returns true from the to_supports_stopped_by_sw_breakpoint hook. This works fine for the PowerPC side. However, when a breakpoint on the SPU side is hit, the kernel does *not* provide a siginfo with TRAP_BRKPT, but instead simply delivers a SIGTRAP without siginfo. The linux-nat target therefore does not recognize the breakpoint and does decrement the PC; this completely throws off infrun, which expects the target to have done this. The attached patch fixes this in the spu-multiarch target by overriding to_wait as well as to to_stopped_by_sw_breakpoint, and handles the SPU case there. This does seem to fix the problem for me. Does this look reasonable to you, or do you have any other suggestions? Thanks, Ulrich Index: binutils-gdb/gdb/spu-multiarch.c =================================================================== --- binutils-gdb.orig/gdb/spu-multiarch.c +++ binutils-gdb/gdb/spu-multiarch.c @@ -311,6 +311,76 @@ spu_search_memory (struct target_ops* op pattern, pattern_len, found_addrp); } +/* Override the to_wait routine. */ +static ptid_t +spu_wait (struct target_ops *ops, + ptid_t ptid, struct target_waitstatus *ourstatus, + int target_options) +{ + struct target_ops *ops_beneath = find_target_beneath (ops); + ptid_t event_ptid; + + event_ptid = ops_beneath->to_wait (ops_beneath, ptid, + ourstatus, target_options); + + /* Special handling is only necessary if we got some trap. */ + if (ourstatus->kind != TARGET_WAITKIND_STOPPED + || ourstatus->value.sig != GDB_SIGNAL_TRAP) + return event_ptid; + + /* If the target is supposed to recognize SW breakpoints, we have a problem. + While linux-nat handles this just fine on the PPU side, the kernel does + not report SW breakpoints on the SPU side. So we detect this case and + handle it manually here. */ + if (ops_beneath->to_supports_stopped_by_sw_breakpoint (ops_beneath)) + { + struct regcache *regcache = get_thread_regcache (event_ptid); + CORE_ADDR pc = regcache_read_pc (regcache); + + if (SPUADDR_SPU (pc) >= 0) + { + struct address_space *aspace = get_regcache_aspace (regcache); + + /* We're supposed to perform decr_pc_after_break processing in the + target_wait routine, so we do it here. The following code is + basically equivalent to adjust_pc_after_break, but makes some + assumptions that are always true on SPU: decr_pc_after_break is + a nonzero value, and hardware single-stepping is unsupported. */ + pc -= gdbarch_decr_pc_after_break (get_regcache_arch (regcache)); + + if (software_breakpoint_inserted_here_p (aspace, pc) + || (target_is_non_stop_p () + && moribund_breakpoint_here_p (aspace, pc))) + regcache_write_pc (regcache, pc); + } + } + + return event_ptid; +} + +/* Override the to_stopped_by_sw_breakpoint routine. */ +static int +spu_stopped_by_sw_breakpoint (struct target_ops *ops) +{ + struct target_ops *ops_beneath = find_target_beneath (ops); + + /* We have to handle this here if we stopped on the SPU; see spu_wait. */ + struct regcache *regcache = get_thread_regcache (inferior_ptid); + CORE_ADDR pc = regcache_read_pc (regcache); + + if (SPUADDR_SPU (pc) >= 0) + { + struct address_space *aspace = get_regcache_aspace (regcache); + + /* Note that decr_pc_after_break processing was done in spu_wait. */ + return (software_breakpoint_inserted_here_p (aspace, pc) + || (target_is_non_stop_p () + && moribund_breakpoint_here_p (aspace, pc))); + } + + return ops_beneath->to_stopped_by_sw_breakpoint (ops_beneath); +} + /* Push and pop the SPU multi-architecture support target. */ @@ -386,6 +456,8 @@ init_spu_ops (void) spu_ops.to_xfer_partial = spu_xfer_partial; spu_ops.to_search_memory = spu_search_memory; spu_ops.to_region_ok_for_hw_watchpoint = spu_region_ok_for_hw_watchpoint; + spu_ops.to_wait = spu_wait; + spu_ops.to_stopped_by_sw_breakpoint = spu_stopped_by_sw_breakpoint; spu_ops.to_thread_architecture = spu_thread_architecture; spu_ops.to_stratum = arch_stratum; spu_ops.to_magic = OPS_MAGIC;