c++ - nm 符号值的偏移量?

标签 c++ macos unix linker nm

只是为了给您一些背景信息,以下是我正在努力实现的目标: 我在共享对象文件中嵌入了一个 const char*,以便在 .so 文件本身中有一个版本字符串。我正在做数据分析,这个字符串使我能够让数据知道是哪个版本的软件产生的。这一切都很好。

我遇到的问题是当我尝试直接从 .so 库中读取字符串时。我试着用

nm libSMPselection.so | grep _version_info

得到

000000000003d968 D __SMPselection_version_info

一切正常,符合预期(char* 称为 _SMPselection_version_info)。 然而,我原本希望现在能够打开文件,查找 0x3d968 并开始读取我的字符串,但我得到的只是垃圾。

当我打开 .so 文件并简单地搜索字符串的内容时(我知道它是如何开始的),我可以在地址 0x2e0b4 找到它。在这个地址它在那里,零终止并且如预期的那样。 (我目前使用的是这种方法。)

我不是计算机科学家。有人可以向我解释为什么 nm 显示的符号值不正确,或者换句话说,如果不是符号的地址,符号值是什么?

(顺便说一下,我正在使用 OSX 10.7 的 Mac 工作)

最佳答案

假设它是一个 ELF 或类似结构的二进制文件,您必须考虑加载内容的地址,这受 ELF header 中内容的影响。

在您的二进制文件上使用 objdump -Fd,您可以让反汇编器还显示符号的确切文件偏移量。

使用 objdump -x 你可以找到这个加载器地址,标准 linux 可执行文件通常是 0x400000。

接下来您需要注意的是查看它是否是间接字符串,您可以使用 objdump -g 轻松完成此操作。当发现字符串是间接字符串时,在objdump -Fd 输出的位置你不会找到字符串,而是地址。您需要从中再次减去加载程序地址。让我向您展示我的一个二进制文件的示例:

objdump -Fd BIN | grep VersionString
  45152f:       48 8b 1d 9a df 87 00    mov    0x87df9a(%rip),%rbx        # ccf4d0 <acVersionString> (File Offset: 0x8cf4d0)

objdump -x BIN
...
LOAD off    0x0000000000000000 vaddr 0x0000000000400000 paddr 0x0000000000400000 align 2**12
...

所以我们查看文件中的0x8cf4d0,在十六进制编辑器中找到:

008C:F4D0 D8 C1 89 00  00 00 00 00  01 00 00 00  FF FF FF FF

所以我们在那里取 0x89C1D8,减去 0x400000 得到 0x49c1d8,当我们在十六进制编辑器中查看时,我们发现:

0049:C1D0 FF FF 7F 7F  FF FF 7F FF  74 72 75 6E  6B 5F 38 30
0049:C1E0 34 33 00 00  00 00 00 00  00 00 00 00  00 00 00 00

意思是“trunk_8043”。

YMMV,尤其是当它是一些其他文件格式时,但这是这些东西的结构的一般方式,有很多缺点和特殊情况下偏离的细节。

关于c++ - nm 符号值的偏移量?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10430655/

相关文章:

bash - 获取 HDFS 中最后更新的文件夹

c++ - 在 WinAPI 项目中管理字符串资源的现代方法

swift - 为什么在SpriteKit中添加的节点不适合窗口?

macos - Mac 上不显示 Outlook 插件

objective-c - 禁用 ESC 和 Command 。在 OSX Cocoa 应用程序中

c - C中的套接字编程(客户端服务器示例)

linux - 我只想从 unix 文件中搜索字符串,前提是它后面跟着另一个字符串

c++ - 如何避免在 C++ 中自动释放?

c++ - 通过引用传递时隐式转换不起作用

c++ - dlopen 在 gdb 中运行时导致段错误