Mirror of the gdb-patches mailing list
 help / color / mirror / Atom feed
* [PATCH] gdb: z80: Fix endless backtrace loop and assertion crashes
@ 2026-06-05 18:56 Ronald Hecht
  2026-06-06 19:40 ` Kevin Buettner
  0 siblings, 1 reply; 10+ messages in thread
From: Ronald Hecht @ 2026-06-05 18:56 UTC (permalink / raw)
  To: gdb-patches; +Cc: Ronald Hecht

This patch fixes two distinct issues in the Z80 frame unwind cache:

1. An infinite loop in the stack pointer wrapping logic. The `for (;; ++sp)`
   loop could run endlessly if the overflow condition `sp < this_base` was
   never met due to 16-bit address space wrapping. Introduced a `loop_count`
   to break out after 4 iterations as a sensible heuristic for Z80.

2. A potential internal GDB assertion failure. The code previously called
   `.addr()` directly on saved registers without verifying if they actually
   held an address, causing crashes when encountering unexpected register
   states (e.g. REG_UNKNOWN). Added a check for `.is_addr()` beforehand.

gdb/ChangeLog:
	* z80-tdep.c (z80_frame_unwind_cache): Prevent infinite loop by
	adding loop_count. Check is_addr() before calling addr().
---
 gdb/z80-tdep.c | 14 ++++++++++----
 1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/gdb/z80-tdep.c b/gdb/z80-tdep.c
index 3a0d5f7e393..5e1c3a877b3 100644
--- a/gdb/z80-tdep.c
+++ b/gdb/z80-tdep.c
@@ -597,6 +597,7 @@ z80_frame_unwind_cache (const frame_info_ptr &this_frame,
       CORE_ADDR sp;
       CORE_ADDR sp_mask = (1 << gdbarch_ptr_bit(gdbarch)) - 1;
       enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
+      int loop_count = 0;
       /* Assume that the FP is this frame's SP but with that pushed
 	 stack space added back.  */
       this_base = get_frame_register_unsigned (this_frame, Z80_SP_REGNUM);
@@ -604,7 +605,7 @@ z80_frame_unwind_cache (const frame_info_ptr &this_frame,
       for (;; ++sp)
 	{
 	  sp &= sp_mask;
-	  if (sp < this_base)
+	  if (++loop_count > 4 || sp < this_base)
 	    { /* overflow, looks like end of stack */
 	      sp = this_base + info->size;
 	      break;
@@ -644,9 +645,14 @@ z80_frame_unwind_cache (const frame_info_ptr &this_frame,
   /* Adjust all the saved registers so that they contain addresses and not
      offsets.  */
   for (i = 0; i < gdbarch_num_regs (gdbarch) - 1; i++)
-    if (info->saved_regs[i].addr () > 0)
-      info->saved_regs[i].set_addr
-	(info->prev_sp - info->saved_regs[i].addr () * addr_len);
+    {
+      if (info->saved_regs[i].is_addr ())
+	{
+	  if (info->saved_regs[i].addr () > 0)
+	    info->saved_regs[i].set_addr
+	      (info->prev_sp - info->saved_regs[i].addr () * addr_len);
+	}
+    }
 
   /* Except for the startup code, the return PC is always saved on
      the stack and is at the base of the frame.  */
-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-07-09  3:52 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-06-05 18:56 [PATCH] gdb: z80: Fix endless backtrace loop and assertion crashes Ronald Hecht
2026-06-06 19:40 ` Kevin Buettner
2026-06-07  7:36   ` Ronald Hecht
2026-06-07  7:48   ` [PATCH v2] " Ronald Hecht
2026-06-14 22:06     ` Kevin Buettner
2026-06-15  6:49       ` Ronald Hecht
2026-06-15  7:04       ` [PATCH v3] gdb: z80: Fix endless loop in frame unwinder and validate saved register types Ronald Hecht
2026-06-20 20:11         ` Kevin Buettner
2026-06-23  7:16           ` Ronald Hecht
2026-07-09  3:52             ` Kevin Buettner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox