75

It there a way to see what compiler and flags were used to create an executable file in *nix? I have an old version of my code compiled and I would like to see whether it was compiled with or without optimization. Google was not too helpful, but I'm not sure I am using the correct keywords.

Inverse
  • 4,408
  • 2
  • 26
  • 35
Mosby
  • 1,291
  • 1
  • 10
  • 14

7 Answers7

85

gcc has a -frecord-gcc-switches option for that:

   -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.

Afterwards, the ELF executables will contain .GCC.command.line section with that information.

$ 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

Of course, it won't work for executables compiled without that option.


For the simple case of optimizations, you could try using a debugger if the file was compiled with debug info. If you step through it a little, you may notice that some variables were 'optimized out'. That suggests that optimization took place.

melpomene
  • 84,125
  • 8
  • 85
  • 148
Michał Górny
  • 18,713
  • 5
  • 53
  • 76
  • `-frecord-gcc-switches` is almost what I need. However the the resulting section has `-fpreprocessed`, and all the `-D` macro definitions are not there anymore. How can I get them? (I'm building a kernel module.) – not-a-user Nov 05 '14 at 15:28
  • 1
    @not-a-user Look at the various `-g` options gcc offers; as I recall, something like `-g3` or `-ggdb3` causes it to include macro definitions into the debug info. Perhaps that'll give you what you seek. – Brian Vandenberg Oct 19 '18 at 18:29
14

If you compile with the -frecord-gcc-switches flag, then the command line compiler options will be written in the binary in the note section. See also the docs.

perreal
  • 94,503
  • 21
  • 155
  • 181
11

Another option is -grecord-gcc-swtiches (note, not -f but -g). According to gcc docs it'll put flags into dwarf debug info. And looks like it's enabled by default since gcc 4.8.

I've found dwarfdump program to be useful to extract those cflags. Note, strings program does not see them. Looks like dwarf info is compressed.

  • 2
    Nice point, and it works even with very old GCC versions. You can use the following command to recover it: `readelf -wi | grep DW_AT_producer` and it produces output like `DW_AT_producer : GNU C11 5.4.0 20160609 -mtune=generic -march=x86-64 -g -O2 -fstack-protector-strong` or `DW_AT_producer : GNU C 2.96 20000731 (Red Hat Linux 7.2 2.96-112.7.2)` – gatopeich Jun 06 '18 at 11:58
  • True, but I think you have o use either -g or -grecord-gcc-swtiches (or -frecord-gcc-swtiches); is there any way to get the compiler flags _without_ using any of these option switches? – kaiwan Jun 25 '23 at 10:57
9

As long as the executable was compiled by gcc with -g option, the following should do the trick:

readelf --debug-dump=info /path/to/executable | grep "DW_AT_producer"

For example:

% 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

Sadly, clang doesn't seem to record options in similar way, at least in version 10.

Of course, strings would turn this up too, but one has to have at least some idea of what to look for as inspecting all the strings in real-world binary with naked eyes is usually impractical. E.g. with the binary from above example:

% strings ./test | grep march
GNU C17 10.2.0 -mtune=generic -march=x86-64 -g -O3
Ilya Kurnosov
  • 3,180
  • 3
  • 23
  • 37
  • Would suggest merging this with Aliaksei Kandratsenka's answer! Anyways, the clang people seem to have thought about doing the same at https://reviews.llvm.org/D30760?id=92410. The gist is that you use `-grecord-gcc-swtiches`, which defaults to off due to privacy concerns. – Mingye Wang Jan 15 '23 at 16:28
3

This is something that would require compiler support. You don't mention what compiler you are using but since you tagged your question linux I will assume you are using gcc -- which does not default the feature you're asking about (but -frecord-gcc-switches is an option to perform this).

If you want to inspect your binary, the strings command will show you everything that appears to be a readable character string within the file.

mah
  • 39,056
  • 9
  • 76
  • 93
1

If you still have the compiler (same version) you used, and it is only one flag you're unsure about, you can try compiling your code again, once with and once without the flag. Then you can compare the executables. Your old one should be identical, or very similar, to one of the new ones.

Zyx 2000
  • 1,625
  • 1
  • 12
  • 18
0

I highly doubt it is possible:

int main()
{
}

When compiled with:

gcc -O3 -ffast-math -g main.c -o main

None of the parameters can be found in the generated object:

strings main | grep -O3
(no output)
user1202136
  • 11,171
  • 4
  • 41
  • 62
  • Although... I was doing a comparison between the executable generated for a similar "do-nothing" program with and without optimizations, and they do show some differences around... – Matteo Italia Aug 24 '12 at 15:33
  • Ok, checking with `readelf` shows that it's just some different arrangement of the functions, nothing explicitly screaming "this was compiled with `-O3`". – Matteo Italia Aug 24 '12 at 15:48