3

让我们只关注Rect_IsEmpty()功能。

nm命令给了我这个输出:

(...)    
00021af0 T Rect_IsEmpty
(...)

另一方面,当我启动gdb并查看此函数的地址时,我得到:

(gdb) info address Rect_IsEmpty
Symbol "Rect_IsEmpty" is at 0x8057c84 in a file compiled without debugging.

谁能解释一下为什么这些地址不一样?gdb 从哪里得到这个地址?

4

2 回答 2

10

nm为您提供损坏的名称符号表的地址偏移量,同时gdb为您提供实际的虚拟进程的内存地址,每次运行该进程时都会更改该地址。

nm只是一个工具,它显示您从代码段的开头偏移。在你的情况下:

00021af0 T Rect_IsEmpty

简单地说,在整个代码段中,在所有其他函数中,该函数与代码段Rect_IsEmpty有偏移量00021af0,因此如果代码段的基址重定位到00000000,那么偏移量将与地址相同,00021af0

在 Linux 上运行可执行文件之前,ASLR 机制用于随机化地址,但不是所有地址,只是段的开始。因此,在运行可执行文件之前,您不能总是知道或依赖动态符号的地址,您只能从段起始地址获得偏移量。

使用调试器查找函数的地址时,您会在 ASLR 完成工作后看到进程代码段内的符号地址。

这是IBM 的一篇关于共享库的好文章,还有一篇关于过程链接表和全局偏移表的文章。

于 2015-07-08T13:20:51.600 回答
2

可执行文件将从不同的内存位置开始,使其内部的任何分配都不同。因此,任何函数都将具有与其先前执行不同的内存地址。

关于您的问题 GDB 从调试信息中获取地址-它将显示绝对内存地址。

于 2015-07-08T13:24:47.250 回答