如何在ARM上生成可用的调用栈?

huangapple go评论66阅读模式
英文:

How to produce usable callstack on ARM?

问题

在ARM上开发C++应用程序(树莓派,g++(Raspbian 8.3.0-6+rpi1)8.3.0)。当我尝试调试我的代码或应用程序在我的代码中崩溃时,我可以正确获取调用堆栈,没有任何问题。但是,当应用程序在外部库中崩溃或我在GDB中进入外部库时,调用堆栈会丢失,除了函数调用之外,它不包含任何有用的信息。

例如,当我在memcpy函数的开头中断时,我会得到以下结果:

(gdb) bt
#0  0x76fa4b5c in memcpy () at /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so
#1  0x000e6118 in CWatchDog::ComputeBatteryPercentage(float) (this=0x2643140, voltage=3.96600008) at WatchDog.cpp:197
#2  0x000e5c24 in CWatchDog::BatteryControl(CWatchDog::RxPacketData const&) (this=0x2643140, data=...) at WatchDog.cpp:149
...等等...

但是当我走了几行之后,在“vpush”指令之后,我只得到以下结果:

(gdb) bt
#0  0x76fa4b60 in memcpy () at /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so
#1  0x00000000 in  ()

是否有可能启用外部函数中的完整调用堆栈?我尝试使用-funwind-tables -fasynchronous-unwind-tables -mapcs-frame选项构建我的代码,但没有任何区别。

英文:

I develop C++ application on ARM (Raspberry Pi, g++ (Raspbian 8.3.0-6+rpi1) 8.3.0
). When I try to debug my code or the application crashes in my code, I get the correct callstack without any problem. But when the application crashes in external library or I step into external library in GDB, the callstack is lost and it does not contain anything useful except the function call.

For example, when I break at the beginning of memcpy function, I get the following:

(gdb) bt
#0  0x76fa4b5c in memcpy () at /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so
#1  0x000e6118 in CWatchDog::ComputeBatteryPercentage(float) (this=0x2643140, voltage=3.96600008) at WatchDog.cpp:197
#2  0x000e5c24 in CWatchDog::BatteryControl(CWatchDog::RxPacketData const&) (this=0x2643140, data=...) at WatchDog.cpp:149
... etc ...

but when I step a few lines, after the instruction "vpush", I get only the following:

(gdb) bt    
#0  0x76fa4b60 in memcpy () at /usr/lib/arm-linux-gnueabihf/libarmmem-v7l.so
#1  0x00000000 in  ()

Is there any posibility how to enable full call stacks in external functions?
I tried building my code with -funwind-tables -fasynchronous-unwind-tables -mapcs-frame but it makes no difference.

答案1

得分: 1

以下是已翻译的内容:

在许多体系结构上,必须具备完整的调试信息或者帧指针才能使回溯工作正常。有时,ABI(应用程序二进制接口)要求使用帧指针(除了堆栈指针之外),有时则不需要。在寄存器相对较少的体系结构上,优化掉帧指针以便将寄存器用于其他用途非常有用。通常,您可以在自己的二进制文件中使用-fno-omit-frame-pointer来阻止它执行此操作,但这对于预构建的二进制文件无法帮助。(在某些体系结构上,必须具备帧指针;仅具备调试信息是不够的。)

许多Linux发行版提供了与其库包一起安装的附加调试包。通常,这些包不会默认安装,以节省磁盘空间和减小下载大小。GDB会寻找调试信息文件,并在找到时使用它们,但如果找不到它们,它不会报错。

这里是我找到的关于Raspbian调试包的一些信息。我不知道这是否正好是您所需的,但它表明它们是存在的。

英文:

It is common on many architectures that you must have either full debug info or a frame pointer for backtracing to work. Sometimes the ABI mandates the use of a frame pointer (in addition to a stack pointer), sometimes not. On architectures with relatively few registers it is useful to optimize away the frame pointer so the register can be used for other things. You can typically prevent it doing this in your own binaries using -fno-omit-frame-pointer, but that doesn't help you with prebuilt binaries. (On some architectures you must have frame pointers; debug info alone is not enough.)

Many Linux distributions provide additional debug packages to install alongside their library packages. These are often not installed by default in order to save disk space and reduce download sizes. GDB will look for the debug info files and use them if it can find them, but will not complain if it cannot.

Here is some information I found about Raspbian debug packages. I don't know if that's specifically what you need, but it shows they exist.

huangapple
  • 本文由 发表于 2023年6月5日 17:47:37
  • 转载请务必保留本文链接:https://go.coder-hub.com/76405204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定