From: "Ulrich Weigand" <uweigand@de.ibm.com>
To: palves@redhat.com
Cc: gdb-patches@sourceware.org
Subject: [RFC] Fix SW breakpoint handling for Cell multi-arch
Date: Thu, 27 Aug 2015 11:54:00 -0000 [thread overview]
Message-ID: <20150827115423.571F824DD@oc7340732750.ibm.com> (raw)
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;
--
Dr. Ulrich Weigand
GNU/Linux compilers and toolchain
Ulrich.Weigand@de.ibm.com
next reply other threads:[~2015-08-27 11:54 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-08-27 11:54 Ulrich Weigand [this message]
2015-08-27 15:43 ` Pedro Alves
2015-08-27 16:23 ` Ulrich Weigand
2015-08-27 16:44 ` Pedro Alves
2015-08-27 17:40 ` Ulrich Weigand
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20150827115423.571F824DD@oc7340732750.ibm.com \
--to=uweigand@de.ibm.com \
--cc=gdb-patches@sourceware.org \
--cc=palves@redhat.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox