[Bug driver/94198] New: Placement of source file in GCC command line has impact on whether the link succeeds

ldionne.2 at gmail dot com gcc-bugzilla@gcc.gnu.org
Mon Mar 16 17:23:09 GMT 2020


https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94198

            Bug ID: 94198
           Summary: Placement of source file in GCC command line has
                    impact on whether the link succeeds
           Product: gcc
           Version: 9.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: driver
          Assignee: unassigned at gcc dot gnu.org
          Reporter: ldionne.2 at gmail dot com
  Target Milestone: ---

It seems that the position where the source file is specified to GCC has an
impact on how it is linked when other `-l` options are passed.

For example, the following command (with the source file specified last) fails
to link:

    $ /usr/bin/g++-9 -L/llvm/build-linux/lib -Wl,-rpath,/llvm/build-linux/lib
-nodefaultlibs -lc++ -lm -lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc go.cpp
    /tmp/ccusVxoZ.o: In function `main':
    go.cpp:(.text+0xa): undefined reference to `__cxa_allocate_exception'
    go.cpp:(.text+0x1a): undefined reference to `typeinfo for int'
    go.cpp:(.text+0x22): undefined reference to `__cxa_throw'
    go.cpp:(.text+0x2a): undefined reference to `__cxa_begin_catch'
    go.cpp:(.text+0x2f): undefined reference to `__cxa_end_catch'
    /tmp/ccusVxoZ.o:(.eh_frame+0x13): undefined reference to
`__gxx_personality_v0'
    collect2: error: ld returned 1 exit status

However, the same command-line with the source file specified first links
successfully:

    $ /usr/bin/g++-9 go.cpp -L/llvm/build-linux/lib
-Wl,-rpath,/llvm/build-linux/lib -nodefaultlibs -lc++ -lm -lgcc_s -lgcc
-lpthread -lc -lgcc_s -lgcc
    <works>

I've tracked it down to a difference in how `collect2` is called after the
assembler. When the source file appears first (which works), `collect2` is
called as:

    $ collect2 [...] /tmp/XXXXX.o -rpath /llvm/build-linux/lib -lc++ -lm
-lgcc_s -lgcc -lpthread -lc -lgcc_s -lgcc [...]

However, when the source file appears last (which fails), `collect2` is called
as follows:

    $ collect2 [...] -rpath /llvm/build-linux/lib -lc++ -lm -lgcc_s -lgcc
-lpthread -lc -lgcc_s -lgcc /tmp/XXXXX.o [...]

You can notice how in the former, the temporary object file `/tmp/XXXXX.o`
appears _before_ the various libraries to link, and in the latter it appears
after. Because of how most linkers operate, the latter can't possibly link.

Since the way GCC calls the linker with a temporary object file is an
implementation detail, I believe the correct behavior here should be that in
both cases, GCC passes the object file before the various libraries to link.

This issue was discovered while running the libc++ conformance test suite with
GCC.


More information about the Gcc-bugs mailing list