Page MenuHomeFreeBSD

Fix the GOOGLETEST build with mips-gcc{6,9}
Needs ReviewPublic

Authored by kevans on Jan 10 2020, 9:25 PM.

Details

Summary

With both gcc6 and gcc9, GCC seems to attempt some optimization in googletest consumers using __floatunsidf, which breaks with our compiler-rt because we compile libgcc.a with -fvisibility=hidden.

gtest_unittest results in always_inline failures, e.g.:

/usr/obj/usr/src/mips.mips/tmp/usr/include/c++/v1/ostream: In member function 'virtual void AssertionResultTest_CanSt
reamOstreamManipulators_Test::TestBody()':
/usr/obj/usr/src/mips.mips/tmp/usr/include/c++/v1/ostream:1004:1: error: inlining failed in call to always_inline 'st
d::__1::basic_ostream<_CharT, _Traits>& std::__1::endl(std::__1::basic_ostream<_CharT, _Traits>&) [with _CharT = char
; _Traits = std::__1::char_traits<char>]': indirect function call with a yet undetermined callee
endl(basic_ostream<_CharT, _Traits>& __os)
^~~~ /usr/obj/usr/src/mips.mips/tmp/usr/include/c++/v1/ostream:196:24: note: called from here
{ return __pf(*this); }

I've scoped the exclusion down to current versions of gcc used to build so we naturally re-evaluate it with the next version (though I'd suspect it won't change there).

Diff Detail

Repository
rS FreeBSD src repository
Lint
Lint Skipped
Unit
Unit Tests Skipped
Build Status
Buildable 28595

Event Timeline

kevans created this revision.Jan 10 2020, 9:25 PM
kevans updated this revision to Diff 66606.Jan 10 2020, 10:28 PM

Unhide floatunsidf in the build gloop, instead. I can narrow the scope to just mips, if desired, but it's not clear to me why the builtins are hidden in the first place.

kevans added a reviewer: kib.Jan 11 2020, 1:47 AM

Adding kib, too, for discussion.

Does the decision to hide by default predate using it as libgcc and we wanted to prevent collisions, allowing us to remove -fvisibility instead?

kib added a comment.Jan 11 2020, 9:52 AM

libcompiler_rt provides symbols needed by a (the ?) compiler-generated code. As such they are not part of the ABI contract for the FreeBSD platforms and must not be exported neither from libraries nor from binaries, which can be compiled with different compilers, requiring different support routines.

This is the reason why the replacement for libgcc.a must not export them, and the symbols must not be reexported after linking. For the same reasons symbols must not be exported from libgcc.so, the only ABI part of libgcc.so are unwinder and corresponding support.

In fact, if something tries to link to the hidden symbol in libgcc.so (is this true ?), perhaps this something should get libgcc.a in the linker arguments, at the right position.

In D23128#507007, @kib wrote:

libcompiler_rt provides symbols needed by a (the ?) compiler-generated code. As such they are not part of the ABI contract for the FreeBSD platforms and must not be exported neither from libraries nor from binaries, which can be compiled with different compilers, requiring different support routines.
This is the reason why the replacement for libgcc.a must not export them, and the symbols must not be reexported after linking. For the same reasons symbols must not be exported from libgcc.so, the only ABI part of libgcc.so are unwinder and corresponding support.

Ah, ok, thanks for the explanation! This makes more sense..

In fact, if something tries to link to the hidden symbol in libgcc.so (is this true ?), perhaps this something should get libgcc.a in the linker arguments, at the right position.

So let's rewind instead of papering over it- here's the failure mode:

--- zfsd_unittest.full ---
/usr/local/bin/mips-unknown-freebsd13.0-g++6 --sysroot=/usr/obj/usr/src/mips.mips/tmp -B/usr/local/mips-unknown-freebsd13.0/bin/ -O -pipe -DNEED_SOLARIS_BOOLEAN -I/usr/src/cddl/contrib/opensolaris/lib/libzpool/common -I/usr/src/cddl/compat/opensolaris/include -I/usr/src/cddl/compat/opensolaris/lib/libumem -I/usr/src/sys/cddl/compat/opensolaris -I/usr/src/cddl/contrib/opensolaris/head -I/usr/src/cddl/contrib/opensolaris/lib/libuutil/common -I/usr/src/cddl/contrib/opensolaris/lib/libumem/common -I/usr/src/cddl/contrib/opensolaris/lib/libzfs_core/common -I/usr/src/cddl/contrib/opensolaris/lib/libzfs/common -I/usr/src/cddl/contrib/opensolaris/lib/libnvpair -I/usr/src/sys/cddl/contrib/opensolaris/common/zfs -I/usr/src/sys/cddl/contrib/opensolaris/uts/common -I/usr/src/sys/cddl/contrib/opensolaris/uts/common/fs/zfs -I/usr/src/cddl/usr.sbin -G0 -EB -mabi=32 -msoft-float -g -Wno-format-zero-length -Wsystem-headers -Werror -Wall -Wno-format-y2k -W -Wno-unused-parameter -Wpointer-arith -Wno-uninitialized -Wno-error=address -Wno-error=array-bounds -Wno-error=attributes -Wno-error=bool-compare -Wno-error=cast-align -Wno-error=clobbered -Wno-error=deprecated-declarations -Wno-error=enum-compare -Wno-error=extra -Wno-error=inline -Wno-error=logical-not-parentheses -Wno-error=strict-aliasing -Wno-error=uninitialized -Wno-error=unused-but-set-variable -Wno-error=unused-function -Wno-error=unused-value -Wno-error=misleading-indentation -Wno-error=nonnull-compare -Wno-error=shift-negative-value -Wno-error=tautological-compare -Wno-error=unused-const-variable -Wno-unknown-pragmas -I/usr/include/private -DGTEST_HAS_POSIX_RE=1 -DGTEST_HAS_PTHREAD=1 -DGTEST_HAS_STREAM_REDIRECTION=1 -frtti -std=c++11  -EB -mabi=32  -o zfsd_unittest.full  callout.o case_file.o zfsd_event.o vdev.o vdev_iterator.o zfsd.o zfsd_exception.o zpool_list.o libmocks.o zfsd_unittest.o -lprivatedevdctl  -lzfs  -lzfs_core  -lutil  -lgeom  -lbsdxml  -lsbuf  -lnvpair  -luutil -lprivategmock_main -lprivategmock -lprivategtest
/usr/local/bin/mips-unknown-freebsd13.0-ld: zfsd_unittest.full: hidden symbol `__floatunsidf' in /usr/obj/usr/src/mips.mips/tmp/usr/lib/libgcc.a(floatunsidf.o) is referenced by DSO
/usr/local/bin/mips-unknown-freebsd13.0-ld: final link failed: bad value
collect2: error: ld returned 1 exit status
*** [zfsd_unittest.full] Error code 1

I popped over to the googletest objdir and checked out gtest:

# readelf -a libprivategtest.so | grep 'floatunsidf'
   540: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf
   394: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf

This one's build from a single .o, gtest-all:

# readelf -a gtest-all.o | grep 'floatunsidf'
00007ff8 00062425 R_MIPS_JALR         00000000 __floatunsidf
00008090 00062425 R_MIPS_JALR         00000000 __floatunsidf
00007ff0 0006240b R_MIPS_CALL16       00000000 __floatunsidf
00008088 0006240b R_MIPS_CALL16       00000000 __floatunsidf
  1572: 0000000000000000     0 NOTYPE  GLOBAL DEFAULT  UND __floatunsidf
kib added a comment.EditedJan 11 2020, 4:02 PM
# readelf -a libprivategtest.so | grep 'floatunsidf'
   540: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf
   394: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf

So two questions:

  1. does libcompiler_rt on mips provide the symbol ?
  2. Is libgcc.a linked into the libprivategtest.o ?
In D23128#507040, @kib wrote:
# readelf -a libprivategtest.so | grep 'floatunsidf'
   540: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf
   394: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf

So two questions:

  1. does libcompiler_rt on mips provide the symbol ?

Still a hidden symbol, as on amd64.

  1. Is libgcc.a linked into the libprivategtest.o ?

As far as I can tell, no.

kib added a comment.Jan 11 2020, 5:36 PM
In D23128#507040, @kib wrote:
# readelf -a libprivategtest.so | grep 'floatunsidf'
   540: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf
   394: 00000000000587a0     0 FUNC    GLOBAL DEFAULT  UND __floatunsidf

So two questions:

  1. does libcompiler_rt on mips provide the symbol ?

Still a hidden symbol, as on amd64.

I should have been more precise, 'does libcompiler_rt.a ...'. The visibility of the symbol is not important for resolution from a static library during link. It is enough that the symbol is provided and it is not local.

  1. Is libgcc.a linked into the libprivategtest.o ?

As far as I can tell, no.

And this is the issue. I am not sure if this a bug with our build infra or clang driver for -shared.

In D23128#507084, @kib wrote:

I should have been more precise, 'does libcompiler_rt.a ...'. The visibility of the symbol is not important for resolution from a static library during link. It is enough that the symbol is provided and it is not local.

Ah- that looks better:

root@viper:/usr/obj/usr/src/mips.mips/lib/libcompiler_rt# nm libcompiler_rt.a | grep 'floatunsidf'
         U __floatunsidf
         U __floatunsidf
floatunsidf.o:
00000000 T __floatunsidf
  1. Is libgcc.a linked into the libprivategtest.o ?

As far as I can tell, no.

And this is the issue. I am not sure if this a bug with our build infra or clang driver for -shared.

In this case, we're actually using:

--- libprivategtest.so.0.full ---
building shared library libprivategtest.so.0
/usr/local/bin/mips-unknown-freebsd13.0-g++6 --sysroot=/usr/obj/usr/src/mips.mips/tmp -B/usr/local/mips-unknown-freebsd13.0/bin/  -EB -mabi=32    -shared -Wl,-x -Wl,--fatal-warnings -Wl,--warn-shared-textrel -Wl,-z,notext  -o libprivategtest.so.0.full -Wl,-soname,libprivategtest.so.0  `NM='/usr/local/mips-unknown-freebsd13.0/bin/nm' NMFLAGS='' lorder gtest-all.pico |  tsort -q`  -lpthread 
--- libprivategtest.so.0.debug ---
/usr/local/mips-unknown-freebsd13.0/bin/objcopy --only-keep-debug libprivategtest.so.0.full libprivategtest.so.0.debug
--- libprivategtest.so.0 ---
/usr/local/mips-unknown-freebsd13.0/bin/objcopy --strip-debug --add-gnu-debuglink=libprivategtest.so.0.debug  libprivategtest.so.0.full libprivategtest.so.0
kib added a comment.Jan 11 2020, 7:30 PM

In this case, we're actually using:

--- libprivategtest.so.0.full ---
building shared library libprivategtest.so.0
/usr/local/bin/mips-unknown-freebsd13.0-g++6 --sysroot=/usr/obj/usr/src/mips.mips/tmp -B/usr/local/mips-unknown-freebsd13.0/bin/  -EB -mabi=32    -shared -Wl,-x -Wl,--fatal-warnings -Wl,--warn-shared-textrel -Wl,-z,notext  -o libprivategtest.so.0.full -Wl,-soname,libprivategtest.so.0  `NM='/usr/local/mips-unknown-freebsd13.0/bin/nm' NMFLAGS='' lorder gtest-all.pico |  tsort -q`  -lpthread

Look at how the linker invoked. Add the -### flag to the linking g++6 call and see where the -lgcc is located, if it is present at all.

Thread model: posix
gcc version 6.5.0 (FreeBSD Ports Collection for mips) 
COMPILER_PATH=/usr/local/mips-unknown-freebsd13.0/bin/:/usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/local/libexec/gcc/mips-unknown-freebsd13.0/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0/../../../../mips-unknown-freebsd13.0/bin/
LIBRARY_PATH=/usr/local/mips-unknown-freebsd13.0/bin/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/obj/usr/src/mips.mips/tmp/usr/lib/
COLLECT_GCC_OPTIONS='-B' '/usr/local/mips-unknown-freebsd13.0/bin/' '-EB' '-mabi=32' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mips3'
 /usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/collect2 -plugin /usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//ccErDyqz.res" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc_s" "--sysroot=/usr/obj/usr/src/mips.mips/tmp" --eh-frame-hdr -EB -EB -mips3 -melf32btsmip_fbsd -Bshareable --enable-new-dtags -o libprivategtest.so.0.full /usr/obj/usr/src/mips.mips/tmp/usr/lib/crti.o /usr/obj/usr/src/mips.mips/tmp/usr/lib/crtbeginS.o -L/usr/local/mips-unknown-freebsd13.0/bin -L/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0 -L/usr/obj/usr/src/mips.mips/tmp/usr/lib -x --fatal-warnings --warn-shared-textrel -z notext -soname libprivategtest.so.0 gtest-all.pico -lpthread "-lc++" -lm -lgcc_s -lc -lgcc_s /usr/obj/usr/src/mips.mips/tmp/usr/lib/crtendS.o /usr/obj/usr/src/mips.mips/tmp/usr/lib/crtn.o
COLLECT_GCC_OPTIONS='-B' '/usr/local/mips-unknown-freebsd13.0/bin/' '-EB' '-mabi=32' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mips3'

No -lgcc, but I dug a little bit and discovered that gcc is perhaps relying on the fact that -lgcc_s pulls in libgcc via linker script. Is there any harm in doing the same on FreeBSD? If so, some follow up questions:

  • Is the preferred spelling "-lgcc" or "@@LIBDIR@@/libgcc.a?" My gut says the latter, so that base system libgcc_s implies base libgcc
  • Is there any reason to use the linker script on any platform that isn't mips, other than it not having been needed yet? It doesn't seem to be scoped to any specific platform on Linux, but I say that having only examined a single libgcc_s.so on a Debian/amd64 host.
kib added a comment.Jan 11 2020, 8:18 PM
Thread model: posix
gcc version 6.5.0 (FreeBSD Ports Collection for mips) 
COMPILER_PATH=/usr/local/mips-unknown-freebsd13.0/bin/:/usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/local/libexec/gcc/mips-unknown-freebsd13.0/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0/../../../../mips-unknown-freebsd13.0/bin/
LIBRARY_PATH=/usr/local/mips-unknown-freebsd13.0/bin/:/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0/:/usr/obj/usr/src/mips.mips/tmp/usr/lib/
COLLECT_GCC_OPTIONS='-B' '/usr/local/mips-unknown-freebsd13.0/bin/' '-EB' '-mabi=32' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mips3'
 /usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/collect2 -plugin /usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc/mips-unknown-freebsd13.0/6.5.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//ccErDyqz.res" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc_s" "--sysroot=/usr/obj/usr/src/mips.mips/tmp" --eh-frame-hdr -EB -EB -mips3 -melf32btsmip_fbsd -Bshareable --enable-new-dtags -o libprivategtest.so.0.full /usr/obj/usr/src/mips.mips/tmp/usr/lib/crti.o /usr/obj/usr/src/mips.mips/tmp/usr/lib/crtbeginS.o -L/usr/local/mips-unknown-freebsd13.0/bin -L/usr/local/lib/gcc/mips-unknown-freebsd13.0/6.5.0 -L/usr/obj/usr/src/mips.mips/tmp/usr/lib -x --fatal-warnings --warn-shared-textrel -z notext -soname libprivategtest.so.0 gtest-all.pico -lpthread "-lc++" -lm -lgcc_s -lc -lgcc_s /usr/obj/usr/src/mips.mips/tmp/usr/lib/crtendS.o /usr/obj/usr/src/mips.mips/tmp/usr/lib/crtn.o
COLLECT_GCC_OPTIONS='-B' '/usr/local/mips-unknown-freebsd13.0/bin/' '-EB' '-mabi=32' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mips3'

No -lgcc, but I dug a little bit and discovered that gcc is perhaps relying on the fact that -lgcc_s pulls in libgcc via linker script. Is there any harm in doing the same on FreeBSD? If so, some follow up questions:

  • Is the preferred spelling "-lgcc" or "@@LIBDIR@@/libgcc.a?" My gut says the latter, so that base system libgcc_s implies base libgcc
  • Is there any reason to use the linker script on any platform that isn't mips, other than it not having been needed yet? It doesn't seem to be scoped to any specific platform on Linux, but I say that having only examined a single libgcc_s.so on a Debian/amd64 host.

I do not know why this happen for mips. For native amd64 linking of the shared library with -shared, I do see separate -lgcc_s and -lgcc in the ld invocation.

I suspect that there is a bug in the freebd-mips spec file.

I'm afraid I can't explain it -- I'm seeing similar results with amd64-gcc6 and amd64-gcc9:

 /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/collect2 -plugin /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cceYHZrZ.res" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc_s" "--sysroot=/usr/obj/usr/src/amd64.amd64/tmp" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable -o libprivategtest.so.0.full /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crti.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtbeginS.o -L/usr/local/x86_64-unknown-freebsd13.0/bin -L/usr/local/lib/gcc/x86_64-unknown-freebsd13.0/9.2.0 -L/usr/obj/usr/src/amd64.amd64/tmp/usr/lib -x --fatal-warnings --warn-shared-textrel -soname libprivategtest.so.0 gtest-all.pico -lpthread "-lc++" -lm -lssp_nonshared -lgcc_s -lc -lgcc_s /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtendS.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtn.o
COLLECT_GCC_OPTIONS='-B' '/usr/local/x86_64-unknown-freebsd13.0/bin/' '-fstack-protector-strong' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

AFAICT all flavors of gcc will rely on the linker script unless we define our own LIBGCC_SPEC, similar to NetBSD.

kib added a comment.Jan 12 2020, 9:06 AM

I'm afraid I can't explain it -- I'm seeing similar results with amd64-gcc6 and amd64-gcc9:

 /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/collect2 -plugin /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cceYHZrZ.res" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc_s" "--sysroot=/usr/obj/usr/src/amd64.amd64/tmp" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable -o libprivategtest.so.0.full /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crti.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtbeginS.o -L/usr/local/x86_64-unknown-freebsd13.0/bin -L/usr/local/lib/gcc/x86_64-unknown-freebsd13.0/9.2.0 -L/usr/obj/usr/src/amd64.amd64/tmp/usr/lib -x --fatal-warnings --warn-shared-textrel -soname libprivategtest.so.0 gtest-all.pico -lpthread "-lc++" -lm -lssp_nonshared -lgcc_s -lc -lgcc_s /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtendS.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtn.o
COLLECT_GCC_OPTIONS='-B' '/usr/local/x86_64-unknown-freebsd13.0/bin/' '-fstack-protector-strong' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

AFAICT all flavors of gcc will rely on the linker script unless we define our own LIBGCC_SPEC, similar to NetBSD.

This is obtained from gcc 9.2.0 from ports, native amd64:

/usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/collect2 -plugin /usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cc604iFJ.res" "-plugin-opt=-pass-through=-lgcc" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc" "-plugin-opt=-pass-through=-lgcc_s" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable /usr/lib/crti.o /usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/crtbeginS.o -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0 -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/../../../../../x86_64-portbld-freebsd11.3/lib -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/../../.. /tmp//ccw8K42v.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/crtendS.o /usr/lib/crtn.o

Note the dance with two linkages for libgcc_s around libgcc.a.

So it is almost definitely an issue with the spec, and changing libcc_s to script would cause weird breakage for native compiler.

lwhsu added a subscriber: lwhsu.Jan 13 2020, 9:08 AM
emaste added inline comments.Jan 13 2020, 7:10 PM
lib/googletest/gtest_main/tests/Makefile
24–30

I think it's fair to commit this part for now

jhb added a comment.Jan 14 2020, 8:14 PM
In D23128#507221, @kib wrote:

I'm afraid I can't explain it -- I'm seeing similar results with amd64-gcc6 and amd64-gcc9:

 /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/collect2 -plugin /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cceYHZrZ.res" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc_s" "--sysroot=/usr/obj/usr/src/amd64.amd64/tmp" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable -o libprivategtest.so.0.full /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crti.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtbeginS.o -L/usr/local/x86_64-unknown-freebsd13.0/bin -L/usr/local/lib/gcc/x86_64-unknown-freebsd13.0/9.2.0 -L/usr/obj/usr/src/amd64.amd64/tmp/usr/lib -x --fatal-warnings --warn-shared-textrel -soname libprivategtest.so.0 gtest-all.pico -lpthread "-lc++" -lm -lssp_nonshared -lgcc_s -lc -lgcc_s /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtendS.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtn.o
COLLECT_GCC_OPTIONS='-B' '/usr/local/x86_64-unknown-freebsd13.0/bin/' '-fstack-protector-strong' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

AFAICT all flavors of gcc will rely on the linker script unless we define our own LIBGCC_SPEC, similar to NetBSD.

This is obtained from gcc 9.2.0 from ports, native amd64:

/usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/collect2 -plugin /usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cc604iFJ.res" "-plugin-opt=-pass-through=-lgcc" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc" "-plugin-opt=-pass-through=-lgcc_s" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable /usr/lib/crti.o /usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/crtbeginS.o -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0 -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/../../../../../x86_64-portbld-freebsd11.3/lib -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/../../.. /tmp//ccw8K42v.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/crtendS.o /usr/lib/crtn.o

Note the dance with two linkages for libgcc_s around libgcc.a.
So it is almost definitely an issue with the spec, and changing libcc_s to script would cause weird breakage for native compiler.

Huh, ok. I can try to look at the compiler driver bits of this to fix that. FWIW, powerpc gcc and sparc64 gcc also trip over this, so it's not just mips, but probably the same root issue is present in their specs in GCC as well. riscv and aarch64 do not trip over this in my testing (haven't yet built a 32-bit arm gcc to test that arch)

jhb added a comment.Jan 14 2020, 8:17 PM
In D23128#508043, @jhb wrote:
In D23128#507221, @kib wrote:

I'm afraid I can't explain it -- I'm seeing similar results with amd64-gcc6 and amd64-gcc9:

 /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/collect2 -plugin /usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc/x86_64-unknown-freebsd13.0/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cceYHZrZ.res" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc_s" "--sysroot=/usr/obj/usr/src/amd64.amd64/tmp" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable -o libprivategtest.so.0.full /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crti.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtbeginS.o -L/usr/local/x86_64-unknown-freebsd13.0/bin -L/usr/local/lib/gcc/x86_64-unknown-freebsd13.0/9.2.0 -L/usr/obj/usr/src/amd64.amd64/tmp/usr/lib -x --fatal-warnings --warn-shared-textrel -soname libprivategtest.so.0 gtest-all.pico -lpthread "-lc++" -lm -lssp_nonshared -lgcc_s -lc -lgcc_s /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtendS.o /usr/obj/usr/src/amd64.amd64/tmp/usr/lib/crtn.o
COLLECT_GCC_OPTIONS='-B' '/usr/local/x86_64-unknown-freebsd13.0/bin/' '-fstack-protector-strong' '-shared' '-o' 'libprivategtest.so.0.full' '-shared-libgcc' '-mtune=generic' '-march=x86-64'

AFAICT all flavors of gcc will rely on the linker script unless we define our own LIBGCC_SPEC, similar to NetBSD.

This is obtained from gcc 9.2.0 from ports, native amd64:

/usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/collect2 -plugin /usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/liblto_plugin.so "-plugin-opt=/usr/local/libexec/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/lto-wrapper" "-plugin-opt=-fresolution=/tmp//cc604iFJ.res" "-plugin-opt=-pass-through=-lgcc" "-plugin-opt=-pass-through=-lgcc_s" "-plugin-opt=-pass-through=-lc" "-plugin-opt=-pass-through=-lgcc" "-plugin-opt=-pass-through=-lgcc_s" --eh-frame-hdr -m elf_x86_64_fbsd -Bshareable /usr/lib/crti.o /usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/crtbeginS.o -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0 -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/../../../../../x86_64-portbld-freebsd11.3/lib -L/usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/../../.. /tmp//ccw8K42v.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/local/lib/gcc9/gcc/x86_64-portbld-freebsd11.3/9.2.0/crtendS.o /usr/lib/crtn.o

Note the dance with two linkages for libgcc_s around libgcc.a.
So it is almost definitely an issue with the spec, and changing libcc_s to script would cause weird breakage for native compiler.

Huh, ok. I can try to look at the compiler driver bits of this to fix that. FWIW, powerpc gcc and sparc64 gcc also trip over this, so it's not just mips, but probably the same root issue is present in their specs in GCC as well. riscv and aarch64 do not trip over this in my testing (haven't yet built a 32-bit arm gcc to test that arch)

Oh, and @kib, you tested lang/gcc9, not the xtoolchain gcc that (freebsd-gcc9@amd64). Not sure then if lang/gcc9 has some local patch we need to apply to the other one. lang/gcc* don't work as system cross-compilers the way freebsd-gcc* do as they assume libstdc++ from the package and don't have kernel printf extensions, etc.

kib added a comment.Jan 14 2020, 8:36 PM
In D23128#508062, @jhb wrote:

Oh, and @kib, you tested lang/gcc9, not the xtoolchain gcc that (freebsd-gcc9@amd64). Not sure then if lang/gcc9 has some local patch we need to apply to the other one. lang/gcc* don't work as system cross-compilers the way freebsd-gcc* do as they assume libstdc++ from the package and don't have kernel printf extensions, etc.

Yes, lang/gcc9. Why the listed extensions would matter for the discussed aspect of the spec file ?

FWIW, below is the ld invocation by devel/llvm90 for shared library linking:

"/usr/local/llvm90/bin/ld" --eh-frame-hdr -Bshareable --hash-style=both --enable-new-dtags -o a.out /usr/lib/crti.o /usr/lib/crtbeginS.o -L/usr/lib /tmp/hello-abc422.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/crtendS.o /usr/lib/crtn.o

Again note the (almost) same dance with libgcc. I believe that this is the intended way to handle libgcc.

jhb added a comment.Jan 14 2020, 9:14 PM
In D23128#508092, @kib wrote:
In D23128#508062, @jhb wrote:

Oh, and @kib, you tested lang/gcc9, not the xtoolchain gcc that (freebsd-gcc9@amd64). Not sure then if lang/gcc9 has some local patch we need to apply to the other one. lang/gcc* don't work as system cross-compilers the way freebsd-gcc* do as they assume libstdc++ from the package and don't have kernel printf extensions, etc.

Yes, lang/gcc9. Why the listed extensions would matter for the discussed aspect of the spec file ?

They don't, but it's good to be testing the same thing that Jenkins and make tinderbox, etc. use. However, what probably matters for the specfile is that devel/freebsd-gcc* use '<arch>-unknown-freebsd<ver>' with a --build of '<arch>-portbld-ferebsd<ver>' so GCC still treats it as a cross-compiler in some ways since the strings don't match equally. lang/gcc9 use the same string for both and thus will be a native compiler. This has subtle impacts in various places in GCC, so it wouldn't surprise me if that somehow triggered different behavior here. For the purposes of using, say, mips-gcc6 on amd64, we want the cross-compile configuration to work, so using 'portbld' instead of 'unknown' in the freebsd-gcc* port isn't a viable fix anyway.

I agree that the compiler driver is what's broken and needs fixing, it will just take some time to figure out why and how to fix.