【发布时间】:2013-05-30 01:22:15
【问题描述】:
我最近正在调试一个定期出现段错误的应用程序——我解决了这个问题,这个问题相对普通(从空指针读取),但我还有一些无法解决的遗留问题我自己的。
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 和内核消息如何在错误类型和指令相对于共享库基地址的偏移量上达成一致,但在指令指针的地址和正在使用的共享库?
【问题讨论】:
-
您看到的原因是共享库中入口点的进程私有地址就是这样。本地的过程。它们已被内核从库的文本段真正所在的位置“转换”。以匹配您的流程要求。 “未转换”版本是内核驻留的。所以,两者都是正确的。想想看。所有进程都不能有 0x00000 地址(或任何基址)。每个进程的基地址物理上位于实际内存中的其他位置。不是流程认为的位置。
-
这是有道理的,但它没有解释为什么内核说错误发生在 /lib/libc-2.12.so 但 gdb 将错误放在 /lib64/libc.so.6 中。我运行的是 64 位系统,所以也许这些库是一样的?
-
一个是符号链接,另一个是链接代码的实际库文件。对照你的编译文件查看 ldd 命令的输出:ldd myexecutable
标签: linux gdb segmentation-fault shared-libraries