只是为了给你一些背景,这就是我想要实现的目标: 我在一个共享对象文件中嵌入一个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上工作)
答案 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具有一些高度可识别的模式,并扫描整个文件 线性地寻找这种模式。