This is an automated email from Gerrit. "Name of user not set <daniel.lizew...@gmail.com>" just uploaded a new patch set to Gerrit, which you can find at https://review.openocd.org/c/openocd/+/8180
-- gerrit commit 773dde0dfa8247bf9cad57d8ef93d1db46cf5665 Author: dlizewski <daniel.lizew...@gmail.com> Date: Tue Mar 19 14:10:46 2024 -0400 src/rtos/rtos_nuttx_stackings.c: Fix stack alignment for cortex-m targets Backtraces performed by GDB on any thread other than the current thread would fail if hardware 8 byte ISR stack alignment was enabled. Nuttx stores the stack pointer post alignment because it automatically gets applied/removed by hardware on enter/exit of an ISR. GDB expects registers to be exactly as they were just prior to ISR. This offset causes backtraces to fail on all threads except the currently executing thread and must be adjusted from the stored value. Change-Id: Ifcbeefb0ddcfbcb528daa9d1d95732ca9584c9ef Signed-off-by: dlizewski <daniel.lizew...@gmail.com> diff --git a/src/rtos/rtos_nuttx_stackings.c b/src/rtos/rtos_nuttx_stackings.c index b70cccb33a..d3a8bab808 100644 --- a/src/rtos/rtos_nuttx_stackings.c +++ b/src/rtos/rtos_nuttx_stackings.c @@ -10,6 +10,30 @@ #include "rtos_standard_stackings.h" #include <target/riscv/riscv.h> +static int nuttx_cortex_m_stack_read(struct target *target, + int64_t stack_ptr, const struct rtos_register_stacking *stacking, + uint8_t *stack_data) +{ + int retval = target_read_buffer(target, stack_ptr, stacking->stack_registers_size, stack_data); + if (retval != ERROR_OK) + return retval; + + // Nuttx stack frames (produced in exception_common) store the SP of the ISR minus + // the hardware stack frame size. This SP may include an additional 4 byte alignment + // depending in xPSR[9]. The Nuttx stack frame stores post alignment since the + // hardware will add/remove automatically on both enter/exit. + // We need to adjust the SP to get the real SP of the stack. + // See Arm Reference manual "Stack alignment on exception entry" + + uint32_t xpsr = le_to_h_u32(&stack_data[0x44]); + if (xpsr & (1 << 9)) { + uint32_t sp = le_to_h_u32(&stack_data[0]); + h_u32_to_le(&stack_data[0], sp - 4 * stacking->stack_growth_direction); + } + + return ERROR_OK; +} + /* see arch/arm/include/armv7-m/irq_cmnvector.h */ static const struct stack_register_offset nuttx_stack_offsets_cortex_m[] = { { ARMV7M_R0, 0x28, 32 }, /* r0 */ @@ -36,8 +60,33 @@ const struct rtos_register_stacking nuttx_stacking_cortex_m = { .stack_growth_direction = -1, .num_output_registers = 17, .register_offsets = nuttx_stack_offsets_cortex_m, + .read_stack = nuttx_cortex_m_stack_read, }; +static int nuttx_cortex_m_fpu_stack_read(struct target *target, + int64_t stack_ptr, const struct rtos_register_stacking *stacking, + uint8_t *stack_data) +{ + int retval = target_read_buffer(target, stack_ptr, stacking->stack_registers_size, stack_data); + if (retval != ERROR_OK) + return retval; + + // Nuttx stack frames (produced in exception_common) store the SP of the ISR minus + // the hardware stack frame size. This SP may include an additional 4 byte alignment + // depending in xPSR[9]. The Nuttx stack frame stores post alignment since the + // hardware will add/remove automatically on both enter/exit. + // We need to adjust the SP to get the real SP of the stack. + // See Arm Reference manual "Stack alignment on exception entry" + + uint32_t xpsr = le_to_h_u32(&stack_data[0x88]); + if (xpsr & (1 << 9)) { + uint32_t sp = le_to_h_u32(&stack_data[0]); + h_u32_to_le(&stack_data[0], sp - 4 * stacking->stack_growth_direction); + } + + return ERROR_OK; +} + static const struct stack_register_offset nuttx_stack_offsets_cortex_m_fpu[] = { { ARMV7M_R0, 0x6c, 32 }, /* r0 */ { ARMV7M_R1, 0x70, 32 }, /* r1 */ @@ -63,6 +112,7 @@ const struct rtos_register_stacking nuttx_stacking_cortex_m_fpu = { .stack_growth_direction = -1, .num_output_registers = 17, .register_offsets = nuttx_stack_offsets_cortex_m_fpu, + .read_stack = nuttx_cortex_m_fpu_stack_read, }; static const struct stack_register_offset nuttx_stack_offsets_riscv[] = { --