偏移的nm符号值?

时间:2012-05-03 11:43:06

标签: 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上工作)

4 个答案:

答案 0 :(得分:7)

假设它是一个ELF或类似结构的二进制文件,你必须考虑加载东西的地址,这受到ELF头中的东西的影响。

在二进制文件上使用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并找到hexeditor:

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

所以我们在那里取0x89C1D8,减去0x400000并得到0x49c1d8,当我们在hexeditor中查看时,我们发现:

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,特别是当它的其他文件格式时,但这是关于这些事情的结构的一般方式,有很多瑕疵和细节偏离特殊情况。

答案 1 :(得分:2)

没有人建议最简单的方法:做一个动态加载你的lib的二进制文件(在命令行上给它命名)并为你的符号做dlsym()(或者也可以在命令行上得到它)把它转换为字符串指针并将其打印到stdout。

答案 2 :(得分:1)

在Linux上,你有'strings'命令可以帮助你从二进制文件中提取字符串。

http://linux.about.com/library/cmd/blcmdl1_strings.htm

在HPUX中(我认为在其他Unix版本中)也有类似的命令叫做'what'。它只提取以“@(#)”开头的字符串,但是如果你控制字符串的内容,这不是问题。

答案 3 :(得分:1)

为什么您希望nm显示的偏移量为偏移量 .so文件? .so个文件不仅仅是内存映像;他们包含 还有很多其他信息,并且或多或少有些复杂 格式。在Unix下(至少在大多数Unices下),共享对象使用 精灵格式。要查找信息,您必须解释 文件中的各个字段,用于查找所需符号的位置 找到,在哪个段,以及该段在文件中的起始位置。 (您可以找到一个可以简化阅读的库。)

另外,如果你说你嵌入char const*是正确的, 即你的代码包含如下内容:

char const* version = "...";

然后version的地址或偏移量是地址或偏移量 指针,而不是它指向的字符串数据。将其定义为:

char const version[] = "...";

会解决这个问题。

最后,最简单的解决方案可能只是确保 string具有一些高度可识别的模式,并扫描整个文件 线性地寻找这种模式。