Skip to content

Commit 148fe97

Browse files
committed
xtensa: gdbstub: fix backtracing and stack unwinding
This fixes GDB backtracing by forcibly spilling all registers, and returning 0s for WINDOWSTART and WINDOWBASE. This is effectively telling GDB that none of physical registers contains active data, and must rely on spilled values on stack. Otherwise, GDB will try to look at AR* registers for previous frame(s). Since we don't save all AR* register values, there is nothing for GDB to look at, and thus failing to unwind stack. With this change, there is no need to populate a portion of the AR* registers, and no need for keep tracking where those registers related to windowed are. Signed-off-by: Daniel Leung <[email protected]>
1 parent 2110725 commit 148fe97

File tree

2 files changed

+19
-44
lines changed

2 files changed

+19
-44
lines changed

arch/xtensa/core/gdbstub.c

+19-38
Original file line numberDiff line numberDiff line change
@@ -178,11 +178,17 @@ static void read_sreg(struct gdb_ctx *ctx, struct xtensa_register *reg)
178178
break;
179179
#endif
180180
#if XCHAL_HAVE_WINDOWED
181+
/* Returning 0s is needed for stack unwinding to work.
182+
* This is effectively telling GDB that none of physical registers
183+
* contains active data, and must rely on spilled values on stack.
184+
* Otherwise, GDB will try to look at AR* registers for previous
185+
* frame(s). Since we don't save all AR* register values, there is
186+
* nothing for GDB to look at, and thus failing to unwind stack.
187+
*/
181188
case WINDOWBASE:
182-
val = get_one_sreg(WINDOWBASE);
183-
break;
189+
__fallthrough;
184190
case WINDOWSTART:
185-
val = get_one_sreg(WINDOWSTART);
191+
val = 0;
186192
break;
187193
#endif
188194
#if XCHAL_NUM_INTLEVELS > 0
@@ -426,6 +432,16 @@ static void copy_to_ctx(struct gdb_ctx *ctx, const struct arch_esf *stack)
426432
{
427433
struct xtensa_register *reg;
428434
int idx, num_laddr_regs;
435+
int32_t a0save;
436+
437+
/* Need to spill all registers so their values are on the stack instead of
438+
* the physical register file. This is required for GDB backtracing to
439+
* walk through stack.
440+
*/
441+
__asm__ volatile("mov %0, a0;"
442+
"call0 xtensa_spill_reg_windows;"
443+
"mov a0, %0"
444+
: "=r"(a0save));
429445

430446
uint32_t *bsa = *(const int **)stack;
431447

@@ -469,33 +485,6 @@ static void copy_to_ctx(struct gdb_ctx *ctx, const struct arch_esf *stack)
469485
}
470486
}
471487

472-
#if XCHAL_HAVE_WINDOWED
473-
uint8_t a0_idx, ar_idx, wb_start;
474-
475-
wb_start = (uint8_t)xtensa_gdb_ctx.regs[xtensa_gdb_ctx.wb_idx].val;
476-
477-
/*
478-
* Copied the logical registers A0-A15 to physical registers (AR*)
479-
* according to WINDOWBASE.
480-
*/
481-
for (idx = 0; idx < num_laddr_regs; idx++) {
482-
/* Index to register description array for A */
483-
a0_idx = xtensa_gdb_ctx.a0_idx + idx;
484-
485-
/* Find the start of window (== WINDOWBASE * 4) */
486-
ar_idx = wb_start * 4;
487-
/* Which logical register we are working on... */
488-
ar_idx += idx;
489-
/* Wrap around A64 (or A32) -> A0 */
490-
ar_idx %= XCHAL_NUM_AREGS;
491-
/* Index to register description array for AR */
492-
ar_idx += xtensa_gdb_ctx.ar_idx;
493-
494-
xtensa_gdb_ctx.regs[ar_idx].val = xtensa_gdb_ctx.regs[a0_idx].val;
495-
xtensa_gdb_ctx.regs[ar_idx].seqno = xtensa_gdb_ctx.regs[a0_idx].seqno;
496-
}
497-
#endif
498-
499488
/* Disable stepping */
500489
set_one_sreg(ICOUNT, 0);
501490
set_one_sreg(ICOUNTLEVEL, 0);
@@ -951,14 +940,6 @@ void arch_gdb_init(void)
951940
/* A0: 0x0000 */
952941
xtensa_gdb_ctx.a0_idx = idx;
953942
break;
954-
case XTREG_GRP_ADDR:
955-
/* AR0: 0x0100 */
956-
xtensa_gdb_ctx.ar_idx = idx;
957-
break;
958-
case (XTREG_GRP_SPECIAL + WINDOWBASE):
959-
/* WINDOWBASE (Special Register) */
960-
xtensa_gdb_ctx.wb_idx = idx;
961-
break;
962943
default:
963944
break;
964945
};

include/zephyr/arch/xtensa/gdbstub.h

-6
Original file line numberDiff line numberDiff line change
@@ -99,12 +99,6 @@ struct gdb_ctx {
9999

100100
/** Index in register descriptions of A0 register */
101101
uint8_t a0_idx;
102-
103-
/** Index in register descriptions of AR0 register */
104-
uint8_t ar_idx;
105-
106-
/** Index in register descriptions of WINDOWBASE register */
107-
uint8_t wb_idx;
108102
};
109103

110104
/**

0 commit comments

Comments
 (0)