从编译的可执行文件中获取编译器选项?

Mos*_*sby 48 c c++ linux

有没有办法看到在*nix中使用什么编译器和标志来创建可执行文件?我有一个旧版本的代码编译,我想看看是否编译有或没有优化.谷歌没有太大帮助,但我不确定我使用的是正确的关键词.

Mic*_*rny 60

gcc有一个-frecord-gcc-switches选项:

   -frecord-gcc-switches
       This switch causes the command line that was used to invoke the compiler to
       be recorded into the object file that is being created.  This switch is only
       implemented on some targets and the exact format of the recording is target
       and binary file format dependent, but it usually takes the form of a section
       containing ASCII text.
Run Code Online (Sandbox Code Playgroud)

之后,ELF可执行文件将包含包含.GCC.command.line该信息的部分.

$ gcc -O2 -frecord-gcc-switches a.c
$ readelf -p .GCC.command.line a.out 

String dump of section '.GCC.command.line':
  [     0]  a.c
  [     4]  -mtune=generic
  [    13]  -march=x86-64
  [    21]  -O2
  [    25]  -frecord-gcc-switches
Run Code Online (Sandbox Code Playgroud)

当然,它不适用于没有该选项编译的可执行文件.


对于简单的优化情况,如果文件是使用调试信息编译的,则可以尝试使用调试器.如果您稍微介绍一下,您可能会注意到某些变量已"优化".这表明优化发生了.


per*_*eal 13

如果使用该-frecord-gcc-switches标志进行编译,则命令行编译器选项将写入注释部分的二进制文件中.另见文档.


Ali*_*nka 9

另一种选择是-grecord-gcc-swtiches(注意,不是-f但是-g).根据gcc docs,它会将标志放入矮人调试信息中.看起来它默认启用,因为gcc 4.8.

我发现dwarfdump程序对于提取那些cflags非常有用.注意,字符串程序看不到它们.看起来矮人信息被压缩了.

  • 好一点,它甚至适用于非常老的GCC版本。您可以使用以下命令来恢复它:`readelf -wi <binary> | grep DW_AT_producer`并产生类似`DW_AT_producer:GNU C11 5.4.0 20160609 -mtune = generic -march = x86-64 -g -O2 -fstack-protector-strong`或`DW_AT_producer:GNU C 2.96 20000731(Red Hat Linux 7.2 2.96-112.7.2)` (2认同)

Ily*_*sov 9

只要可执行文件是由带有-g选项的 gcc 编译的,以下操作就可以解决问题:

readelf --debug-dump=info /path/to/executable | grep "DW_AT_producer"
Run Code Online (Sandbox Code Playgroud)

例如:

% cat test.c
int main() {
    return 42;
}
% gcc -g test.c -o test
% readelf --debug-dump=info ./test | grep "DW_AT_producer"
    <c>   DW_AT_producer    : (indirect string, offset: 0x2a): GNU C17 10.2.0 -mtune=generic -march=x86-64 -g
Run Code Online (Sandbox Code Playgroud)

遗憾的是,clang 似乎没有以类似的方式记录选项,至少在版本 10 中是这样。

当然,strings也会将其打开,但人们必须至少知道要寻找什么,因为用肉眼检查现实世界二进制中的所有字符串通常是不切实际的。例如,使用上面示例中的二进制文件:

% strings ./test | grep march
GNU C17 10.2.0 -mtune=generic -march=x86-64 -g -O3
Run Code Online (Sandbox Code Playgroud)