2

我在一些加载一组用户指定的共享对象的软件上工作。我想向我们的“加载器”组件添加一些代码,它可以查询每个指定的共享对象并找出用于构建/链接该共享对象的编译器和编译器版本。

过去,我可以使用“strings -a | grep”方法,如下所示。但是,这种方法不适用于在 power AIX 上使用 g++ 4.8 编译的代码,并且对于在 x86 linux 上使用 g++ 4.8 编译的代码也不是特别好。

如果可能的话,我也很想找到一些比 grepping 字符串更简洁的方法来获取这些信息。

谁能提供有关如何查询共享对象以获取构建它的编译器的名称以及该编译器的版本的建议?


这是我当前技术的一些示例命令和输出:

在 x86 linux g++ 4.1 编译的共享对象上:

$ strings -a libshareme.so | grep GNU
GCC: (GNU) 4.1.2 20080704 (Red Hat 4.1.2-50)
<etc>

(这里有很多重复的输出,但很明显版本是GCC 4.1.2)

在 Power AIX xlC v11 编译对象上

$ strings -a libshareme.so | grep XL
XL  
IBM XL C/C++ for AIX, Version 11.1.0.6
IBM XL C/C++ for AIX, Version 10.1.0.6

(显示 v11 和 v10 有点令人困惑,但 XL C 很清楚)

在 x86 linux g++ 4.8 编译的共享对象上:

$ strings -a libshareme.so | grep GNU
GCC: (GNU) 4.4.6 20120305 (Red Hat 4.4.6-4)
GCC: (GNU) 4.8.2 20131111 (Red Hat 4.8.2-4)
GNU C++ 4.8.2 20131111 (Red Hat 4.8.2-4) -m32 -mtune=generic -march=i686 -g -fmessage-length=0 -fPIC

(这里也有点令人困惑,它显示了多个版本)

在 Power AIX g++ 4.8 编译对象上

$ strings -a libshareme.so | grep GNU
<no output>

在 x86/linux 上,我通常会在我可以匹配的 'strings -a' 输出中看到“GNU”类型的字符串。但是,在使用 g++4.8 在 power/aix 上编译的这个 libshareme.so 上使用 strings -a 并没有向我显示任何关于编译器版本的明显信息。

4

2 回答 2

1

多亏了一位同事来检测库是否在 AIX 上使用 g++ 编译,我才找到了这种方法:

dump -X32_64 -Tv libshareme.so  | grep libgcc 

[1]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __cxa_finalize
[2]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __register_frame_info_table
[3]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __deregister_frame_info
[4]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __cmpdi2
[5]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __gcc_qdiv
[6]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) __udivdi3
[7]     0x00000000    undef      IMP     DS EXTref libgcc_s.a(shr.o) _Unwind_Resume
[635]   0x20118d70    .data      EXP     DS   Ldef        [noIMid] __init_aix_libgcc_cxa_atex

这种方法加上原始问题中的方法基本上可以让我编写代码来检测编译器(至少是我正在使用的编译器)以及在加载失败期间编译器的任何潜在不匹配。

于 2014-10-31T17:52:59.257 回答
0

不可能万无一失地做你想做的事。您有时可能能够找到编译器的随机符号或某些编译器标志,但肯定没有通用的方法来获取此信息。而且这些信息中的大部分根本不存在于目标文件中(例如,我所知道的没有编译器存储用于目标文件的确切编译器标志)。

你可以看看其他包的作者做了什么,我会先检查 Perl。Perl 使用它自己的“./configure”脚本,它收集不同工具的路径和要与它们一起使用的标志,然后在编译 perl 二进制文件和那里提供的标准模块时使用这些信息。这些信息也被编译到 perl 二进制文件中,为了方便起见,以后可以打印出来(perl -V),或者用于通过 perl 自己的 make helper 库编译“匹配”额外的 perl 模块(请参阅perl Makefile.PL)。甚至 perl 的功能也不是万无一失的,因为您可能会尝试加载不兼容的编译/链接共享库。

于 2014-10-16T13:52:45.973 回答