Bug 37152 - Building shared libraries and PIEs with LTO is broken on mipsel
Summary: Building shared libraries and PIEs with LTO is broken on mipsel
Status: NEW
Alias: None
Product: Sisyphus
Classification: Development
Component: gcc8 (show other bugs)
Version: unstable
Hardware: mipsel Linux
: P3 normal
Assignee: Gleb F-Malinovskiy
QA Contact: qa-sisyphus
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2019-08-29 13:01 MSK by Ivan A. Melnikov
Modified: 2019-08-29 13:04 MSK (History)
3 users (show)

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Ivan A. Melnikov 2019-08-29 13:01:01 MSK
For a few moths we've seen problems with building packages that build shared libraries and/or position-independent executables with -flto on mipsel. Notable examples of such packages are systemd and python3. Here is an example of the failure from systemd build log:

[811/2091] Linking target src/udev/ata_id.
FAILED: src/udev/ata_id 
cc  -o src/udev/ata_id 'src/udev/3eb56e7@@ata_id@exe/ata_id_ata_id.c.o' -flto -Wl,--no-undefined -Wl,--as-needed -pie -Wl,-z,relro -Wl,-z,now -Wl,--gc-sections -pipe -frecord-gcc-switches -Wall -g -O2 -Wl,--start-group src/udev/libudev_static.a src/shared/libsystemd-shared-241.a src/libsystemd/libsystemd_static.a src/basic/libbasic.a src/udev/libudev-basic.a -lrt /usr/lib/gcc/mipsel-alt-linux/8/../../../../lib/libcap.so -lacl /usr/lib/gcc/mipsel-alt-linux/8/../../../../lib/libcryptsetup.so -lgcrypt /usr/lib/libip4tc.so /usr/lib/libip6tc.so -lkmod -lmount -lseccomp -lselinux -lidn2 -llzma -llz4 -lblkid -lrt -lselinux -lm -Wl,--end-group -pthread '-Wl,-rpath,$ORIGIN/:$ORIGIN/../shared:$ORIGIN/../libsystemd:$ORIGIN/../basic' -Wl,-rpath-link,/usr/src/RPM/BUILD/systemd-241/mipsel-alt-linux/src/udev:/usr/src/RPM/BUILD/systemd-241/mipsel-alt-linux/src/shared:/usr/src/RPM/BUILD/systemd-241/mipsel-alt-linux/src/libsystemd:/usr/src/RPM/BUILD/systemd-241/mipsel-alt-linux/src/basic  
collect2: fatal error: ld terminated with signal 11 [Segmentation fault]
compilation terminated.
/usr/bin/ld.default: /usr/src/tmp/ccXX2rYk.ltrans0.ltrans.o: relocation R_MIPS_HI16 against `a local symbol' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld.default: BFD (GNU Binutils) 2.31.1.20181202 assertion fail elfxx-mips.c:3566


With systemd, the problem first appeared at 241-alt1, when upstream stopped adding -fPIC to  CFLAGS relying on the corresponding meson functionality to do the right thing. With python3, the problem first noticed during transition from 3.6.x to 3.7.x -- 3.6.x was build without LTO.

Two workarounds are possible: either disabling LTO altogether (which we are mostly doing) or adding something like -fPIC to the linking command.
Comment 1 Ivan A. Melnikov 2019-08-29 13:02:36 MSK
It's not hard to reproduce the problem with a somewhat smaller example. Here is my take:

$ cat var.c

int helper_var = 42;

$ cat func.c

extern int helper_var;

int helper_func() {
    return helper_var;
}

$ gcc -flto -fPIC -O2 -g -c -o func.o func.c
$ gcc -flto -fPIC -O2 -g -c -o var.o var.c
$ gcc -flto -shared -o libhelper-lto.so func.o var.o
collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
compilation terminated.
/usr/bin/ld.default: /tmp/.private/iv/ccGL82XI.ltrans0.ltrans.o: relocation R_MIPS_HI16 against `__gnu_local_gp' can not be used when making a shared object; recompile with -fPIC
/usr/bin/ld.default: BFD (GNU Binutils) 2.31.1.20181202 assertion fail elfxx-mips.c:3566

Adding -fPIC or removing -flto to the last commend helps and produces a working shared library.
Comment 2 Ivan A. Melnikov 2019-08-29 13:03:11 MSK
With this example at hand, I was able to determine that the relocation in question is generated because -mno-shared is passed to collect2:

$ gcc -v -flto -shared -o libhelper-lto.so func.o var.o                                                                                                                                                                   
[... skipping the boring part ...]
COLLECT_GCC_OPTIONS='-v' '-flto' '-shared' '-o' 'libhelper-lto.so' '-march=mips32r2' '-mfpxx' '-mllsc' '-mno-lxc1-sxc1' '-mno-madd4' '-mips32r2' '-mno-shared' '-EL' '-mabi=32'
 /usr/libexec/gcc/mipsel-alt-linux/8/collect2 -plugin /usr/libexec/gcc/mipsel-alt-linux/8/liblto_plugin.so -plugin-opt=/usr/libexec/gcc/mipsel-alt-linux/8/lto-wrapper -plugin-opt=-fresolution=/tmp/.private/iv/ccgFMx4f.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 -flto --build-id --no-add-needed --eh-frame-hdr --as-needed -EL -mips32r2 -shared -melf32ltsmip 
-o libhelper-lto.so /usr/lib/gcc/mipsel-alt-linux/8/../../../../lib/crti.o /usr/lib/gcc/mipsel-alt-linux/8/crtbeginS.o -L/usr/lib/gcc/mipsel-alt-linux/8 -L/usr/lib/gcc/mipsel-alt-linux/8/../../../../lib -L/lib/../lib -L/usr/lib/../lib -L/us
r/lib/gcc/mipsel-alt-linux/8/../../.. func.o var.o -lgcc --push-state --as-needed -lgcc_s --pop-state -lc -lgcc --push-state --as-needed -lgcc_s --pop-state /usr/lib/gcc/mipsel-alt-linux/8/crtendS.o /usr/lib/gcc/mipsel-alt-linux/8/../../../
../lib/crtn.o
collect2: fatal error: ld terminated with signal 11 [Segmentation fault], core dumped
compilation terminated.
[...]

'-mno-shared'  is a mipsel-specific option that enables certain optimizations which are not valid for postion-independent code of any kind. It is added by the gcc driver as a part of DRIVER_SPECS (see NO_SHARED_SPECS) here:

http://git.altlinux.org/gears/g/gcc8.git?a=blob;f=gcc/gcc/config/mips/gnu-user.h;h=22097e285bf2645d0b96877fa1de17831b8cfde1#l103
Comment 3 Ivan A. Melnikov 2019-08-29 13:04:39 MSK
I'm not entirely convinced that this should not be addressed on the other side -- that is, by adding the required options to the linking commend. man gcc(1) for both -shared an -pie says:

> For predictable results, you must also specify the same set
> of options used for compilation (-fpie, -fPIE, or model suboptions)
> when you specify this linker option.

But I think that consistency across platforms is also valuable, so I'm suggesting the following patch:

http://git.altlinux.org/people/iv/packages/gcc8.git?a=blob;f=alt/alt-mips-shared-implies-mshared.patch;h=e853da1ee7c47037cf27a0cc60a25f949ac3ae1b

Here is the full change:

http://git.altlinux.org/people/iv/packages/gcc8.git?a=commitdiff;h=ce841dcf74343fd634b4308c2de7c8ea3a81024e

With this change, I can't reproduce the problem anymore, and gcc apparently build working systemd and python3 with LTO enabled (task #33910 on gyle-secondary).

Since the change entirely mips-specific, I think we can safely add it to gcc8 in Sisyphus. I can create a task. WDYT?