Re: Re: [PATCH] Fix exception unwinding for ARM Cortex-M

James-Adam Renquinha Henri
2016-08-03T17:33:31Z

Hi, I'm back from the dead.

Seriously though, I was a bit too busy at work to pursue on this and I
didn't have a clear idea of where to start after the comments. Moreover,
as the patch did "just work" at my workplace, it was a bit difficult to
justify spending a lot more time digging information about target
descriptions, how to determine what features are present on target, etc.

So thanks to push toward the progress of this issue, apparently with
your mail subject you successfully brought people that gives more
specific guidance to get this done.

Indeed, the patch looks really close to what I've done, to the point
that I can see that, aside from a small refactoring, the changes between
our patches are mainly variable name changes and added comments. You
really wrote your patch from scratch? You've got rid of the various
calls to `user_reg_map_name_to_regnum', though, which is nice.

> 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.
> Meaning for eg. Cortex-M4F its not possible to get any call-stack
backtrace if setting a breakpoint in ISR, and floating-point variable
was used.

Actually, the info here is inaccurate: FPU context stacking and the
MSP/PSP switch are two unrelated concepts. Meaning, you can fix the code
to deal with the PSP, but it still won't handle FPU register unstacking.

> This patch was inspired by the great work done by James-Adam
Renquinha Henri, submitted April this year.
Thanks :)

> The next thing would then be to also add FPU context control reg
FPCCR, which is needed for retrieving info on the FPU lazy stacking.
> Though its complicated I think and I will try to investigate an
'arm-m-fpu.xml' profile further, if this is solution perhaps.

It indeed is just a bit more complicated. Let me summarize what needs to
be done. Have the ARMv7-M Architecture Reference Manual handy, see B1.5.7.

- Check if lazy stacking is enabled (FPCCR.LSPEN == 1). If it's not, the
case is uncomplicated, registers are stacked as usual
- If lazy stacking is active (FPCCR.LSACT == 1), the extended stack has
space reserved for the FPU registers (S0-S15, FPSCR), but there are not
stacked, they are still in FPU registers unmodified.

So that adds more random fetches from "memory" of the target, because
these are memory-mapped.

ARM gives some example scenarios with chronograms of some important bits
with stacking information [1].

> ChangeLog entry should cover what do you change on the function level.
> Please read https://sourceware.org/gdb/wiki/ContributionChecklist

If only I knew that checklist! I searched for something like this, but
maybe it didn't use the correct search terms, I didn't find it.

[1]
http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.dai0298a/DAFGGBJD.html

James-Adam Renquinha Henri, Ing. jr
IngÃ©nieur d'application
CIMEQ INC.

Le 2016-08-03 Ã  06:56, Fredrik Hederstierna a Ã©crit :
> Hi Yao,
>
> thanks for reviewing, I attach here updated patch.
>
> I have FSF assignment papers for GCC from December 2005, maybe needs separate assignment for GDB,
> so I have now sent in application to FSF for GDB assignment as well.
>
> gdb/ChangeLog:
>
> 2016-08-03 Fredrik Hederstierna <fredrik.hederstierna@verisure.com>
>
> * arm-tdep.c (arm_m_addr_is_magic): New function.
> (arm_addr_bits_remove)
> (arm_m_exception_unwind_sniffer): Check correct EXC_RETURN values.
>
> diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c
> index d2661cb..1d154cc 100644
> --- a/gdb/arm-tdep.c
> +++ b/gdb/arm-tdep.c
> @@ -464,6 +464,61 @@ arm_pc_is_thumb (struct gdbarch *gdbarch, CORE_ADDR memaddr)
> return 0;
> }
>
> +/* Determine if the address specified equals any of
> + these magic return values, called EXC_RETURN, defined
> + by the ARM v6-M and v7-M architectures.
> +
> + From ARMv6-M Reference Manual B1.5.8
> + Table B1-5 Exception return behavior
> +
> + EXC_RETURN Return To Return Stack
> + 0xFFFFFFF1 Handler mode Main
> + 0xFFFFFFF9 Thread mode Main
> + 0xFFFFFFFD Thread mode Process
> +
> + From ARMv7-M Reference Manual B1.5.8
> + Table B1-8 EXC_RETURN definition of exception return behavior, no FP
> +
> + EXC_RETURN Return To Return Stack
> + 0xFFFFFFF1 Handler mode Main
> + 0xFFFFFFF9 Thread mode Main
> + 0xFFFFFFFD Thread mode Process
> +
> + Table B1-9 EXC_RETURN definition of exception return behavior, with FP
> +
> + EXC_RETURN Return To Return Stack Frame Type
> + 0xFFFFFFE1 Handler mode Main Extended
> + 0xFFFFFFE9 Thread mode Main Extended
> + 0xFFFFFFED Thread mode Process Extended
> + 0xFFFFFFF1 Handler mode Main Basic
> + 0xFFFFFFF9 Thread mode Main Basic
> + 0xFFFFFFFD Thread mode Process Basic
> +
> + For more details see "B1.5.8 Exception return behavior"
> + in both ARMv6-M and ARMv7-M Architecture Reference Manuals. */
> +
> +static int
> +arm_m_addr_is_magic (CORE_ADDR addr)
> +{
> + switch (addr)
> + {
> + /* Values from Tables in B1.5.8 the EXC_RETURN definitions of
> + the exception return behavior. */
> + case 0xffffffe1:
> + case 0xffffffe9:
> + case 0xffffffed:
> + case 0xfffffff1:
> + case 0xfffffff9:
> + case 0xfffffffd:
> + /* Address is magic. */
> + return 1;
> +
> + default:
> + /* Address is not magic. */
> + return 0;
> + }
> +}
> +
> /* Remove useless bits from addresses in a running program. */
> static CORE_ADDR
> arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
> @@ -471,7 +526,7 @@ arm_addr_bits_remove (struct gdbarch *gdbarch, CORE_ADDR val)
> /* On M-profile devices, do not strip the low bit from EXC_RETURN
> (the magic exception return address). */
> if (gdbarch_tdep (gdbarch)->is_m
> - && (val & 0xfffffff0) =0xfffffff0)
> + && arm_m_addr_is_magic (val))
> return val;
>
> if (arm_apcs_32)
> @@ -2990,14 +3045,8 @@ arm_m_exception_unwind_sniffer (const struct frame_unwind *self,
> /* No need to check is_m; this sniffer is only registered for
> M-profile architectures. */
>
> - /* Exception frames return to one of these magic PCs. Other values
> - are not defined as of v7-M. See details in "B1.5.8 Exception
> - return behavior" in "ARMv7-M Architecture Reference Manual". */
> - if (this_pc =0xfffffff1 || this_pc == 0xfffffff9
> - || this_pc =0xfffffffd)
> - return 1;
> -
> - return 0;
> + /* Check if exception frame returns to a magic PC value. */
> + return arm_m_addr_is_magic (this_pc);
> }
>
> /* Frame unwinder for M-profile exceptions. */
> --
>