qboot fails to build with LTO enabled - redundant addr32 prefix
Hi,
I've found the following in a recent Ubuntu build and reproduced it on plain qboot git.
If built normally qboot works fine:
$ rm -rf build; meson build && ninja -C build
The Meson build system
Version: 0.63.0
Source dir: /root/qboot
Build dir: /root/qboot/build
Build type: native build
Project name: qboot
Project version: undefined
C compiler for the host machine: cc (gcc 11.3.0 "cc (Ubuntu 11.3.0-3ubuntu1) 11.3.0")
C linker for the host machine: cc ld.bfd 2.38.50.20220629
Host machine cpu family: x86_64
Host machine cpu: x86_64
Program objcopy found: YES (/usr/bin/objcopy)
Compiler for C supports link arguments -Wl,--build-id=none: YES
Compiler for C supports link arguments -no-pie: YES
Build targets in project: 2
Found ninja-1.11.0 at /usr/bin/ninja
ninja: Entering directory `build'
[16/17] Linking target bios.bin.elf
/usr/bin/ld: warning: bios.bin.elf.p/entry.S.o: missing .note.GNU-stack section implies executable stack
/usr/bin/ld: NOTE: This behaviour is deprecated and will be removed in a future version of the linker
/usr/bin/ld: warning: bios.bin.elf has a LOAD segment with RWX permissions
[17/17] Generating bios.bin with a custom command
But when using lto I've found two issues so far (depending on other flags)
$ export CFLAGS="-flto=auto -ffat-lto-objects"
$ export LDFLAGS="-flto=auto -ffat-lto-objects"
$ rm -rf build; meson build && ninja -C build
...
[16/17] Linking target bios.bin.elf
FAILED: bios.bin.elf
cc -o bios.bin.elf bios.bin.elf.p/code16.c.o bios.bin.elf.p/code32seg.c.o bios.bin.elf.p/cstart.S.o bios.bin.elf.p/entry.S.o bios.bin.elf.p/fw_cfg.c.o bios.bin.elf.p/hwsetup.c.o bios.bin.elf.p/linuxboot.c.o bios.bin.elf.p/main.c.o bios.bin.elf.p/malloc.c.o bios.bin.elf.p/mptable.c.o bios.bin.elf.p/pci.c.o bios.bin.elf.p/printf.c.o bios.bin.elf.p/string.c.o bios.bin.elf.p/smbios.c.o bios.bin.elf.p/tables.c.o -Wl,--as-needed -Wl,--no-undefined -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -nostdlib -m32 -Wl,--build-id=none -Wl,-T/root/qboot/flat.lds -no-pie
../linuxboot.c: Assembler messages:
../linuxboot.c:102: Error: value of fff123b4 too large for field of 2 bytes at 000023aa
make: *** [/tmp/ccApOVk6.mk:2: /tmp/ccNRHUMX.ltrans0.ltrans.o] Error 1
lto-wrapper: fatal error: make returned 2 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
Or the more common case of anything with -O1
or higher:
export LDFLAGS="-g -O2 -flto=auto -ffat-lto-objects"
root@k:~/qboot# export CFLAGS="-g -O2 -flto=auto -ffat-lto-objects"
root@k:~/qboot# rm -rf build; meson build && ninja -C build
...
[16/17] Linking target bios.bin.elf
FAILED: bios.bin.elf
cc -o bios.bin.elf bios.bin.elf.p/code16.c.o bios.bin.elf.p/code32seg.c.o bios.bin.elf.p/cstart.S.o bios.bin.elf.p/entry.S.o bios.bin.elf.p/fw_cfg.c.o bios.bin.elf.p/hwsetup.c.o bios.bin.elf.p/linuxboot.c.o bios.bin.elf.p/main.c.o bios.bin.elf.p/malloc.c.o bios.bin.elf.p/mptable.c.o bios.bin.elf.p/pci.c.o bios.bin.elf.p/printf.c.o bios.bin.elf.p/string.c.o bios.bin.elf.p/smbios.c.o bios.bin.elf.p/tables.c.o -Wl,--as-needed -Wl,--no-undefined -g -O2 -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -g -O2 -flto=auto -ffat-lto-objects -flto=auto -ffat-lto-objects -nostdlib -m32 -Wl,--build-id=none -Wl,-T/root/qboot/flat.lds -no-pie
../code16.c: Assembler messages:
../code16.c:37: Error: redundant addr32 prefix
../code16.c:27: Error: redundant addr32 prefix
../code16.c:18: Error: redundant addr32 prefix
make: *** [/tmp/ccqE9zCb.mk:2: /tmp/ccPw0c7S.ltrans0.ltrans.o] Error 1
lto-wrapper: fatal error: make returned 2 exit status
compilation terminated.
/usr/bin/ld: error: lto-wrapper failed
collect2: error: ld returned 1 exit status
ninja: build stopped: subcommand failed.
I tried with the following (all failed the same way):
- gcc 11.3.0-3ubuntu1
- gcc 11.3.0-4ubuntu1
- gcc 12.1.0-5ubuntu1
I also tried clang 14.0.6-1 but needed to drop -mstringop-strategy=rep_byte
from meson.build and -ffat-lto-objects
from my options as they are not supported. But even then it was not happy (but that might be ok - I haven't spent much time on getting clang to work by adding other arguments) with these instructions:
../code16.c:27:15: error: instruction requires: 64-bit mode
asm volatile("addr32 movl %%fs:%1,%0" : "=r" (v) : "m" (*(uint32_t *)addr));
In the Ubuntu builds I'll just stop LTO form being used for qboot for now, but I thought it might be worthwhile to report this for tracking and your opinion/consideration as I haven't found a former discussion on the case.
P.S. It happened in the past that after review the code was found to be correct and the bug being in the compiler. If you come to that conclusion please let me know as I'd want to then convert this to a compiler bug instead.