堆栈跟踪在获取我的代码之前停止(在使用NDK的Android上)

stack traces stop before getting to my code (on Android using NDK)

本文关键字:NDK Android 我的 获取 跟踪 代码 堆栈      更新时间:2023-10-16

我正在使用NDK r5b在Android 2.3.x上进行开发。偶尔我的代码会崩溃,我想知道在哪里。当我有一个指针(即来自Android的堆栈跟踪)时,我已经知道如何在我的应用程序中获得相应的行

然而,我经常看到这样无用的堆栈跟踪(完整堆栈跟踪):

     #00  pc 0006561a  /system/lib/egl/libGLESv2_adreno200.so
     #01  pc 0006b900  /system/lib/egl/libGLESv2_adreno200.so
     #02  pc 0005aac8  /system/lib/egl/libGLESv2_adreno200.so
     #03  pc 0001687a  /system/lib/egl/libGLESv1_CM_adreno200.so
     #04  pc 000096ce  /system/lib/egl/libGLESv1_CM_adreno200.so

或者这个:

(gdb) bt
#0  0xafd0c51c in epoll_wait () from /Volumes/SecureCode/webos/rta/android/obj/local/armeabi/libc.so
#1  0xa81216a6 in ?? ()

甚至根本没有提到我的代码。

有什么方法可以得到比这更好的堆栈跟踪吗?为什么有些库函数是"不透明的",因为它们不允许回溯"穿透"调用函数,从而导致堆栈跟踪停止?

据我所知,调试这样一个问题的唯一方法是在程序的每一点使用日志记录和/或使用gdb遍历每一行。

这些Android库的调试版本而不是运行时版本是否有ROM可用,这会有帮助吗?(我只使用一部手机进行开发,所以我不关心保持完整的功能。)(实际上,我注意到上面的gdb堆栈跟踪中的libc.so路径在我的应用程序目录中。我可以用另一个(调试)libc.so打包它吗?这有帮助吗?)

最后一件可能有帮助的事情是:在上面的logcat堆栈跟踪(第一个)中,我的库在原始堆栈转储中提到:

stack:
  ...
  ...
  4471cb88  00000028  
  4471cb8c  afd4649c  
  4471cb90  80b4eb71  /data/data/com.audia.dev.rta/lib/librta.so
  4471cb94  00299180  
  ...
  ...

但那不是函数指针。这会是什么,在应用程序崩溃后会有什么帮助吗?我猜可能不是,如果它是一个堆指针或类似的东西。

有什么方法可以得到比这更好的堆栈跟踪吗?

据我所知,你必须自己构建和编写Android镜像。它使您能够拥有Android的完整符号(可执行文件和共享库),但专有共享库除外。

  • 从源代码构建-从源代码编译CyanogenMod

此外,它还提供了使用gdb的符号。

$ adb shell setprop debug.db.uid 32767
$ adb forward tcp:5039 tcp:5039
/*
 program terminated and debuggerd caught exception like the following.
 Use the PID number for gdbclient 3rd parameter.
 I/DEBUG   ( 2154): ******************************************************** 
 I/DEBUG   ( 2154): * Process 2508 has been suspended while crashing.  To
 I/DEBUG   ( 2154): * attach gdbserver for a gdb connection on port 5039:
 I/DEBUG   ( 2154): *
 I/DEBUG   ( 2154): *     adb shell gdbserver :5039 --attach 2508 &
 I/DEBUG   ( 2154): *
 I/DEBUG   ( 2154): * Press HOME key to let the process continue crashing.
 I/DEBUG   ( 2154): ********************************************************)
*/
$ gdbclient "" "" 2508

编辑:

您仍然可以使用ndk-gdb而不是gdbclient命令。请指定共享库的符号文件。

(gdb) set solib-search-path (ANDROID_SOURCE_PATH)/out/target/product/(PRODUCT_NAME)/symbols/system/lib

编辑2:

如果你不需要Android系统共享库的符号,只需adb拉取共享库并设置sollib搜索路径即可。

$ adb pull /system/lib lib
$ ndk-gdb
...
(gdb) set solib-search-path lib

注意事项:

  • 在某些情况下,您的堆栈跟踪可能会损坏,因为您的堆栈已被部分破坏。不太可能
  • 您使用的操作系统是什么?姜饼(Android 2.3)在堆栈跟踪方面要好得多。如果你没有运行Android 2.3,可以在某个地方为你的手机找到一个Android 2.3 ROM,或者买一个运行2.3的廉价开发手机
  • 你看过奥努尔的剧本吗?它对我来说一直运行得很好,即使在安卓2.2手机上也是如此
  • 希望法登能读到这篇文章,我相信他有一个比我更有帮助的答案

查看以下问题:当我的gcc C++应用程序崩溃时,如何生成堆栈竞赛

我们对Android应用程序也做了同样的操作。:我们编写了自己的信号处理程序,处理了信号7(sigbus)和11(sigsegov),并从处理程序中打印出堆栈tace。不过,我们没有使用backtrace()函数,而是手动取消堆栈。。。

结合前两个答案,您应该能够编写自己的信号处理程序来转储堆栈跟踪。这篇文章还可以帮助您:http://www.ibm.com/developerworks/power/library/l-sigdebug/index.html.请记住,提取寄存器内容取决于体系结构,因此您必须将上述代码中使用的结构替换为android上的结构(取决于ARM处理器)。例如,我不得不深入研究"structucontext"的Android源代码。

当您有堆栈跟踪时,在输出上运行一个脚本,该脚本将使用addr2line和您的可执行文件解析符号。

很抱歉我自己的问题充斥着答案,但我确实发现集成Google Breakpad是获得良好堆栈跟踪/崩溃报告的绝佳方法。编写一个调用Breakpad的信号处理程序很容易,它可以处理所有事情;我们只需要把报告上传到我们的服务器上。我们还将调用stackwalk.sh的过程集成到了构建系统中。这需要一些工作,但总的来说,它非常适合在Android上获得良好的本地崩溃报告。

这个答案有一些关于编写信号处理程序的细节;你需要的其余代码在维基下的谷歌Breakpad网站上。

对于一些堆栈跟踪,我确实得到了这个问题的答案。(从这个问题的外观来看,这可能是我得到的全部。)这些是以lr(链接寄存器)地址结尾的。请参阅我的其他问题/答案。