每当我的 android 应用程序原生代码发生崩溃时,我都会使用 NDK 提供的 addr2line 工具将地址解析为源代码中的确切代码行。这些天来,我一直在忽略调用堆栈中提供的其他信息,即偏移量。示例崩溃堆栈
08-16 07:44:47.328 1349 1349 F DEBUG : #00 pc 0000000000e52516 /data/data/com.syam.test/files/data/applibs/libnative.so (offset 0x1702000)
08-16 07:44:47.328 1349 1349 F DEBUG : #01 pc 0000000000e5242b /data/data/com.syam.test/files/data/applibs/libnative.so (offset 0x1702000)
08-16 07:44:47.328 1349 1349 F DEBUG : #02 pc 0000000000e5226d /data/data/com.syam.test/files/data/applibs/libnative.so (offset 0x1702000)
在考虑这些偏移量的同时,我也开始明白,我也不知道这些地址在物理上对应什么......有人可以告诉我这两个崩溃堆栈,即地址和偏移量。这些到底对应什么,我怎样才能更好地利用它们。
最佳答案
偏移量只是加载该模块(即共享库)的进程中的起始地址。所以与进程本身相关的实际地址是offset + address
.
这就是操作系统仅根据当时程序寄存器中的地址来识别哪个模块崩溃的方式。请注意,至少还有另一层,因为进程本身在全局地址空间中具有自己的偏移量,并且实际上可以由操作系统移动。但是我跑题了。。
由于库本身可能会加载到进程地址空间内的任何位置,因此除非开发人员也知道偏移量,否则它对开发人员没有用处。幸运的是,您可以减去偏移量并返回到在编译时确定的库特定地址。这就是 addr2line
作品。
换句话说,偏移量可以改变,但地址是固定的。
所有这一切的重点是您不需要编译包含任何调试符号的二进制文件(因此其他人无法轻松找出您的程序是如何工作的)。但是如果有人报告了崩溃并且您至少有进程地址和库偏移量,您可以使用私有(private)调试符号来确定它发生在哪里。
所以,如果你有 libnative.so
的符号和源代码用于构建在程序崩溃时运行的版本,然后您可以使用完全相同的技术来了解发生这种情况的位置。如果幸运的话,该库可能包含一些基本的调试信息,例如函数名称。
关于android - native 崩溃调用堆栈中的地址和偏移量到底是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63518186/