c++ - 如何使用backward-cpp在ARM上获取堆栈跟踪
问题描述
在使用向后 cpp库在 ARM 机器上引发异常后,我正在尝试恢复我的程序堆栈跟踪。在 AMD64 机器上运行简单程序时,以下代码返回预期的堆栈跟踪:
#include <backward/backward.hpp>
backward::SignalHandling sh{};
int main() {
throw 1;
}
terminate called after throwing an instance of 'int'
Stack trace (most recent call last):
#9 Object "", at 0xffffffffffffffff, in
#8 Object "/home/uy/Sandbox/SimpleC++/cmake-build-debug---native/main", at 0x556929e5308d, in
#7 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7fb8a1e8c0b2, in __libc_start_main
#6 Source "/home/uy/Sandbox/SimpleC++/main.cpp", line 7, in int main() [0x556929e53174]
4: backward::SignalHandling sh{};
5:
6: int main() {
> 7: throw 1;
8: }
#5 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7fb8a211c798, in __cxa_throw
#4 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7fb8a211c4e6, in std::terminate()
#3 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7fb8a211c47b, in
#2 Object "/lib/x86_64-linux-gnu/libstdc++.so.6", at 0x7fb8a2110950, in
#1 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7fb8a1e8a858, in abort
#0 Object "/lib/x86_64-linux-gnu/libc.so.6", at 0x7fb8a1eab18b, in gsignal
Aborted (Signal sent by tkill() 32939 1000)
但是,当在 ARM 机器上运行相同的代码时,程序给出的堆栈跟踪并不是特别有用:
terminate called after throwing an instance of 'int'
Stack trace (most recent call last):
#7 Object "/lib/arm-linux-gnueabihf/libc.so.6", at 0xb6d08e9f, in gsignal
#6 Object "/lib/arm-linux-gnueabihf/libc.so.6", at 0xb6cf9c65, in gnu_get_libc_version
#5 Object "/lib/arm-linux-gnueabihf/libc.so.6", at 0xb6d09cbf, in __default_sa_restorer
#4 Source "/home/uy/Sandbox/SimpleC++/backward-cpp/include/backward/backward.hpp", line 3972, in backward::SignalHandling::sig_handler(int signo, siginfo_t *info, void *_ctx) [0x7f5a2429]
#3 Source "/home/uy/Sandbox/SimpleC++/backward-cpp/include/backward/backward.hpp", line 3947, in backward::SignalHandling::handleSignal(int, siginfo_t *info, void *_ctx) [0x7f5a2371]
#2 Source "/home/uy/Sandbox/SimpleC++/backward-cpp/include/backward/backward.hpp", line 823, in size_t backward::StackTraceImpl<backward::system_tag::linux_tag>::load_from(void *addr, size_t depth) [0x7f59d44f]
#1 Source "/home/uy/Sandbox/SimpleC++/backward-cpp/include/backward/backward.hpp", line 817, in size_t backward::StackTraceImpl<backward::system_tag::linux_tag>::load_here(size_t depth) [0x7f59d3d3]
#0 Source "/home/uy/Sandbox/SimpleC++/backward-cpp/include/backward/backward.hpp", line 802, in size_t backward::details::unwind<backward::StackTraceImpl<backward::system_tag::linux_tag>::callback>(callback f, size_t depth) [0x7f5a2df3]
Aborted (Signal sent by tkill() 8424 1000)
Aborted
如何获得类似于我在 AMD64 机器上获得的堆栈跟踪?
解决方案
这是可行的,但需要访问 libgcc 如何实现 _Unwind_Backtrace 函数的内部细节。幸运的是,代码是开源的,但依赖于这些内部细节是脆弱的,因为它可能会在将来的 armgcc 版本中中断,而不会发出任何通知。
通常,读取执行回溯的 libgcc 的源代码,它会创建 CPU 内核寄存器的内存虚拟表示,然后使用此表示向上遍历堆栈,模拟异常抛出。_Unwind_Backtrace 所做的第一件事是从当前 CPU 寄存器中填充此上下文,然后调用内部实现函数。
在大多数情况下,从堆栈异常结构手动创建该上下文足以伪造从处理程序模式向上通过调用堆栈的回溯。这是一些示例代码(来自https://github.com/bakerstu/openmrn/blob/62683863e8621cef35e94c9dcfe5abcaf996d7a2/src/freertos_drivers/common/cpu_profile.hxx#L162):
推荐阅读
- r - R中的自定义重采样方法
- asp.net - Asp.net 超链接控件 NavigateURL 属性在 mywebsite 中不起作用
- algorithm - 如何使用合并排序为Scala中的Int列表计算反转计数?
- json - Unity - 从android读取JSON文件
- intellij-idea - Intellij idea - 在结构视图上显示参数名称
- visual-c++ - 在 Visual Studio C++ 上加载大量网格滞后
- spring - 如何使用 Spring Data 进行分页?
- c# - 如何将两个文本框值相乘并在 C# 中显示第三个的答案?
- azure - 错误 ID:VertexFailedFast,错误消息:Vertex 因快速失败错误而失败
- javascript - 我想通过选择类来获取数据并使用 jquery 在控制台中打印它