确定用于在*ix操作系统上构建共享对象的编译器和版本

Determining compiler and version used to build a shared object on *ix operating system

本文关键字:对象 共享 编译器 版本 构建 用于 操作系统 ix      更新时间:2023-10-16

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

在过去,我已经能够使用"strings-a|grep"方法,如下所示。然而,这种方法不适用于在powerAIX上使用g++4.8编译的代码,对于在x86Linux上使用g++4.8编译的代码来说,它的工作效果不是特别好。

如果可能的话,我也想找到一些比查找字符串更干净的方式来获取这些信息。

有人能就如何在共享对象中查询构建该对象的编译器的名称以及该编译器的版本提供建议吗


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

在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)

在强大的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

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

在一个强大的AIX g++4.8编译对象上

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

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

多亏了一位同事,我发现了这种方法,可以检测库是否在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

it

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

不可能万无一失地实现您想要实现的目标。您有时可能能够找到编译器的随机符号或某些编译器标志,但肯定没有获得这些信息的通用方法。而且这些信息中的大多数根本不存在于对象文件中(例如,据我所知,没有一个编译器会将使用的编译器标志存储到对象文件中)。

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