On 11/6/19 6:21 PM, Egeyar Bagcioglu wrote:
Hello,
Hello.
I would like to propose the following patches which introduce a compile option
--record-gcc-command-line. When passed to gcc, it saves the command line option
into the produced object file. The option makes it trivial to trace back how a
file was compiled and by which version of the gcc. It helps with debugging,
reproducing bugs and repeating the build process.
I like your motivation, we as SUSE would like to have a similar functionality.
But the current approach has some limitations that make it not usable (will
explain later).
This option is similar to -frecord-gcc-switches. However, they have three fundamental differences: Firstly, -frecord-gcc-switches saves the internal state after the argv is processed and passed by the driver. As opposed to that, --record-gcc-command-line saves the
I would not name it as a fundamental changes, it's doing very similar to what
-frecord-gcc-switches does. Moreover, we also have one another option
-grecord-gcc-switches
that saves command line into DWARF. Plus there's a Red Hat plugin called
Annobin:
https://www.youtube.com/watch?v=uzffr1M-w5M
https://developers.redhat.com/blog/2018/02/20/annobin-storing-information-binaries/
Main limitation of current approach (and probably the suggested patch) are:
a) it does not print per function options, which can be modified with
__attribute__ (or pragma):
$ cat demo.c
int foo()
{
return 1;
}
#pragma GCC optimize ("-O3")
int bar()
{
return 0;
}
int main()
{
return 0;
}
b) we as SUSE are switching to LTO (-flto); doing that each LTO LTRANS will
become one compilation unit and
one will see a misleading command line invocation:
$ gcc -flto -O2 demo2.c -c
$ gcc -flto -O3 demo.c -c
$ gcc demo.o demo2.o -o a.out -frecord-gcc-switches
...
.file "<artificial>"
.section .GCC.command.line,"MS",@progbits,1
.ascii "-mtune=generic"
.zero 1
.ascii "-march=x86-64"
.zero 1
.ascii "-auxbase-strip a.out.ltrans0.ltrans.o"
.zero 1
.ascii "-O3"
.zero 1
.ascii "-fno-openmp"
.zero 1
.ascii "-fno-openacc"
.zero 1
.ascii "-fno-pie"
.zero 1
.ascii "-frecord-gcc-switches"
.zero 1
.ascii "-fltrans"
.zero 1
.ascii "a.out.ltrans0.o"
.zero 1
.text
.type foo, @function
c) Current option recording is missing macros, which can influence compilation
significantly:
-D_FORTIFY_SOURCE=2
Martin
command-line as received by the driver. Secondly, -frecord-gcc-switches saves
the switches as separate entries into a mergeable string section. Therefore,
the entries belonging to different object files get mixed up after being
linked. The new --record-gcc-command-line, on the other hand, creates one entry
per invocation. By doing so, it makes it clear which options were used together
in a single gcc invocation. Lastly, --record-gcc-command-line also adds the
version of the gcc into this single entry to make it clear which version of gcc
was called with any given command line. This is useful in cases where .comment
section reports multiple versions.
While there are also similarities between the implementations of these two
options, they are completely independent. These commands can be used separately
or together without issues. I used the same section that -frecord-gcc-switches
uses on purpose. I could not use the name -frecord-gcc-command-line for this
option; because of a {f*} in the specs, which forwards all options starting
with -f to cc1/cc1plus as is. This is not we want for this option. We would
like to append it a filename as well to pass the argv of the driver to child
processes.
This functionality operates as the following: It saves gcc's argv into a temporary
file, and passes --record-gcc-command-line <tempfilename> to cc1 or cc1plus.
The functionality of the backend is implemented via a hook. This patch includes an
example implementation of the hook for elf targets: elf_record_gcc_command_line
function. This function reads the given file and writes gcc's version and the command
line into a mergeable string section, .GCC.command.line.
Here is an *example usage* of the option:
[egeyar@localhost save-commandline]$ gcc main.c --record-gcc-command-line
[egeyar@localhost save-commandline]$ readelf -p .GCC.command.line a.out
String dump of section '.GCC.command.line':
[ 0] 10.0.0 20191025 (experimental) : gcc main.c
--record-gcc-command-line
The following is a *second example* calling g++ with -save-temps,
-frecord-gcc-switches, and repetition of options, where --save-temps saves the
intermediate file, main.cmdline in this case. You can see that the options are
recorded unprocessed:
[egeyar@localhost save-commandline]$ g++ main.c -save-temps
--record-gcc-command-line -O0 -O2 -O3 --record-gcc-command-line
[egeyar@localhost save-commandline]$ readelf -p .GCC.command.line a.out
String dump of section '.GCC.command.line':
[ 0] 10.0.0 20191025 (experimental) : g++ main.c -save-temps
--record-gcc-command-line -O0 -O2 -O3 --record-gcc-command-line
Here is a *third example* calling g++ with both -frecord-gcc-switches and
--record-gcc-command-line for comparison:
[egeyar@localhost save-commandline]$ g++ main.c --record-gcc-command-line
-frecord-gcc-switches
[egeyar@localhost save-commandline]$ readelf -p .GCC.command.line a.out
String dump of section '.GCC.command.line':
[ 0] 10.0.0 20191025 (experimental) : g++ main.c
--record-gcc-command-line -frecord-gcc-switches
[ 5c] -D_GNU_SOURCE
[ 6a] main.c
[ 71] -mtune=generic
[ 80] -march=x86-64
[ 8e] --record-gcc-command-line /tmp/ccgC4ZtS.cmdline
The first patch of this two-patch-series only extends the testsuite machinery,
while the second patch implements this functionality and adds a test case for
it. In addition to that new test case, I built binutils as my test case after
passing this option to CFLAGS. The added .GCC.command.line section of ld listed
many compile commands as expected. Tested on x86_64-pc-linux-gnu.
Please review the patches, let me know what you think and apply if appropriate.
Regards
Egeyar
Egeyar Bagcioglu (2):
Introduce dg-require-target-object-format
Introduce the gcc option --record-gcc-command-line
gcc/common.opt | 4 +++
gcc/config/elfos.h | 5 +++
gcc/doc/tm.texi | 22 ++++++++++++
gcc/doc/tm.texi.in | 4 +++
gcc/gcc.c | 41 ++++++++++++++++++++++
gcc/gcc.h | 1 +
gcc/target.def | 30 ++++++++++++++++
gcc/target.h | 3 ++
.../c-c++-common/record-gcc-command-line.c | 8 +++++
gcc/testsuite/lib/target-supports-dg.exp | 11 ++++++
gcc/toplev.c | 13 +++++++
gcc/varasm.c | 36 +++++++++++++++++++
12 files changed, 178 insertions(+)
create mode 100644 gcc/testsuite/c-c++-common/record-gcc-command-line.c