[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