From Gentoo Wiki
Jump to:navigation Jump to:search

dev-libs/mpfr version 4 introduced an ABI and soname change that has the potential of breaking the compiler toolchain. In order to minimize potential problems it is strongly recommended to rebuild dev-libs/mpc and sys-devel/gcc immediately after mpfr.

The problem is used by (provided by dev-libs/mpc), as well as internal executables (e.g. cc1, cc1plus) of sys-devel/gcc. Appropriate subslots in mpfr and slot-operators in dependencies in mpc and gcc will cause a rebuild of mpc and gcc after an upgrade of mpfr.

However, after dev-libs/mpfr version 4 is installed and dev-libs/mpc rebuilt, but before sys-devel/gcc is rebuilt, the gcc compiler will be in an inconsistent state wherein symbols from incorrect library versions of mpfr might get used. This can result in segmentation faults and internal compiler errors. It is therefore important to rebuild gcc immmediately after mpc.

Preparatory steps

Make sure that you have enabled the "preserved libs" feature:

user $emerge --info | grep preserve-libs
FEATURES="... preserve-libs ..."

Detailed upgrade steps

Update and rebuild all affected packages as atomically as possible:

root #emerge --ask --oneshot ">=dev-libs/mpfr-4" dev-libs/mpc sys-devel/gcc

Check that cc1 is dynamically linked against the new mpfr version. First identify the absolute path of the cc1 executable by running

user $qlist gcc | grep -P "cc1$"

Then, use ldd to list all dynamically linked libraries:

user $ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr => /usr/lib64/ (0x00007fe37e9df000)

You might want to use this ldd invocation to list all dynamically linked libraries for any installed gcc compilers:

user $for i in /usr/libexec/gcc/*-pc-linux-gnu/*/cc1; do echo $i; ldd $i | grep mpfr ; done;
/usr/libexec/gcc/i686-pc-linux-gnu/6.4.0/cc1 => /usr/lib/ (0xf7747000)
/usr/libexec/gcc/i686-pc-linux-gnu/7.3.0/cc1 => /usr/lib/ (0xf7b70000)
/usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 => /usr/lib/ (0xf7797000)

You should only see and not the old in the output of ldd.


Mixed linkage

If the ldd command in the previous step returns two library versions,

user $ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr => /usr/lib64/ (0x00007fe37fa02000) => /usr/lib64/ (0x00007fe37e9df000)

You have rebuilt sys-libs/mpc against the new mpfr version, but not sys-devel/gcc (or vice versa). Rebuild the mpc library and the gcc executable immediately:

root #emerge --ask --oneshot dev-libs/mpc sys-devel/gcc

Warning about preserved libraries

If you get the following warning you had the preserve-libs feature disabled:

 * Messages for package dev-libs/mpfr-4.0.1:                                                                                                                                                   
 * Old versions of installed libraries were detected on your system.                                                                                                            
 * In order to avoid breaking packages that depend on these old libs,                                                 
 * the libraries are not being removed.  You need to run revdep-rebuild                                         
 * in order to remove these old dependencies.  If you do not have this                                        
 * helper program, simply emerge the 'gentoolkit' package.                                                               
 *   # revdep-rebuild --library '/usr/lib64/' && rm '/usr/lib64/

Follow above instructions immediately and check that the link interface is consistent before you remove the library. ldd must return exactly one mpfr library:

user $ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr => /usr/lib64/ (0x00007fe37e9df000)

Missing mpfr-4 library

If you encounter internal compiler errors of the form

/usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1plus: error while loading shared libraries: cannot open shared object file: No such file or directory

The library got removed before mpc and gcc had been both rebuilt. The preserve-libs feature and the manual check mentioned above should have prevented this.

There is a workaround to bring the system back into working order:

This is a very fragile workaround and only meant as last resort. Under normal circumstances, you should refrain from changing sonames in such manner.
root # ln -s /usr/lib64/ /usr/lib64/
root # emerge --ask --oneshot dev-libs/mpc sys-devel/gcc
root # rm /usr/lib64/
root # revdep-rebuild

Make sure that the link interface is consistent after above steps:

user $ldd /usr/libexec/gcc/x86_64-pc-linux-gnu/7.3.0/cc1 | grep mpfr => /usr/lib64/ (0x00007fe37e9df000)