【问题标题】:When I run a program in GDB, how does GDB show me the program's virtual address?当我在 GDB 中运行程序时,GDB 如何显示程序的虚拟地址?
【发布时间】:2017-09-19 01:43:08
【问题描述】:

我编译了一个简单的代码并通过 GDB 运行它。

当我在 GDB 中运行我的简单程序时,GDB 向我显示程序的虚拟地址(在我的程序的可执行目标文件中定义)。

GDB 也是一个程序。所以 GDB 有自己的虚拟地址。因为 GDB 有自己的虚拟地址,所以当 GDB 映射我的简单程序获取虚拟地址时,我的简单程序在 GDB 的虚拟地址空间中会有不同的虚拟地址。

但是 GDB 并没有向我显示那个地址。相反,GDB 向我显示了我的简单程序的虚拟地址,它在我的简单程序的可执行目标文件中定义。

这是怎么发生的? GDB 有虚拟到虚拟地址表吗?

【问题讨论】:

  • 您可能会发现由三部分组成的系列How debuggers work 很有帮助。
  • 哦,谢谢。那份文件对我有帮助。
  • 不,您的程序在附加到 gdb 自己的地址空间时不会获得不同的虚拟地址空间。您的程序无法知道它正在被调试,因为 gdb 使用可用的标准 linux 工具启动您的程序。它继续拥有与 gdb 意识到它之前相同的虚拟地址。 GDB 是将附加的进程地址(在其自己的虚拟地址空间中)转换为附加进程的虚拟地址空间的程序,因此您拥有正确的地址,就像没有涉及 gdb 一样。

标签: c debugging process gdb


【解决方案1】:

gdb 也是一个程序。所以 gdb 有自己的虚拟地址。因为gdb有自己的虚拟地址,当gdb运行我的简单程序时,我的简单程序在gdb的虚拟地址空间中会有不同的虚拟地址。

非常很困惑。

在任何现代操作系统上,gdb 和您的程序在不同(虚拟)地址空间中运行,它们彼此无关,并且可以以任意方式重叠。

对于非位置无关的可执行文件,GDB 和您的程序都将加载到它们被链接到要加载的虚拟地址。您可以将该地址视为readelf -l /path/to/a.out 输出中第一个PT_LOAD 段的VirtAddr。在 Linux/x86_64 上,该地址(默认)为0x400000

对于位置无关的可执行文件,第一个PT_LOAD段的地址通常为0,可执行文件被重定位。

如果您的二进制文件和 GDB 都是 PIE,它们都将被重新定位,但它们再次不共享地址空间,因此可以重新定位到完全相同的(虚拟)地址。

【讨论】:

  • 嗯,感谢您的回答。但我知道每个程序都有自己的地址。建议有一个程序 A. 当我的 shell 运行 gdb 时,shell 将分叉另一个进程并执行 gdb。然后,gdb 将把“A”映射到它自己的虚拟地址区域。当然,相对于写在 A 的可执行目标文件上的虚拟地址,A 的基区会发生变化。
  • 。例如,符号 main 的虚拟地址是 A 的可执行目标文件中的 0x10cfc。在 gdb 程序中,我可以在 0x10cfc(main) 处设置断点。但在 gdb 进程中,main 不会存在于 0x10cfc 中。我在这里有个问题。 gdb 怎么知道 0x10cfc 是主要的?我想我的电脑是树莓派 3(32 位)
  • 你是对的。他们不共享地址。但如果 gdb 想要指向我的简单程序“A”的某个地址,gdb 可能会“映射”程序“A”以获得虚拟地址。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-08-05
  • 2022-01-05
相关资源
最近更新 更多