有没有办法看到在* nix中使用什么编译器和标志来创建可执行文件?我有一个旧版本的代码编译,我想看看是否编译有或没有优化。谷歌没有太大帮助,但我不确定我使用的是正确的关键词。
答案 0 :(得分:58)
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.
之后,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
当然,它不适用于没有该选项编译的可执行文件。
对于简单的优化情况,如果文件是使用调试信息编译的,那么可以尝试使用调试器。如果您稍微介绍一下,您可能会注意到某些变量已“优化”。这表明优化已经发生。
答案 1 :(得分:12)
如果使用-frecord-gcc-switches
标志进行编译,则命令行编译器选项将写入注释部分的二进制文件中。 See also the docs
答案 2 :(得分:8)
另一种选择是-grecord-gcc-swtiches(注意,不是-f但是-g)。根据gcc docs,它会将标志放入矮人调试信息中。看起来它默认启用,因为gcc 4.8。
我发现dwarfdump程序对于提取那些cflags非常有用。注意,字符串程序看不到它们。看起来矮人信息被压缩了。
答案 3 :(得分:3)
这需要编译器支持。你没有提到你正在使用什么编译器,但是因为你标记了你的问题linux
我会假设你正在使用gcc - 它不会默认你要问的功能(但-frecord-gcc-switches是执行此操作的选项。)
如果要检查二进制文件,strings
命令将显示文件中看似可读字符串的所有内容。
答案 4 :(得分:1)
我非常怀疑这是可能的:
int main()
{
}
编译时使用:
gcc -O3 -ffast-math -g main.c -o main
在生成的对象中找不到任何参数:
strings main | grep -O3
(no output)
答案 5 :(得分:1)
如果您仍然使用了您使用的编译器(相同版本),并且它只是您不确定的一个标志,您可以尝试再次编译代码,一次使用,一次没有标记。然后你可以比较可执行文件。你的旧的应该与其中一个相同或非常相似。
答案 6 :(得分:1)
只要可执行文件是由带有 -g
选项的 gcc 编译的,以下内容就可以解决问题:
readelf --debug-dump=info /path/to/executable | grep "DW_AT_producer"
例如:
% 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
遗憾的是,clang 似乎没有以类似的方式记录选项,至少在版本 10 中如此。
当然,strings
也会出现这种情况,但是人们必须至少知道要查找什么,因为用肉眼检查现实世界二进制文件中的所有字符串通常是不切实际的。例如。使用上面示例中的二进制文件:
% strings ./test | grep march
GNU C17 10.2.0 -mtune=generic -march=x86-64 -g -O3