2

I'm trying to debug a program running on a bare-metal ARM platform using gdb. At some point an SWI (Software Interrupt) exception is generated. However the back-trace doesn't show what generated the exception as you can see:

(gdb) c

Continuing. 
^C 
Program received signal SIGTRAP, Trace/breakpoint trap. 0xffff0008 in ?? ()
(gdb) bt
#0  0xffff0008 in ?? ()

The program running on the ARM was compiled with arm-none-linux-gnueabi-gcc -O2 -c -ggdb, I also tried using -O0 with the same result.

How can I get a meaningful call stack? Is there another way to find what is generating this exception?

4

1 回答 1

4

要了解gdb生成堆栈跟踪的问题,您首先必须了解如何gdb生成堆栈跟踪。编译器在创建函数时使用标准的序言结尾,这是函数入口和出口处的汇编代码。其中一部分是将 保存在堆栈上,为局部变量保留空间链接前一帧指针或. 这些堆栈帧提供了一种以 the为根并通常以终止的链表。这取决于ABI(参见-mabiClrfpfp)。每种 ARM ABI类型的细节略有不同,但概念相似。

因此,当SWI(或任何异常发生)时,它会完全中断已C编译代码的流程,并且帧指针列表可能难以解码,尤其是在堆栈损坏的情况下。此外,gdb不解码程序的上下文。某些系统可能会更改帧指针并立即从 a 切换exception modesystem/supervisor mode。该sp异常甚至可以用作暂存寄存器。输入 后,处理程序的SWI部分工作将是保存user寄存器 ( r0-r12)。在多任务 O/S的情况下,这可能会导致user堆栈从一个任务到另一个任务的完全变化。

您始终可以通过检查异常模式来确定故障/导致指令。lr这在ARM Architechure中指定,并且对于任何ARM CPU 都是相同的。0xfff0008是默认SWI处理程序地址(使用高内存向量表时)。ARM ARM(架构参考手册)SWI中的除外,


A2.6.4 软件中断异常

软件中断指令 (SWI) 进入超级用户模式以请求特定的超级用户(操作系统)功能。执行 SWI 时,将执行以下操作:

   R14_svc    = address of next instruction after the SWI instruction
   SPSR_svc   = CPSR
   CPSR[4:0]  = 0b10011                 /* Enter Supervisor mode */
   CPSR[5]    = 0                       /* Execute in ARM state */
                                        /* CPSR[6] is unchanged */
   CPSR[7]    = 1                       /* Disable normal interrupts */
                                        /* CPSR[8] is unchanged */
   CPSR[9]    = CP15_reg1_EEbit         /* Endianness on exception entry */
   if high vectors configured then
       PC     = 0xFFFF0008
   else
       PC     = 0x00000008

要在执行 SWI 操作后返回,请使用以下指令恢复 PC(来自 R14_svc)和 CPSR(来自 SPSR_svc)并返回到 SWI 之后的指令:

       MOVS PC,R14

如您所见,R14_svclr处于主管模式时,设置为SWI指令+4。这样正常返回会重新启动下面的指令。通过检查在哪里lr,您可以确定在哪里SWI发生。supervisor如果用户堆栈没有损坏,您可以使用编译器正在使用userABI通过fp. 如果这样做,则gdb可以提供堆栈跟踪。但是,在讨论的系统中,没有SWI支持代码。

在这种情况下,您还可以编写gdb宏来提供堆栈跟踪。但是,我希望很明显,一般而言,这gdb将是一项艰巨的任务。

于 2013-03-02T18:14:55.533 回答