• R/O
  • HTTP
  • SSH
  • HTTPS

Commit

Tags
Aucun tag

Frequently used words (click to add to your profile)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

Commit MetaInfo

Révision8b73ee207c9c4b2d692a82a29d1cee2dcfa07394 (tree)
l'heure2022-10-26 20:59:13
AuteurLuis Machado <luis.machado@arm....>
CommiterLuis Machado

Message de Log

gdb/arm: Terminate frame unwinding in M-profile lockup

In the lockup state the PC value of the the outer frame is irreversibly
lost. The other registers are intact so LR likely contains
PC of some frame next to the outer one, but we cannot analyze
the nearest outer frame without knowing its PC
therefore we do not know SP fixup for this frame.

The frame unwinder possibly gets mad due to the wrong SP value.
To prevent problems terminate unwinding if PC contains the magic
value of the lockup state.

Example session wihtout this change,
Cortex-M33 CPU in lockup, gdb 13.0.50.20221016-git:


(gdb) c
Continuing.
Program received signal SIGINT, Interrupt.
0xeffffffe in ?? ()
(gdb) bt
#0 0xeffffffe in ?? ()
#1 0x0c000a9c in HardFault_Handler ()
at C:/dvl/stm32l5trustzone/GPIO_IOToggle_TrustZone/Secure/Src/stm32l5xx_it.c:99
#2 0x2002ffd8 in ?? ()
Backtrace stopped: previous frame identical to this frame (corrupt stack?)
(gdb)

The frame #1 is at correct PC taken from LR, #2 is a total nonsense.

With the change:


(gdb) c
Continuing.
Program received signal SIGINT, Interrupt.
warning: ARM M in lockup state, stack unwinding terminated.
<signal handler called>
(gdb) bt
#0 <signal handler called>
(gdb)

There is a visible drawback of emitting a warning in a cache buildnig routine
as introduced in Torbjörn SVENSSON's
[PATCH v4] gdb/arm: Stop unwinding on error, but do not assert
The warning is printed just once and not repeated on each backtrace command.

Signed-off-by: Tomas Vanek <vanekt@fbl.cz>

Change Summary

Modification

--- a/gdb/arm-tdep.c
+++ b/gdb/arm-tdep.c
@@ -724,9 +724,30 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
724724 return 0;
725725 }
726726
727+static inline bool
728+arm_m_addr_is_lockup (CORE_ADDR addr)
729+{
730+ switch (addr)
731+ {
732+ /* Values for lockup state.
733+ For more details see "B1.5.15 Unrecoverable exception cases" in
734+ both ARMv6-M and ARMv7-M Architecture Reference Manuals, or
735+ see "B4.32 Lockup" in ARMv8-M Architecture Reference Manual. */
736+ case 0xeffffffe:
737+ case 0xfffffffe:
738+ case 0xffffffff:
739+ return true;
740+
741+ default:
742+ /* Address is not lockup. */
743+ return false;
744+ }
745+}
746+
727747 /* Determine if the address specified equals any of these magic return
728748 values, called EXC_RETURN, defined by the ARM v6-M, v7-M and v8-M
729- architectures.
749+ architectures. Also include lockup magic PC value.
750+ Check also for FNC_RETURN if we have the v8-M security extension.
730751
731752 From ARMv6-M Reference Manual B1.5.8
732753 Table B1-5 Exception return behavior
@@ -769,6 +790,9 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
769790 static int
770791 arm_m_addr_is_magic (struct gdbarch *gdbarch, CORE_ADDR addr)
771792 {
793+ if (arm_m_addr_is_lockup (addr))
794+ return 1;
795+
772796 arm_gdbarch_tdep *tdep = gdbarch_tdep<arm_gdbarch_tdep> (gdbarch);
773797 if (tdep->have_sec_ext)
774798 {
@@ -3355,6 +3379,31 @@ arm_m_exception_cache (frame_info_ptr this_frame)
33553379 describes which bits in LR that define which stack was used prior
33563380 to the exception and if FPU is used (causing extended stack frame). */
33573381
3382+ /* In the lockup state PC contains a lockup magic value.
3383+ The PC value of the the next outer frame is irreversibly
3384+ lost. The other registers are intact so LR likely contains
3385+ PC of some frame next to the outer one, but we cannot analyze
3386+ the next outer frame without knowing its PC
3387+ therefore we do not know SP fixup for this frame.
3388+ Some heuristics to resynchronize SP might be possible.
3389+ For simplicity, just terminate the unwinding to prevent it going
3390+ astray and attempting to read data/addresses it shouldn't,
3391+ which may cause further issues due to side-effects. */
3392+ CORE_ADDR pc = get_frame_pc (this_frame);
3393+ if (arm_m_addr_is_lockup (pc))
3394+ {
3395+ /* The lockup can be real just in the innermost frame
3396+ as the CPU is stopped and cannot create more frames.
3397+ If we hit lockup magic PC in the other frame, it is
3398+ just a sentinel at the top of stack: do not warn then. */
3399+ if (frame_relative_level (this_frame) == 0)
3400+ warning (_("ARM M in lockup state, stack unwinding terminated."));
3401+
3402+ /* Terminate any further stack unwinding. */
3403+ arm_cache_set_active_sp_value (cache, tdep, 0);
3404+ return cache;
3405+ }
3406+
33583407 CORE_ADDR lr = get_frame_register_unsigned (this_frame, ARM_LR_REGNUM);
33593408
33603409 /* ARMv7-M Architecture Reference "A2.3.1 Arm core registers"
@@ -3824,11 +3873,12 @@ arm_m_exception_unwind_sniffer (const struct frame_unwind *self,
38243873 return arm_m_addr_is_magic (gdbarch, this_pc);
38253874 }
38263875
3827-/* Frame unwinder for M-profile exceptions. */
3876+/* Frame unwinder for M-profile exceptions (EXC_RETURN on stack),
3877+ lockup and secure/nonsecure interstate function calls (FNC_RETURN). */
38283878
38293879 struct frame_unwind arm_m_exception_unwind =
38303880 {
3831- "arm m exception",
3881+ "arm m exception lockup sec_fnc",
38323882 SIGTRAMP_FRAME,
38333883 arm_m_exception_frame_unwind_stop_reason,
38343884 arm_m_exception_this_id,