Merge pull request #21264 from medhefgo/boot-lto

sd-boot: LTO support
This commit is contained in:
Zbigniew Jędrzejewski-Szmek 2021-12-07 12:58:59 +01:00 committed by GitHub
commit 3944ef20f5
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 54 additions and 27 deletions

View file

@ -413,7 +413,9 @@ option('gnu-efi', type : 'combo', choices : ['auto', 'true', 'false'],
description : 'gnu-efi support for sd-boot')
option('efi-cc', type : 'array',
description : 'the compiler to use for EFI modules')
option('efi-ld', type : 'string', value : 'ld',
# Note that LLD does not support PE/COFF relocations
# https://lists.llvm.org/pipermail/llvm-dev/2021-March/149234.html
option('efi-ld', type : 'combo', choices : ['bfd', 'gold'],
description : 'the linker to use for EFI modules')
option('efi-libdir', type : 'string',
description : 'path to the EFI lib directory')

View file

@ -52,12 +52,12 @@ EFI_STATUS console_key_read(UINT64 *key, UINT64 timeout_usec) {
/* If WaitForKeyEx fails here, the firmware pretends it talks this
* protocol, but it really doesn't. */
TextInputEx = NULL;
else
events[n_events++] = TextInputEx->WaitForKeyEx;
checked = TRUE;
}
if (TextInputEx)
events[n_events++] = TextInputEx->WaitForKeyEx;
err = BS->CreateEvent(EVT_TIMER, 0, NULL, NULL, &timer);
if (EFI_ERROR(err))
return log_error_status_stall(err, L"Error creating timer event: %r", err);

View file

@ -48,14 +48,6 @@ if efi_cc.length() == 0
efi_cc = cc.cmd_array()
endif
efi_ld = find_program(get_option('efi-ld'))
efi_ld_name = efi_ld.path().split('/')[-1]
if efi_ld_name == 'lld' or efi_ld_name == 'ld.lld'
# LLVM/LLD does not support PE/COFF relocations
# https://lists.llvm.org/pipermail/llvm-dev/2021-March/149234.html
error('LLVM/lld does not support PE/COFF relocations. Use different linker for EFI image.')
endif
efi_libdir = ''
foreach dir : [get_option('efi-libdir'),
'/usr/lib/gnuefi' / efi_arch[0],
@ -252,34 +244,67 @@ if get_option('b_ndebug') == 'true' or (
get_option('b_ndebug') == 'if-release' and get_option('buildtype') in ['plain', 'release'])
efi_cflags += ['-DNDEBUG']
endif
if get_option('b_lto')
efi_cflags += ['-flto']
endif
foreach arg : get_option('c_args')
if arg in ['-Werror', '-g', '-ggdb', '-O1', '-O2', '-O3', '-Og', '-Os', '-DNDEBUG']
if arg in ['-Werror', '-g', '-ggdb', '-O1', '-O2', '-O3', '-Og', '-Os', '-DNDEBUG', '-flto', '-fno-lto']
message('Using "@0@" from c_args for EFI compiler'.format(arg))
efi_cflags += arg
endif
endforeach
efi_ldflags = ['-T', efi_lds,
'-shared',
'-Bsymbolic',
'-nostdlib',
'--no-undefined',
'--warn-common',
'--fatal-warnings',
'-znocombreloc',
'--build-id=sha1',
'-L', efi_libdir,
efi_crt0]
efi_ldflags = [
'-fuse-ld=' + get_option('efi-ld'),
'-L', efi_libdir,
'-nostdlib',
'-T', efi_lds,
'-Wl,--build-id=sha1',
'-Wl,--fatal-warnings',
'-Wl,--no-undefined',
'-Wl,--warn-common',
'-Wl,-Bsymbolic',
'-z', 'nocombreloc',
efi_crt0,
]
if efi_arch[1] in ['aarch64', 'arm', 'riscv64']
efi_ldflags += ['-shared', '-fwhole-program']
# Aarch64, ARM32 and 64bit RISC-V don't have an EFI capable objcopy.
# Use 'binary' instead, and add required symbols manually.
efi_ldflags += ['--defsym=EFI_SUBSYSTEM=0xa']
efi_ldflags += ['-Wl,--defsym=EFI_SUBSYSTEM=0xa']
efi_format = ['-O', 'binary']
else
efi_ldflags += ['-pie']
if get_option('efi-ld') == 'bfd'
efi_ldflags += '-Wl,--no-dynamic-linker'
endif
efi_format = ['--target=efi-app-@0@'.format(efi_arch[1])]
endif
if run_command('grep', '-q', '__CTOR_LIST__', efi_lds).returncode() == 0
# fedora has a patched gnu-efi that adds support for ELF constructors.
# If ld is called by gcc something about these symbols breaks, resulting
# in sd-boot freezing when gnu-efi runs the constructors. Force defining
# them seems to work around this.
efi_ldflags += [
'-Wl,--defsym=_init_array=0',
'-Wl,--defsym=_init_array_end=0',
'-Wl,--defsym=_fini_array=0',
'-Wl,--defsym=_fini_array_end=0',
'-Wl,--defsym=__CTOR_LIST__=0',
'-Wl,--defsym=__CTOR_END__=0',
'-Wl,--defsym=__DTOR_LIST__=0',
'-Wl,--defsym=__DTOR_END__=0',
]
endif
efi_cc_version = run_command(efi_cc, '--version').stdout().split('\n')[0]
if efi_cc_version.contains('clang') and efi_cc_version.split('.')[0].split(' ')[-1].to_int() <= 10
# clang <= 10 doesn't pass -T to the linker and then even complains about it being unused
efi_ldflags += ['-Wl,-T,' + efi_lds, '-Wno-unused-command-line-argument']
endif
systemd_boot_objects = []
stub_objects = []
foreach file : fundamental_source_paths + common_sources + systemd_boot_sources + stub_sources
@ -296,7 +321,6 @@ foreach file : fundamental_source_paths + common_sources + systemd_boot_sources
endif
endforeach
libgcc_file_name = run_command(efi_cc + ['-print-libgcc-file-name']).stdout().strip()
systemd_boot_efi_name = 'systemd-boot@0@.efi'.format(efi_arch[0])
stub_elf_name = 'linux@0@.elf.stub'.format(efi_arch[0])
stub_efi_name = 'linux@0@.efi.stub'.format(efi_arch[0])
@ -308,7 +332,7 @@ foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects
tuple[0],
input : tuple[2],
output : tuple[0],
command : [efi_ld, '-o', '@OUTPUT@', efi_ldflags, tuple[2], '-lefi', '-lgnuefi', libgcc_file_name],
command : [efi_cc, '-o', '@OUTPUT@', efi_ldflags, efi_cflags, tuple[2], '-lefi', '-lgnuefi', '-lgcc'],
install : tuple[3],
install_dir : bootlibdir)
@ -317,6 +341,7 @@ foreach tuple : [['systemd_boot.so', systemd_boot_efi_name, systemd_boot_objects
input : so,
output : tuple[1],
command : [objcopy,
'-j', '.bss*',
'-j', '.data',
'-j', '.dynamic',
'-j', '.dynsym',