我最近正在调试一个定期出现段错误的应用程序——我解决了这个问题,这个问题相对来说比较普通(从空指针读取),但是我有一些我自己无法解决的遗留问题。
在大多数情况下,gdb 堆栈跟踪是这样开始的:
0x00007fdff330059f in __strlen_sse42 () from /lib64/libc.so.6
使用 /proc/[my proc id]/maps 中的信息来获取共享库的基地址,我可以看到问题发生在共享库的同一条指令上——在指令 0x13259f 处,即
pcmpeqb (%rdi),%xmm1 (gdb)
到目前为止,一切都很好。但是随后,操作系统(linux)也会向 /var/logs/messags 写入一条错误消息,如下所示
[3540502.783205] node[24638]: segfault at 0 ip 00007f8abbe6459f sp 00007fff7bf2f148 error 4 in libc-2.12.so[7f8abbd32000+189000]
这让我很困惑。一方面,内核正确识别故障(用户模式保护故障),并且通过从指令指针中减去共享库的基地址,我们得到相同的相对偏移量——0x13259f——正如我们由 gdb 完成。但是内核标识的库不同,指令的地址不同,库中的函数和指令也不同。也就是说,libc-2-12.so 中的指令是
0x13259f <__memset_sse2+911>: movdqa %xmm0,-0x43(%edx)
所以,我的问题是,gdb 和内核消息如何在故障类型和指令相对于共享库基地址的偏移量上达成一致,但在指令指针和共享库的地址上存在分歧正在使用?