Gdb 如何从软件中断异常获取调用堆栈
我正在尝试使用Gdb 如何从软件中断异常获取调用堆栈,gdb,arm,bare-metal,Gdb,Arm,Bare Metal,我正在尝试使用gdb调试一个在裸机ARM平台上运行的程序。在某一点上,会生成SWI(软件中断)异常。但是,正如您所看到的,回溯跟踪没有显示异常的产生原因: (gdb)c 在ARM上运行的程序是用armnonelinuxgnueabigcc-O2-c-ggdb编译的,我还尝试使用-O0获得相同的结果 如何获得有意义的调用堆栈?是否有其他方法可以找到生成此异常的原因?要理解gdb在生成堆栈跟踪时遇到的问题,首先必须了解gdb如何生成堆栈跟踪。编译器在创建C函数时使用标准的序言和尾声,这是函数入口和出
gdb
调试一个在裸机ARM平台上运行的程序。在某一点上,会生成SWI
(软件中断)异常。但是,正如您所看到的,回溯跟踪没有显示异常的产生原因:
(gdb)c
在ARM上运行的程序是用armnonelinuxgnueabigcc-O2-c-ggdb
编译的,我还尝试使用-O0
获得相同的结果
如何获得有意义的调用堆栈?是否有其他方法可以找到生成此异常的原因?要理解
gdb
在生成堆栈跟踪时遇到的问题,首先必须了解gdb
如何生成堆栈跟踪。编译器在创建C
函数时使用标准的序言和尾声,这是函数入口和出口处的汇编代码。其中一部分是在堆栈上保存lr
,为局部变量保留空间,并链接上一帧指针或fp
。这些堆栈帧提供一种链表类型,该链表以fp
为根,通常以零结尾。这取决于ABI(请参阅)。每种手臂类型的细节略有不同,但概念相似
因此,当SWI
(或发生任何异常)时,它会完全中断C
编译代码的流,并且帧指针列表可能很难解码,尤其是在堆栈损坏的情况下。而且,gdb
不会解码程序的上下文。某些系统可能会更改帧指针,并立即从异常模式
切换到系统/监控模式
。异常的sp
甚至可以用作暂存寄存器。当输入SWI
时,处理程序的部分工作将是保存用户
寄存器(r0-r12
)。在多任务O/S的情况下,这可能导致用户
堆栈从一个任务完全更改为另一个任务
通过在异常模式下检查lr
,始终可以确定故障/原因指令。这在中指定,并且对于任何ARMCPU都是相同的0xfff0008
是默认的SWI
处理程序地址(使用高内存向量表时)。以下是ARM(建筑技术参考手册)中SWI
的例外情况:
A2.6.4软件中断异常 软件中断指令(SWI)进入监控模式以请求特定的监控(操作系统)功能。执行SWI时,将执行以下操作: 要在执行SWI操作后返回,请使用以下指令恢复PC(从R14_svc)和CPSR(从SPSR_svc)并返回到SWI后的指令:
如您所见,
R14_svc
是在监控模式下的lr
,被设置为SWI
指令+4。这样,正常返回将重新启动以下指令。通过检查lr
的位置,可以确定SWI
发生的位置。如果用户堆栈未损坏,则可以使用编译器通过fp
使用的ABI将主管
堆栈链接到用户
堆栈。如果这样做,那么gdb
可以给出堆栈跟踪。但是,在讨论的系统中,没有SWI
支持代码
在这种情况下,您还可以编写
gdb
宏来提供堆栈跟踪。但是,我希望很明显,一般来说,gdb
将有一个困难的任务。要理解gdb
与生成堆栈跟踪有关的问题,首先必须理解gdb
如何生成堆栈跟踪。编译器在创建C
函数时使用标准的序言和尾声,这是函数入口和出口处的汇编代码。其中一部分是在堆栈上保存lr
,为局部变量保留空间,并链接上一帧指针或fp
。这些堆栈帧提供一种链表类型,该链表以fp
为根,通常以零结尾。这取决于ABI(请参阅)。每种手臂类型的细节略有不同,但概念相似
因此,当SWI
(或发生任何异常)时,它会完全中断C
编译代码的流,并且帧指针列表可能很难解码,尤其是在堆栈损坏的情况下。而且,gdb
不会解码程序的上下文。某些系统可能会更改帧指针,并立即从异常模式
切换到系统/监控模式
。异常的sp
甚至可以用作暂存寄存器。当输入SWI
时,处理程序的部分工作将是保存用户
寄存器(r0-r12
)。在多任务O/S的情况下,这可能导致用户
堆栈从一个任务完全更改为另一个任务
通过在异常模式下检查lr
,始终可以确定故障/原因指令。这在中指定,并且对于任何ARMCPU都是相同的0xfff0008
是默认的SWI
处理程序地址(使用高内存向量表时)。以下是ARM(建筑技术参考手册)中SWI
的例外情况:
A2.6.4软件中断异常 软件中断指令(SWI)进入监控模式以请求特定的监控程序(操作系统)
Continuing.
^C
Program received signal SIGTRAP, Trace/breakpoint trap. 0xffff0008 in ?? ()
(gdb) bt
#0 0xffff0008 in ?? ()
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
MOVS PC,R14