From: Fredrik Hederstierna <fredrik.hederstierna@verisure.com>
To: "gdb-patches\\@sourceware.org" <gdb-patches@sourceware.org>
Cc: nd <nd@arm.com>,
James-Adam Renquinha Henri <arenquinha@cimeq.qc.ca>,
Alan Hayward <Alan.Hayward@arm.com>
Subject: [PATCH] Fix exception stack unwinding for ARM Cortex-M
Date: Sat, 29 Aug 2020 08:35:04 +0000 [thread overview]
Message-ID: <AM6PR10MB21507E7084C758828FC11B1BEF530@AM6PR10MB2150.EURPRD10.PROD.OUTLOOK.COM> (raw)
In-Reply-To: <790E863F-88F4-47D7-A70A-FA22779ACC2A@arm.com>
[-- Attachment #1: Type: text/plain, Size: 661 bytes --]
For Cortex-M targets using floating-point, eg the Cortex-M4F, its not possible to get any call-stack backtrace if setting a breakpoint in ISR.
The exception stack unwinder for Cortex-M does not consider if floating-point registers was stacked or not,
further the Cortex-M has two stack pointers: MSP (Main Stack Pointer) and PSP (Process Stack Pointer).
This is not handled when GDB tries to backtrace in the exception stack unwinder.
This patch fixes this, and gives a correct call-stack backtrace from breakpoints set in a handler or ISR.
Best Regards,
Fredrik Hederstierna
Senior Software Developer
Verisure Innovation Centre
Malmoe Sweden
[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: gdb-cortex-m-exception-unwind-fix.patch --]
[-- Type: text/x-patch; name="gdb-cortex-m-exception-unwind-fix.patch", Size: 5233 bytes --]
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 1ff47c3355..1d80e8cfc8 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,9 @@
+2020-08-29 Fredrik Hederstierna <fredrik.hederstierna@verisure.com>
+ Adam Renquinha <arenquinha@cimeq.qc.ca>
+
+ * arm-tdep.c (arm_m_exception_cache): Try use correct stack
+ pointer and stack frame offset when unwinding.
+
2020-08-29 Pedro Alves <pedro@palves.net>
* progspace.c (print_program_space): Use all_inferiors. Switch to
diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
index 074eedb480..ed7d4b1d37 100644
--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -2923,14 +2923,59 @@ arm_m_exception_cache (struct frame_info *this_frame)
struct gdbarch *gdbarch = get_frame_arch (this_frame);
enum bfd_endian byte_order = gdbarch_byte_order (gdbarch);
struct arm_prologue_cache *cache;
+ CORE_ADDR lr;
+ CORE_ADDR sp;
CORE_ADDR unwound_sp;
LONGEST xpsr;
+ uint32_t main_stack_used;
+ uint32_t extended_frame_used;
cache = FRAME_OBSTACK_ZALLOC (struct arm_prologue_cache);
cache->saved_regs = trad_frame_alloc_saved_regs (this_frame);
- unwound_sp = get_frame_register_unsigned (this_frame,
- ARM_SP_REGNUM);
+ /* ARMv7-M Architecture Reference "B1.5.6 Exception entry behavior"
+ describes which bits in LR that define which stack was used prior
+ to the exception and if FPU is used (causing extended stack frame). */
+
+ lr = get_frame_register_unsigned (this_frame, ARM_LR_REGNUM);
+ sp = get_frame_register_unsigned (this_frame, ARM_SP_REGNUM);
+
+ /* Check if main stack was used. */
+ main_stack_used = ((lr & 0xf) != 0xd);
+ if (main_stack_used)
+ {
+ /* Main stack used, use MSP as SP. */
+ unwound_sp = sp;
+ }
+ else
+ {
+ /* Thread (process) stack used.
+ Potentially this could be other register defined by target, but PSP
+ can be considered a standard name for the "Process Stack Pointer".
+ To be fully aware of system registers like MSP and PSP, these could
+ be added to a separate XML arm-m-system-profile that is valid for
+ ARMv6-M and ARMv7-M architectures. Also to be able to debug eg a
+ corefile off-line, then these registers must be defined by GDB,
+ and also be included in the corefile regsets. */
+
+ int psp_regnum = user_reg_map_name_to_regnum (gdbarch, "psp", -1);
+ if (psp_regnum == -1)
+ {
+ /* Thread (process) stack could not be fetched,
+ give warning and exit. */
+
+ warning (_("no PSP thread stack unwinding supported, exiting."));
+
+ /* Terminate any further stack unwinding by refer to self. */
+ cache->prev_sp = sp;
+ return cache;
+ }
+ else
+ {
+ /* Thread (process) stack used, use PSP as SP. */
+ unwound_sp = get_frame_register_unsigned (this_frame, psp_regnum);
+ }
+ }
/* The hardware saves eight 32-bit words, comprising xPSR,
ReturnAddress, LR (R14), R12, R3, R2, R1, R0. See details in
@@ -2940,15 +2985,47 @@ arm_m_exception_cache (struct frame_info *this_frame)
cache->saved_regs[1].addr = unwound_sp + 4;
cache->saved_regs[2].addr = unwound_sp + 8;
cache->saved_regs[3].addr = unwound_sp + 12;
- cache->saved_regs[12].addr = unwound_sp + 16;
- cache->saved_regs[14].addr = unwound_sp + 20;
- cache->saved_regs[15].addr = unwound_sp + 24;
+ cache->saved_regs[ARM_IP_REGNUM].addr = unwound_sp + 16;
+ cache->saved_regs[ARM_LR_REGNUM].addr = unwound_sp + 20;
+ cache->saved_regs[ARM_PC_REGNUM].addr = unwound_sp + 24;
cache->saved_regs[ARM_PS_REGNUM].addr = unwound_sp + 28;
+ /* Check if extended stack frame (FPU regs stored) was used. */
+ extended_frame_used = ((lr & (1 << 4)) == 0);
+ if (extended_frame_used)
+ {
+ int i;
+ int fpu_regs_stack_offset;
+
+ /* This code does not take into account the lazy stacking, see "Lazy
+ context save of FP state", in B1.5.7, also ARM AN298, supported
+ by Cortex-M4F architecture. Give a warning and try do best effort.
+ To fully handle this the FPCCR register (Floating-point Context
+ Control Register) needs to be read out and the bits ASPEN and LSPEN
+ could be checked to setup correct lazy stacked FP registers. */
+
+ warning (_("no FPU lazy stack unwinding supported, check FPCCR."));
+
+ fpu_regs_stack_offset = unwound_sp + 0x20;
+ for (i = 0; i < 16; i++)
+ {
+ cache->saved_regs[ARM_D0_REGNUM + i].addr = fpu_regs_stack_offset;
+ fpu_regs_stack_offset += 4;
+ }
+ cache->saved_regs[ARM_FPSCR_REGNUM].addr = unwound_sp + 0x60;
+
+ /* Offset 0x64 is reserved. */
+ cache->prev_sp = unwound_sp + 0x68;
+ }
+ else
+ {
+ /* Basic frame type used. */
+ cache->prev_sp = unwound_sp + 32;
+ }
+
/* If bit 9 of the saved xPSR is set, then there is a four-byte
aligner between the top of the 32-byte stack frame and the
previous context's stack pointer. */
- cache->prev_sp = unwound_sp + 32;
if (safe_read_memory_integer (unwound_sp + 28, 4, byte_order, &xpsr)
&& (xpsr & (1 << 9)) != 0)
cache->prev_sp += 4;
next prev parent reply other threads:[~2020-08-29 8:35 UTC|newest]
Thread overview: 10+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <AM4PR1001MB0948AC4D9CB635F5A9A2FC82EFDC0@AM4PR1001MB0948.EURPRD10.PROD.OUTLOOK.COM>
[not found] ` <HE1PR1001MB130613C0995C4C21A630373BEF1B0@HE1PR1001MB1306.EURPRD10.PROD.OUTLOOK.COM>
2019-06-10 21:25 ` [PATCH] Fix exception " James-Adam Renquinha Henri
2019-06-12 9:01 ` Alan Hayward
2020-08-29 8:35 ` Fredrik Hederstierna [this message]
2020-09-02 13:24 ` [PATCH] Fix exception stack " Alan Hayward
2020-09-06 9:27 ` Fredrik Hederstierna
2020-09-09 8:12 ` Alan Hayward
2020-09-10 21:00 ` Fredrik Hederstierna
2020-09-14 14:44 ` Alan Hayward
2020-09-14 18:31 ` Joel Brobecker
2020-09-15 14:05 ` Alan Hayward
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=AM6PR10MB21507E7084C758828FC11B1BEF530@AM6PR10MB2150.EURPRD10.PROD.OUTLOOK.COM \
--to=fredrik.hederstierna@verisure.com \
--cc=Alan.Hayward@arm.com \
--cc=arenquinha@cimeq.qc.ca \
--cc=gdb-patches@sourceware.org \
--cc=nd@arm.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