Bug 221423 - gcc std::locale(LocaleName) crashes instead of throwing an exception
Summary: gcc std::locale(LocaleName) crashes instead of throwing an exception
Status: New
Alias: None
Product: Ports & Packages
Classification: Unclassified
Component: Individual Port(s) (show other bugs)
Version: Latest
Hardware: Any Any
: --- Affects Many People
Assignee: freebsd-toolchain (Nobody)
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2017-08-11 19:29 UTC by Artyom Beilis
Modified: 2022-05-30 05:32 UTC (History)
8 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Artyom Beilis 2017-08-11 19:29:22 UTC
This simple program crashes "Abort trap (core dumped)" when it either expected to succeed or to catch an exception.


$ g++ -v
Using built-in specs.
COLLECT_GCC=g++
COLLECT_LTO_WRAPPER=/usr/local/libexec/gcc5/gcc/x86_64-portbld-freebsd11.0/5.4.0/lto-wrapper
Target: x86_64-portbld-freebsd11.0
Configured with: /wrkdirs/usr/ports/lang/gcc5/work/gcc-5.4.0/configure --with-build-config=bootstrap-debug --disable-nls --enable-gnu-indirect-function --libdir=/usr/local/lib/gcc5 --libexecdir=/usr/local/libexec/gcc5 --program-suffix=5 --with-as=/usr/local/bin/as --with-gmp=/usr/local --with-gxx-include-dir=/usr/local/lib/gcc5/include/c++/ --with-ld=/usr/local/bin/ld --with-pkgversion='FreeBSD Ports Collection' --with-system-zlib --with-ecj-jar=/usr/local/share/java/ecj-4.5.jar --enable-languages=c,c++,objc,fortran,java --prefix=/usr/local --localstatedir=/var --mandir=/usr/local/man --infodir=/usr/local/info/gcc5 --build=x86_64-portbld-freebsd11.0
Thread model: posix
gcc version 5.4.0 (FreeBSD Ports Collection) 

$ pkg info gcc
gcc-5.4.0_2
Name           : gcc
Version        : 5.4.0_2
Installed on   : Wed Aug  9 03:18:50 2017 IDT
Origin         : lang/gcc
Architecture   : FreeBSD:11:*
Prefix         : /usr/local
Categories     : lang java
Licenses       : 
Maintainer     : gerald@FreeBSD.org
WWW            : http://gcc.gnu.org
Comment        : Meta-port for the default version of the GNU Compiler Collection
Annotations    :
        repo_type      : binary
        repository     : FreeBSD
Flat size      : 17.0B
Description    :
GCC, the GNU Compiler Collection, supports a number of languages.  This
port pulls in gcc5 (or another version-specific port) and defines symlinks
called gcc, g++, and gfortran.

WWW: http://gcc.gnu.org

Gerald Pfeifer <gerald@FreeBSD.org>

$ uname -a
FreeBSD freebsd11 11.1-RELEASE FreeBSD 11.1-RELEASE #0 r321309: Fri Jul 21 02:08:28 UTC 2017     root@releng2.nyi.freebsd.org:/usr/obj/usr/src/sys/GENERIC  amd64


//////////////////

Code:


////////////


#include <iostream>
#include <locale>

int main()
{
        try {
                std::locale l = std::locale("en_US.UTF-8");
        }
        catch(std::exception const &e) {
                std::cerr << e.what() << std::endl;
        }
        catch(...) {
                std::cerr << "Unknown exception " << std::endl;
        }
}
Comment 1 Artyom Beilis 2017-08-11 19:37:59 UTC
For got to add building/running:

$ g++ test.cpp 
$ ./a.out 
Abort trap (core dumped)
Comment 2 Gerald Pfeifer freebsd_committer freebsd_triage 2017-08-11 21:31:44 UTC
Might this be related to what was just discussed a few days ago
(related to libsupc++ vs libcxxrt) in PR 221288?
Comment 3 Mark Millard 2017-08-11 22:44:58 UTC
(In reply to Artyom Beilis from comment #1)

The compile/link command did not specify:

-Wl,-rpath=/usr/local/lib/gcc5

and so is likely to get more of a mix of
system and gcc libraries than gcc5 is designed
for.

(That command line option above has details
that assume typical placements of files.)

A from source build of lang/gcc5 reports the
need for such options.
Comment 4 Mark Millard 2017-08-11 22:46:45 UTC
(In reply to Mark Millard from comment #3)

You can use ldd on the a,out after each type
of link to see the different bindings.
Comment 5 Jan Beich freebsd_committer freebsd_triage 2017-08-15 17:23:24 UTC
Can you confirm the issue doesn't affect lang/gcc6 and lang/gcc7? The default is going to change soon per bug 219275.

I can reproduce in a pristine jail with nothing but gcc5 installed. gcc49, gcc48, gcc47, gcc46 are also affected.

(In reply to Mark Millard from comment #3)
> The compile/link command did not specify: -Wl,-rpath=...

Maybe -Wl,-rpath should be added to the specfile instead of relying on ldconfig hints roulette. Not having sane defaults is a bug.

(In reply to Mark Millard from comment #3)
> mix of system and gcc libraries than gcc5

Tier1 and some Tier2 archs don't have system GCC anymore. It's enough to install more than one lang/gcc* to get ambiguity about libstdc++ et al.
Comment 6 Mark Millard 2017-08-15 19:09:45 UTC
(In reply to Jan Beich from comment #5)

>(In reply to Mark Millard from comment #3)
>> mix of system and gcc libraries than gcc5
>
>Tier1 and some Tier2 archs don't have system GCC anymore. It's enough to install more
>than one lang/gcc* to get ambiguity about libstdc++ et al.

There are still system libraries that are ambiguously
bound to when the system has no gcc of its own. Use
of:

-Wl,-rpath=/usr/local/lib/gcc<?>

for the appropriate <?> prevents that. For example:

       libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800fbd000)
vs.
       libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x800e06000)

But there is also the lack of:

       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)

when -Wl,-rpath=/usr/local/lib/gcc<?> is used.

This can interact badly with binding to:

       libthr.so.3 => /lib/libthr.so.3 (0x8011d3000)

since libthr was built based on the context for:

       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)

and not the implicit material in libstdc++. See
bugzilla 221423.

For reference:

g++6 -std=c++14 -Wpedantic -Wall -pthread -Wl,-rpath=/usr/local/lib/gcc6 -O2
cpp_clocks_investigation.cpp

# ldd a.out
a.out:
       libstdc++.so.6 => /usr/local/lib/gcc6/libstdc++.so.6 (0x800844000)
       libm.so.5 => /lib/libm.so.5 (0x800bd9000)
       libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x800e06000)
       libthr.so.3 => /lib/libthr.so.3 (0x80101d000)
       libc.so.7 => /lib/libc.so.7 (0x801245000)

and the result has crash problems from the
odd mix of libstdc++ supplying what would be
used from libcxxrt inlibthr. (FYI:
cpp_clocks_investigation.cpp is pure
standard C++ code.)

(I did not notice libthr using libgcc_s but if it
did then it is the same sort of problem as for
libstdc++ providing when the system libcxxrt
would provide.)

By contrast:

clang++ -std=c++14 -Wpedantic -Wall -pthread cpp_clocks_investigation.cpp 

# ldd a.out
a.out:
       libc++.so.1 => /usr/lib/libc++.so.1 (0x8008a6000)
       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)
       libm.so.5 => /lib/libm.so.5 (0x800d90000)
       libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800fbd000)
       libthr.so.3 => /lib/libthr.so.3 (0x8011d3000)
       libc.so.7 => /lib/libc.so.7 (0x8013fb000)

works fine and libthr has libcxxrt to bind to (and
the system libgcc_s if libthr has any binding to
there).


Separately from the above:

-Wl,-rpath=/usr/local/lib/gcc<?>

also disambiguates when having multiple lang/gcc* 's
installed. But this type of context is not required
for there to be binding problems.
Comment 7 Mark Millard 2017-08-15 19:32:01 UTC
(In reply to Mark Millard from comment #6)

Dumb typo. Wrong:

See bugzilla 221423.

Should have been:

See bugzilla 221288 .
Comment 8 Mark Millard 2017-08-15 22:22:52 UTC
(In reply to Jan Beich from comment #5)

> Can you confirm the issue doesn't affect lang/gcc6 and lang/gcc7?
> The default is going to change soon per bug 219275.

I'm not sure which issue(s)/aspect(s) you are after,
so I pick the following to try to answer.

I strongly expect that an ldd on the original
context that was using std::locale(LocaleName)
would show something implying a mix of system
and gcc original definitions, where at run-time
a specific binding ends up being made. (But no
one has posted such ldd output for the failing
context(s).)

I expect that what is required is producing the
program and libraries it is bound to such that
that they avoid the mix and bind at run time to
the same implementation related materials as
they all were built with.

I expect that such applies to all lang/gcc*
examples, including gcc6 and gcc7 and the
older gcc5 (and before).

This hole area of bindings is a mess. Progressing
from gccN to gcc <N+1> is an example were if

-Wl,-rpath=/usr/local/lib/gccN

was used then it looks explicitly for files from:

/usr/local/lib/gccN/

and if lang/gccN is uninstalled they will not be
there to be found. It takes a rebuild or other
form of forced redirection to have it try looking
in:

/usr/local/lib/gcc<N+1>/

instead. Even if it looks and finds a binding in
the new place it can try to use, the behavior need
not be compatible once bound.

Some types of system have a means of leaving the
libraries around for binding even when the compiler
and such is no long around for the version in
question.

Without -Wl,-rpath=/usr/local/lib/gccN involved
there are other issues. But sometimes the binding
that results happens to work better than does with
-rpath in use (since other libraries involved
were not set up for the -rpath libraries but,
say, system ones).

I'm not sure there is a universal, fixed answer to
which binding is better for the likes of (gcc6
example):

       libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800fbd000)
vs.
       libgcc_s.so.1 => /usr/local/lib/gcc6/libgcc_s.so.1 (0x800e06000)

but as things are the run-time binding is
controlled via use or not of the:

-Wl,-rpath=/usr/local/lib/gccN

Any set of libraries that is put to use in a program
but that ends up being originally based overall on a
mix of the two bindings (build time) is likely to end
up being a problem combination when one implementation
is actually bound.

However, as I understand it, that option does not
determine the use or not of the likes of:

       libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b72000)

because a bunch of those bindings can instead be
found from the likes of:

       libstdc++.so.6 => /usr/local/lib/gcc6/libstdc++.so.6 (0x800844000)

if it is involved, even without a -rpath in the link.

Again a set of libraries used in a program but
that mix the original contexts is likely to
end up being a problem combination. (The
program needs to match as well.)

It appears that avoiding mixes is generally
(but not universally?) required (both for
libgcc_s alternative and for libcxxrt vs.
implicit in libstdc++ ).

In case an example makes it clearer:

For my libthr example: It appears to me that a program
using libstdc++ itself or in libraries would need a
libthr equivalent that had also been built based on
libstdc++ as libstdc++ is now constructed. Similarly
for any libgcc_s use by the libthr equivalent.

An alternate would be a libstdc++ that was built based
on the system libgcc_s and libcxxrt and so that libstdc++
did not provide various bindings to gcc specifics that
libstdc++ now does --and there would be no gcc based
libgcc_s in use. As I understand g++ and libstdc++ is
not designed for this sort of structure.
Comment 9 Mark Millard 2017-08-16 03:42:56 UTC
Here are lang/gcc7 and system clang compile/link results as viewed
by ldd (all under head -r322287 in a Virtual Box virtual machine):
things look good until I try my threading example. Then one
combination fails (the -rpath one!).

# g++7 -std=c++14 -Wpedantic -Wall -Wl,-rpath=/usr/local/lib/gcc7 -O2 locale_failure_test.cc

# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800824000)
	libm.so.5 => /lib/libm.so.5 (0x800bb8000)
	libgcc_s.so.1 => /usr/local/lib/gcc7/libgcc_s.so.1 (0x800de5000)
	libc.so.7 => /lib/libc.so.7 (0x800ffc000)

# ./a.out

Note: The above did not crash but had no output.

# g++7 -std=c++14 -Wpedantic -Wall -O2 locale_failure_test.cc

# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800824000)
	libm.so.5 => /lib/libm.so.5 (0x800bb8000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800de5000)
	libc.so.7 => /lib/libc.so.7 (0x800ffb000)

# ./a.out

Note: The above did not crash but had no output.

# clang++ -std=c++14 -Wpedantic -Wall -O2 locale_failure_test.cc

# ldd a.out
a.out:
	libc++.so.1 => /usr/lib/libc++.so.1 (0x800824000)
	libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800af0000)
	libm.so.5 => /lib/libm.so.5 (0x800d0e000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800f3b000)
	libc.so.7 => /lib/libc.so.7 (0x801151000)

# ./a.out

Note: The above did not crash but had no output.


Replacing the locale line with:

                std::locale l = std::locale("NOSUCH::en_US.UTF-8");
 
# g++7 -std=c++14 -Wpedantic -Wall -Wl,-rpath=/usr/local/lib/gcc7 -O2 locale_failure_test.cc

# ./a.out
locale::facet::_S_create_c_locale name not valid

# g++7 -std=c++14 -Wpedantic -Wall -O2 locale_failure_test.cc

# ./a.out
locale::facet::_S_create_c_locale name not valid

# ./a.out
collate_byname<char>::collate_byname failed to construct for NOSUCH::en_US.UTF-8

So no exception was thrown in any of the examples and the
code did not fail.


Trying instead:

# more exception_test.cc
#include <exception>

int main(void)
{
    try { throw std::exception(); }
    catch (std::exception& e) {}
    return 0;
}

# g++7 -std=c++14 -Wpedantic -Wall -Wl,-rpath=/usr/local/lib/gcc7 -O2 exception_test.cc

# ./a.out

# g++7 -std=c++14 -Wpedantic -Wall -O2 exception_test.cc

# ./a.out

# clang++ -std=c++14 -Wpedantic -Wall -O2 exception_test.cc

# ./a.out


So none of them fail.

But trying my standard-C++ program that uses C++ threads:

# g++7 -std=c++14 -Wpedantic -Wall -pthread -Wl,-rpath=/usr/local/lib/gcc7 -O2 cpp_clocks_investigation.cpp

# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800844000)
	libm.so.5 => /lib/libm.so.5 (0x800bd8000)
	libgcc_s.so.1 => /usr/local/lib/gcc7/libgcc_s.so.1 (0x800e05000)
	libthr.so.3 => /lib/libthr.so.3 (0x80101c000)
	libc.so.7 => /lib/libc.so.7 (0x801244000)

# ./a.out
. . . (omitted) . . .
Segmentation fault (core dumped)

# g++7 -std=c++14 -Wpedantic -Wall -pthread -O2 cpp_clocks_investigation.cpp# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc7/libstdc++.so.6 (0x800844000)
	libm.so.5 => /lib/libm.so.5 (0x800bd8000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800e05000)
	libthr.so.3 => /lib/libthr.so.3 (0x80101b000)
	libc.so.7 => /lib/libc.so.7 (0x801243000)

# ./a.out
. . . (omitted) . . .
End of clock tests.

So it worked for /lib/libgcc_s.so.1 but not for /usr/local/lib/gcc7/libgcc_s.so.1
and I must have been wrong about /lib/libcxxrt.so.1 being what mattered.

This threading example is a context where -Wl,-rpath=/usr/local/lib/gcc7
prevents correct operation because of cross library dependencies on
implementation details of the build-time context vs. the mismatched
runtime context for libthr.so.3 vs. libgcc_s.so.1 .


# clang++ -std=c++14 -Wpedantic -Wall -pthread -O2 cpp_clocks_investigation.cpp

# ldd a.out
a.out:
	libc++.so.1 => /usr/lib/libc++.so.1 (0x800844000)
	libcxxrt.so.1 => /lib/libcxxrt.so.1 (0x800b10000)
	libm.so.5 => /lib/libm.so.5 (0x800d2e000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800f5b000)
	libthr.so.3 => /lib/libthr.so.3 (0x801171000)
	libc.so.7 => /lib/libc.so.7 (0x801399000)

# ./a.out
. . . (omitted) . . .
End of clock tests.

So this also worked. Again /lib/libthr.so.3 and /lib/libgcc_s.so.1
go together just fine.
Comment 10 Walter Schwarzenfeld freebsd_triage 2019-08-07 22:57:45 UTC
Is this still relevant?
Comment 11 Mark Millard 2019-08-07 23:42:24 UTC
(In reply to w.schwarzenfeld from comment #10)

Well, I tried one of my old failing examples, but for
more recent g++ vintages (8 and 9) in a more recent
amd64 head release ( -r350364 ) and the failure did
not happen . . .

# g++8 -std=c++17 -Wpedantic -Wall -pthread -Wl,-rpath=/usr/local/lib/gcc8 -O2 cpp_clocks_investigation.cpp
# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc8/libstdc++.so.6 (0x800661000)
	libm.so.5 => /lib/libm.so.5 (0x8009f5000)
	libgcc_s.so.1 => /usr/local/lib/gcc8/libgcc_s.so.1 (0x800a27000)
	libthr.so.3 => /lib/libthr.so.3 (0x800c3e000)
	libc.so.7 => /lib/libc.so.7 (0x800c6b000)
# ./a.out
. . .

# g++9 -std=c++17 -Wpedantic -Wall -pthread -Wl,-rpath=/usr/local/lib/gcc9 -O2 cpp_clocks_investigation.cpp
# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc9/libstdc++.so.6 (0x800663000)
	libm.so.5 => /lib/libm.so.5 (0x800a54000)
	libgcc_s.so.1 => /usr/local/lib/gcc9/libgcc_s.so.1 (0x800a86000)
	libthr.so.3 => /lib/libthr.so.3 (0x800c9d000)
	libc.so.7 => /lib/libc.so.7 (0x800cca000)
# ./a.out
. . .

Both of those worked: no "Segmentation fault (core dumped)".

Like earlier for g++7, locale_failure_test.cc did not fail
either.


I've no 11.x or 12.x context around to test. Being based only
on head, this might not be enough evidence to close the submittal.
Comment 12 Jan Beich freebsd_committer freebsd_triage 2019-08-11 03:41:00 UTC
(In reply to Walter Schwarzenfeld from comment #10)
> Is this still relevant?

std::locale test still fails on GCC < 6. As lang/gcc (i.e., g++ symlink) abides by GCC_DEFAULT it's not an issue since bug 219275.

$ pkg install gcc48 gcc5 gcc6 gcc7 gcc8 gcc9
$ g++9 -Wl,-rpath=/usr/local/lib/gcc9 test.cpp
$ ./a.out
$ g++8 -Wl,-rpath=/usr/local/lib/gcc8 test.cpp
$ ./a.out
$ g++7 -Wl,-rpath=/usr/local/lib/gcc7 test.cpp
$ ./a.out
$ g++6 -Wl,-rpath=/usr/local/lib/gcc6 test.cpp
$ ./a.out
$ g++5 -Wl,-rpath=/usr/local/lib/gcc5 test.cpp
$./a.out
locale::facet::_S_create_c_locale name not valid
$ g++48 -Wl,-rpath=/usr/local/lib/gcc48 test.cpp
$ ./a.out
locale::facet::_S_create_c_locale name not valid
$ g++42 test.cpp
$ ./a.out
locale::facet::_S_create_c_locale name not valid

As for ABI mismatch between g++ and libstdc++ when -Wl,-rpath is not passed and more than one lang/gcc* is installed it doesn't seem to crash on FreeBSD 11.3 or later.

$ uname -rp
11.2-RELEASE amd64
$ pkg install gcc48 gcc5 gcc6 gcc7 gcc8 gcc9
$ g++9 test.cpp
$ ./a.out
Abort trap
$ ldd ./a.out
./a.out:
        libstdc++.so.6 => /usr/local/lib/gcc48/libstdc++.so.6 (0x800822000)
        libm.so.5 => /lib/libm.so.5 (0x800b29000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x800d56000)
        libc.so.7 => /lib/libc.so.7 (0x800f65000)
Comment 13 Daniel Engberg freebsd_committer freebsd_triage 2022-03-26 15:48:32 UTC
I guess we can close this one now as lang/gcc48 is listed as deprecated?
Comment 14 Gerald Pfeifer freebsd_committer freebsd_triage 2022-04-07 10:03:03 UTC
I'd try with current versions of the lang/gcc* ports. This might still 
reproduce, if I'm right.
Comment 15 Dimitry Andric freebsd_committer freebsd_triage 2022-04-07 14:36:12 UTC
(In reply to Gerald Pfeifer from comment #14)
There's something in the ports gccs that makes them all link automatically to /usr/local/lib/gcc10/libstdc++.so.6:

% for i in 8 9 10 11; do g++$i bug22143.cpp -o bug221423-gcc$i; done
% for i in 8 9 10 11; do ldd ./bug221423-gcc$i; done
./bug221423-gcc8:
        libstdc++.so.6 => /usr/local/lib/gcc10/libstdc++.so.6 (0x821663000)
        libm.so.5 => /lib/libm.so.5 (0x8226cc000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x823302000)
        libc.so.7 => /lib/libc.so.7 (0x8245ed000)
./bug221423-gcc9:
        libstdc++.so.6 => /usr/local/lib/gcc10/libstdc++.so.6 (0x822cd3000)
        libm.so.5 => /lib/libm.so.5 (0x8218a1000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x822089000)
        libc.so.7 => /lib/libc.so.7 (0x823e62000)
./bug221423-gcc10:
        libstdc++.so.6 => /usr/local/lib/gcc10/libstdc++.so.6 (0x82206e000)
        libm.so.5 => /lib/libm.so.5 (0x823de2000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x822ec6000)
        libc.so.7 => /lib/libc.so.7 (0x8246c0000)
./bug221423-gcc11:
        libstdc++.so.6 => /usr/local/lib/gcc10/libstdc++.so.6 (0x821ed0000)
        libm.so.5 => /lib/libm.so.5 (0x82176b000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x8229b1000)
        libc.so.7 => /lib/libc.so.7 (0x822ad4000)

I don't have to pass any rpath options, something implicitly stuffs in the gcc10 libdstdc++.so.

And none of the executables crash here... FreeBSD 14-CURRENT as of ~2022-03-31.
Comment 16 Dimitry Andric freebsd_committer freebsd_triage 2022-04-07 15:05:24 UTC
Freshly build and installed the gcc48 port, same results, no crash:

% g++48 bug221423.cpp -o bug221423-gcc48

% ./bug221423-gcc48

% echo $?
0

% ldd bug221423-gcc48
bug221423-gcc48:
        libstdc++.so.6 => /usr/local/lib/gcc10/libstdc++.so.6 (0x822954000)
        libm.so.5 => /lib/libm.so.5 (0x821edc000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x823a5d000)
        libc.so.7 => /lib/libc.so.7 (0x823f91000)
Comment 17 Mark Millard 2022-04-07 16:10:56 UTC
I do not have gcc10 installed. In my context a.out will not even run:

# g++11 locale_failure_test.cpp
# ./a.out
ld-elf.so.1: /lib/libgcc_s.so.1: version GCC_4.5.0 required by /usr/local/lib/gcc11/libstdc++.so.6 not found
# ldd a.out
a.out:
        libstdc++.so.6 => /usr/local/lib/gcc11/libstdc++.so.6 (0x82400000)
        libm.so.5 => /lib/libm.so.5 (0x81411000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x82b01000)
        libc.so.7 => /lib/libc.so.7 (0x8376e000)

# uname -apKU
FreeBSD CA72_16Gp_ZFS 14.0-CURRENT FreeBSD 14.0-CURRENT #40
main-n253904-4d1ba6febfa7-dirty: Tue Mar 22 20:52:57 PDT 2022
root@CA72_16Gp_ZFS:/usr/obj/BUILDs/main-CA72-nodbg-clang/usr/main-src/arm64.aarch64/sys/GENERIC-NODBG-CA72
arm64 aarch64 1400053 1400053

(Line split for readability.)
Comment 18 Mark Millard 2022-04-07 16:16:57 UTC
(In reply to Mark Millard from comment #17)

In my amd64 context (instead of aarch64) it runs and is silent:

# g++11 locale_failure_test.cpp 
# ./a.out
# ldd a.out
a.out:
	libstdc++.so.6 => /usr/local/lib/gcc11/libstdc++.so.6 (0x824200000)
	libm.so.5 => /lib/libm.so.5 (0x822040000)
	libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x82238a000)
	libc.so.7 => /lib/libc.so.7 (0x822ad5000)
# uname -apKU
FreeBSD amd64_ZFS 14.0-CURRENT FreeBSD 14.0-CURRENT #33
main-n253904-4d1ba6febfa7-dirty: Tue Mar 22 21:12:26 PDT 2022
root@amd64_ZFS:/usr/obj/BUILDs/main-amd64-nodbg-clang/usr/main-src/amd64.amd64/sys/GENERIC-NODBG
amd64 amd64 1400053 1400053
Comment 19 Mark Millard 2022-04-07 16:33:32 UTC
(In reply to Mark Millard from comment #17)

Back to aarch64:

# g++11 -Wl,-rpath=/usr/local/lib/gcc11 locale_failure_test.cpp
# ./a.out
# ldd a.out
a.out:
        libstdc++.so.6 => /usr/local/lib/gcc11/libstdc++.so.6 (0x83400000)
        libm.so.5 => /lib/libm.so.5 (0x81a6f000)
        libgcc_s.so.1 => /usr/local/lib/gcc11/libgcc_s.so.1 (0x8265c000)
        libc.so.7 => /lib/libc.so.7 (0x83fbe000)

So use of -Wl,-rpath=/usr/local/lib/gcc11 makes things coherent in
my aarch64 context.
Comment 20 Mark Millard 2022-04-07 16:44:14 UTC
(In reply to Mark Millard from comment #18)

My armv7 chroot context on the aarch64 system worked like amd64:

# g++11 locale_failure_test.cpp
# ./a.out
# ldd ./a.out
./a.out:
        libstdc++.so.6 => /usr/local/lib/gcc11/libstdc++.so.6 (0x4008e000)
        libm.so.5 => /lib/libm.so.5 (0x40267000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x402b6000)
        libc.so.7 => /lib/libc.so.7 (0x402f0000)

So the "version GCC_4.5.0 required by" type of issue seems to be
platform specific.

I do not have powerpc* contexts to test any more.
Comment 21 Konstantin Belousov freebsd_committer freebsd_triage 2022-04-07 16:57:57 UTC
It is not platform-specific.  The magic is in
/usr/local/libdata/ldconfig/gcc<version>
and somewhat randomly depends on the order of directorires as applied by
`for i in ${ldconfig_local_dirs}; do ...` loop in /etc/rc.d/ldconfig script.

Ideally, because gcc project takes backward ABI compatibility quite seriously,
only gcc<highest version> file from libdata/ldconfig directory should be
applied.  I have no idea how to do that idiomatically.
Comment 22 Mark Millard 2022-04-07 17:19:52 UTC
(In reply to Konstantin Belousov from comment #21)

FYI:

All 3 of my environments have only one gcc* installed: gcc11 .
All get the same for:

# more /usr/local/libdata/ldconfig/gcc11
/usr/local/lib/gcc11

The variation that I showed must not be tied to the content of
that file.
Comment 23 Mark Millard 2022-04-07 17:31:20 UTC
(In reply to Mark Millard from comment #22)

Looks to me like my aarch64 and armv7 contexts have exact matches
for the ELF ldconfig path . . .

aarch64:
ELF ldconfig path: /lib /usr/lib /usr/lib/compat /usr/local/lib /usr/local/lib/compat/pkg /usr/local/lib/compat/pkg /usr/local/lib/gcc11 /usr/local/lib/perl5/5.32/mach/CORE /usr/local/lib/qt5 /usr/local/llvm12/lib /usr/local/llvm13/lib /usr/local/llvm14/lib

armv7:
ELF ldconfig path: /lib /usr/lib /usr/lib/compat /usr/local/lib /usr/local/lib/compat/pkg /usr/local/lib/compat/pkg /usr/local/lib/gcc11 /usr/local/lib/perl5/5.32/mach/CORE /usr/local/lib/qt5 /usr/local/llvm12/lib /usr/local/llvm13/lib /usr/local/llvm14/lib

amd64:
ELF ldconfig path: /lib /usr/lib /usr/lib/compat /usr/local/lib /usr/local/lib/compat/pkg /usr/local/lib/compat/pkg /usr/local/lib/e2fsprogs /usr/local/lib/gcc11 /usr/local/lib/perl5/5.32/mach/CORE /usr/local/lib/qt5 /usr/local/llvm12/lib /usr/local/llvm13/lib

amd64 is different.
Comment 24 Konstantin Belousov freebsd_committer freebsd_triage 2022-04-07 17:39:07 UTC
Search for all libstdc++.so.6 files on your machines, then see which one is
loaded where.
Comment 25 Mark Millard 2022-04-07 18:25:45 UTC
(In reply to Mark Millard from comment #23)

While I do not see the gcc11 as having oddities for
ldconfig, I do see the likes of ( the 3 ones with multiple
alternatives are shown, as id -lclang.12 ):

# egrep '(lssp|lgcc_s|lclang\.)' ~/ldconfig-r-output.txt | more
        26:-lssp.0 => /lib/libssp.so.0
        35:-lgcc_s.1 => /lib/libgcc_s.so.1
        516:-lssp.0 => /usr/local/lib/gcc11/libssp.so.0
        522:-lgcc_s.1 => /usr/local/lib/gcc11/libgcc_s.so.1
        554:-lclang.12 => /usr/local/llvm12/lib/libclang.so.12
        559:-lclang.13 => /usr/local/llvm13/lib/libclang.so.13
        569:-lclang.13 => /usr/local/llvm14/lib/libclang.so.13

So no -lclang.14 (the more recently installed) and two -lclang.13 listings.
Comment 26 Mark Millard 2022-04-07 18:31:55 UTC
(In reply to Konstantin Belousov from comment #24)

On the aarch64 machine that also has the armv7 chroot area:

# find / -name libstdc++.so.6 -print | more
/usr/obj/DESTDIRs/main-CA53-chroot/usr/local/lib/gcc11/libstdc++.so.6
/usr/obj/DESTDIRs/main-CA72-chroot/usr/local/lib/gcc11/libstdc++.so.6
/usr/obj/DESTDIRs/main-CA7-chroot/usr/local/lib/gcc11/libstdc++.so.6
/usr/local/lib/gcc11/libstdc++.so.6

Effectively there is only one libstdc++.so.6 outside the chroot trees and
only one in each chroot tree.

The ldconfig -r output in the contexts shows no examples of cross-tree
references.
Comment 27 Mark Millard 2022-04-07 19:34:14 UTC
(In reply to Mark Millard from comment #25)

Going along with the 2 -lclang.13 's is:

# ls -Tld /usr/local/llvm14/lib/libclang.so*
lrwxr-xr-x  1 root  wheel        14 Mar 22 01:40:38 2022 /usr/local/llvm14/lib/libclang.so -> libclang.so.13
lrwxr-xr-x  1 root  wheel        18 Mar 22 01:40:38 2022 /usr/local/llvm14/lib/libclang.so.13 -> libclang.so.14.0.0
-rwxr-xr-x  1 root  wheel  26767664 Mar 22 01:40:38 2022 /usr/local/llvm14/lib/libclang.so.14.0.0

So llvm14 has a libclang.so.13 -> libclang.so.14.0.0
and a libclang.so -> libclang.so.13 for some reason.
Comment 28 Mark Millard 2022-04-07 20:29:54 UTC
(In reply to Konstantin Belousov from comment #24)

I see searching on the web that ampere1's aarch64 port
builds have failures for the "version GCC_4.5.0 required
by" type of issue. An example I ran into was a log file
from back in Jan:

http://ampere1.nyi.freebsd.org/data/130arm64-default/7201e24c4c91/logs/fluxengine-572.log

So looking at a build that is ongoing right now:

http://ampere1.nyi.freebsd.org/data/130arm64-quarterly/1085d041ce12/logs/errors/fluxengine-572.log

also failed for the  same reason.

So nothing is unique to my environment and official build
servers had (or still have?) the "version GCC_4.5.0
required by" issue.
Comment 29 Mark Millard 2022-04-07 20:33:51 UTC
(In reply to Mark Millard from comment #28)

Sorry: Still have.

I forgot to correct that part of the wording after checking an
ongoing bulk build. (Distracted.)
Comment 30 Mark Millard 2022-04-07 20:50:36 UTC
(In reply to Mark Millard from comment #27)

Turns out that there is:

https://github.com/llvm/llvm-project/issues/54004

reporting the issue for llvm14 vs. using 13 in the
.so.VER naming:

QUOTE
Seen in conda-forge/clangdev-feedstock#165, where we explicitly test for presence of libclang.so.<major_ver> in the installed environment. Turns out, that libclang.so.14.0.0 is created, but not the symlink to libclang.so.14:

-- Installing: /home/conda/feedstock_root/build_artifacts/[...]/lib/libclang.so.14.0.0
-- Installing: /home/conda/feedstock_root/build_artifacts/[...]/lib/libclang.so.13
-- Installing: /home/conda/feedstock_root/build_artifacts/[...]/lib/libclang.so
END QUOTE

but . . .

QUOTE
This is expected. libclang.so ABI usually stays stable across major releases, so we've frozen the soname at libclang.so.13. The plan is to keep it with this name unless the ABI changes.
END QUOTE

There is more to the exchange but I'll stop quoting here.
Comment 31 Mark Millard 2022-04-08 00:24:24 UTC
(In reply to Mark Millard from comment #28)

I will note that fluxengine building for aarch64 on the FreeBSD servers
gets the "version GCC_4.5.0 required by" errors from using gcc10 instead
of gcc11 .

So the issue spans some range of gcc versions, not just gcc11 .
Comment 32 Mark Millard 2022-04-08 01:03:30 UTC
(In reply to Mark Millard from comment #17)

The following seem to explain the:

ld-elf.so.1: /lib/libgcc_s.so.1: version GCC_4.5.0 required by /usr/local/lib/gcc11/libstdc++.so.6

On aarch64 there is such a reference involved:

# nm -a /usr/local/lib/gcc11/libstdc++.so.6 | grep @GCC_4
                 U _Unwind_GetIPInfo@GCC_4.2.0
                 U __floatunditf@GCC_4.2.0
                 U __unordtf2@GCC_4.5.0

The fluxengine examples indicate that other code generation can
also produce @GCC_4.5.0 references in other files. I've not
checked if it is only __unordtf2 that is referenced.
Comment 33 Mark Millard 2022-04-08 01:28:23 UTC
(In reply to Mark Millard from comment #32)

The 2nd symbol is also not used by amd64 or armv7 libstdc++.so.6
and so seems (somewhat?) unique to aarch64 for the libstdc++.so.6
usage context:

                 U __floatunditf@GCC_4.2.0

(I've no powerpc* environment access these days and so do not
test that kind of context.)
Comment 34 Mark Millard 2022-04-08 20:51:34 UTC
(In reply to Konstantin Belousov from comment #24)

The following 6 line c++ program is sufficient to demonstrate
the __unordtf2@GCC_4.5.0 binding failure when targeting
aarch64:

# more fp-binding-failure-aarch64.cpp
#include <cmath>
volatile long double v=NAN;
int main()
{
    return std::isnan(v) ? 1 : 0;
}

# g++11 fp-binding-failure-aarch64.cpp
# ./a.out
ld-elf.so.1: /lib/libgcc_s.so.1: version GCC_4.5.0 required by /usr/home/root/c_tests/a.out not found

Note that the complaint is not about a reference in
/usr/local/lib/gcc11/libstdc++.so.6 but about the
a.out that has its own reference to __unordtf2@GCC_4.5.0 :

# nm -a a.out | grep '@GCC_[4-9]\.' | more
                 U __unordtf2@GCC_4.5.0

For reference . . .

# ldd a.out
a.out:
        libstdc++.so.6 => /usr/local/lib/gcc11/libstdc++.so.6 (0x83000000)
        libm.so.5 => /lib/libm.so.5 (0x81834000)
        libgcc_s.so.1 => /lib/libgcc_s.so.1 (0x8275a000)
        libc.so.7 => /lib/libc.so.7 (0x845f3000)
Comment 35 Mark Millard 2022-04-08 21:19:19 UTC
(In reply to Mark Millard from comment #34)

Below is a list of the differences in aarch64 for
GCC_ symbols between /usr/local/lib/gcc11/libgcc_s.so.1
and /lib/libgcc_s.so.1 . There are some GCC_4.7.0, GCC_7.0.0,
and GCC_11.0 examples, plus the various GCC_3* differences.

# objdump -T /usr/local/lib/gcc11/libgcc_s.so.1 | sort -k6 | grep GCC_ | cut -f6-7 -w > ~/gcc11_lbgcc_s_GCC_symbols.txt

# objdump -T /lib/libgcc_s.so.1 | sort -k6 | grep GCC_ | cut -f6-7 -w > ~/fbsd_main_lbgcc_s_GCC_symbols.txt

# diff -u ~/fbsd_main_lbgcc_s_GCC_symbols.txt ~/gcc11_lbgcc_s_GCC_symbols.txt | more
--- /usr/home/root/fbsd_main_lbgcc_s_GCC_symbols.txt    2022-04-08 14:09:15.865134000 -0700
+++ /usr/home/root/gcc11_lbgcc_s_GCC_symbols.txt        2022-04-08 14:09:00.966899000 -0700
@@ -1,3 +1,13 @@
+GCC_11.0       GCC_11.0
+GCC_11.0       __divhc3
+GCC_11.0       __extendhftf2
+GCC_11.0       __fixhfti
+GCC_11.0       __fixunshfti
+GCC_11.0       __floattihf
+GCC_11.0       __floatuntihf
+GCC_11.0       __mulhc3
+GCC_11.0       __trunctfhf2
+GCC_3.0        GCC_3.0
 GCC_3.0        _Unwind_DeleteException
 GCC_3.0        _Unwind_Find_FDE
 GCC_3.0        _Unwind_ForcedUnwind
@@ -13,130 +23,120 @@
 GCC_3.0        _Unwind_SetIP
 GCC_3.0        __absvdi2
 GCC_3.0        __absvsi2
+GCC_3.0        __addtf3
 GCC_3.0        __addvdi3
 GCC_3.0        __addvsi3
-GCC_3.0        __ashldi3
 GCC_3.0        __ashlti3
-GCC_3.0        __ashrdi3
 GCC_3.0        __ashrti3
 GCC_3.0        __clear_cache
-GCC_3.0        __cmpdi2
 GCC_3.0        __cmpti2
 GCC_3.0        __deregister_frame
-GCC_3.0        __divdi3
+GCC_3.0        __deregister_frame_info
+GCC_3.0        __deregister_frame_info_bases
+GCC_3.0        __divtf3
 GCC_3.0        __divti3
+GCC_3.0        __eqtf2
+GCC_3.0        __extenddftf2
+GCC_3.0        __extendsftf2
 GCC_3.0        __ffsdi2
 GCC_3.0        __ffsti2
-GCC_3.0        __fixdfdi
 GCC_3.0        __fixdfti
-GCC_3.0        __fixsfdi
 GCC_3.0        __fixsfti
+GCC_3.0        __fixtfdi
+GCC_3.0        __fixtfsi
+GCC_3.0        __fixtfti
 GCC_3.0        __fixunsdfdi
-GCC_3.0        __fixunsdfsi
 GCC_3.0        __fixunsdfti
 GCC_3.0        __fixunssfdi
-GCC_3.0        __fixunssfsi
 GCC_3.0        __fixunssfti
-GCC_3.0        __fixunsxfdi
-GCC_3.0        __fixunsxfsi
-GCC_3.0        __fixunsxfti
-GCC_3.0        __fixxfdi
-GCC_3.0        __fixxfti
-GCC_3.0        __floatdidf
-GCC_3.0        __floatdisf
-GCC_3.0        __floatdixf
+GCC_3.0        __fixunstfdi
+GCC_3.0        __fixunstfsi
+GCC_3.0        __fixunstfti
+GCC_3.0        __floatditf
+GCC_3.0        __floatsitf
 GCC_3.0        __floattidf
 GCC_3.0        __floattisf
-GCC_3.0        __floattixf
-GCC_3.0        __lshrdi3
+GCC_3.0        __floattitf
+GCC_3.0        __getf2
+GCC_3.0        __gttf2
+GCC_3.0        __letf2
 GCC_3.0        __lshrti3
-GCC_3.0        __moddi3
+GCC_3.0        __lttf2
 GCC_3.0        __modti3
-GCC_3.0        __muldi3
+GCC_3.0        __multf3
 GCC_3.0        __multi3
 GCC_3.0        __mulvdi3
 GCC_3.0        __mulvsi3
-GCC_3.0        __negdi2
+GCC_3.0        __negtf2
 GCC_3.0        __negti2
 GCC_3.0        __negvdi2
 GCC_3.0        __negvsi2
+GCC_3.0        __netf2
 GCC_3.0        __register_frame
+GCC_3.0        __register_frame_info
+GCC_3.0        __register_frame_info_bases
+GCC_3.0        __register_frame_info_table
+GCC_3.0        __register_frame_info_table_bases
+GCC_3.0        __register_frame_table
+GCC_3.0        __subtf3
 GCC_3.0        __subvdi3
 GCC_3.0        __subvsi3
-GCC_3.0        __ucmpdi2
+GCC_3.0        __trunctfdf2
+GCC_3.0        __trunctfsf2
 GCC_3.0        __ucmpti2
-GCC_3.0        __udivdi3
-GCC_3.0        __udivmoddi4
 GCC_3.0        __udivmodti4
 GCC_3.0        __udivti3
-GCC_3.0        __umoddi3
 GCC_3.0        __umodti3
+GCC_3.3        GCC_3.3
 GCC_3.3        _Unwind_Backtrace
 GCC_3.3        _Unwind_FindEnclosingFunction
 GCC_3.3        _Unwind_GetCFA
 GCC_3.3        _Unwind_Resume_or_Rethrow
+GCC_3.3.1      GCC_3.3.1
 GCC_3.3.1      __gcc_personality_v0
+GCC_3.4        GCC_3.4
 GCC_3.4        __clzdi2
-GCC_3.4        __clzsi2
 GCC_3.4        __clzti2
 GCC_3.4        __ctzdi2
-GCC_3.4        __ctzsi2
 GCC_3.4        __ctzti2
 GCC_3.4        __paritydi2
-GCC_3.4        __paritysi2
 GCC_3.4        __parityti2
 GCC_3.4        __popcountdi2
-GCC_3.4        __popcountsi2
 GCC_3.4        __popcountti2
+GCC_3.4.2      GCC_3.4.2
 GCC_3.4.2      __enable_execute_stack
+GCC_3.4.4      GCC_3.4.4
 GCC_3.4.4      __absvti2
 GCC_3.4.4      __addvti3
 GCC_3.4.4      __mulvti3
 GCC_3.4.4      __negvti2
 GCC_3.4.4      __subvti3
+GCC_4.0.0      GCC_4.0.0
 GCC_4.0.0      __divdc3
 GCC_4.0.0      __divsc3
-GCC_4.0.0      __divxc3
+GCC_4.0.0      __divtc3
 GCC_4.0.0      __muldc3
 GCC_4.0.0      __mulsc3
-GCC_4.0.0      __mulxc3
+GCC_4.0.0      __multc3
 GCC_4.0.0      __powidf2
 GCC_4.0.0      __powisf2
-GCC_4.0.0      __powixf2
+GCC_4.0.0      __powitf2
+GCC_4.2.0      GCC_4.2.0
 GCC_4.2.0      _Unwind_GetIPInfo
-GCC_4.2.0      __floatundidf
-GCC_4.2.0      __floatundisf
-GCC_4.2.0      __floatundixf
+GCC_4.2.0      __floatunditf
+GCC_4.2.0      __floatunsitf
 GCC_4.2.0      __floatuntidf
 GCC_4.2.0      __floatuntisf
-GCC_4.2.0      __floatuntixf
+GCC_4.2.0      __floatuntitf
+GCC_4.3.0      GCC_4.3.0
 GCC_4.3.0      __bswapdi2
 GCC_4.3.0      __bswapsi2
-GCC_4.6.0      __addtf3
-GCC_4.6.0      __cmptf2
-GCC_4.6.0      __divtf3
-GCC_4.6.0      __eqtf2
-GCC_4.6.0      __extenddftf2
-GCC_4.6.0      __extendsftf2
-GCC_4.6.0      __fixtfdi
-GCC_4.6.0      __fixtfsi
-GCC_4.6.0      __fixtfti
-GCC_4.6.0      __fixunstfdi
-GCC_4.6.0      __fixunstfsi
-GCC_4.6.0      __fixunstfti
-GCC_4.6.0      __floatditf
-GCC_4.6.0      __floatsitf
-GCC_4.6.0      __floattitf
-GCC_4.6.0      __floatunditf
-GCC_4.6.0      __floatunsitf
-GCC_4.6.0      __floatuntitf
-GCC_4.6.0      __getf2
-GCC_4.6.0      __gttf2
-GCC_4.6.0      __letf2
-GCC_4.6.0      __lttf2
-GCC_4.6.0      __multf3
-GCC_4.6.0      __netf2
-GCC_4.6.0      __subtf3
-GCC_4.6.0      __trunctfdf2
-GCC_4.6.0      __trunctfsf2
-GCC_4.6.0      __unordtf2
+GCC_4.3.0      __emutls_get_address
+GCC_4.3.0      __emutls_register_common
+GCC_4.5.0      GCC_4.5.0
+GCC_4.5.0      __unordtf2
+GCC_4.7.0      GCC_4.7.0
+GCC_4.7.0      __clrsbdi2
+GCC_4.7.0      __clrsbti2
+GCC_7.0.0      GCC_7.0.0
+GCC_7.0.0      __divmodti4

For reference (long line split for readability):

# uname -apKU
FreeBSD CA72_16Gp_ZFS 14.0-CURRENT FreeBSD 14.0-CURRENT #40
main-n253904-4d1ba6febfa7-dirty: Tue Mar 22 20:52:57 PDT 2022
root@CA72_16Gp_ZFS:/usr/obj/BUILDs/main-CA72-nodbg-clang/usr/main-src/arm64.aarch64/sys/GENERIC-NODBG-CA72
arm64 aarch64 1400053 1400053
Comment 36 Mark Millard 2022-04-09 00:35:57 UTC
(In reply to Mark Millard from comment #35)

I did similarly for amd64 and armv7 but I'll not show
the full diff's here.

An interesting point is amd64 vs. aarch64 for
/usr/local/lib/gcc11/libgcc_s.so.1 :

+GCC_4.6.0	__unordtf2
vs.
+GCC_4.5.0      __unordtf2

So the GCC_* vintage is architecture specific.

Also, armv7's /usr/local/lib/gcc11/libgcc_s.so.1
does not have __unordtf2 (or related) at all. Again,
architecture specific.

There are other significant differences in what is
present vs. absent in /usr/local/lib/gcc11/libgcc_s.so.1
across the 3 architectures.
Comment 37 Gerald Pfeifer freebsd_committer freebsd_triage 2022-05-30 05:32:24 UTC
(In reply to Konstantin Belousov from comment #21)
> Ideally, because gcc project takes backward ABI compatibility quite
> seriously, only gcc<highest version> file from libdata/ldconfig
> directory should be applied.

Agreed.

> I have no idea how to do that idiomatically.

What SUSE does with SUSE Linux Enterprise and openSUSE is to split the
compiler itself and this run-time into different packages.

The run-time then will be updated to a newer version somewhat regularly,
which works due to the focus on backwards compatibility by the upstream 
GCC project, the system compiler usually left in place (and still working
with the new run-time), and additional compiler versions added (and also
working with the new run-time.


In the context of FreeBSD, and ports, that would mean all GCC ports
sharing one run-time package coming from the latest stable version.

(Not something our packaging system supports very naturally.)