diff --git a/meson_options.txt b/meson_options.txt index 1e91bf1fd2..e4b85c73ee 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -411,7 +411,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') diff --git a/src/boot/efi/meson.build b/src/boot/efi/meson.build index 17407281bb..b8001d1c65 100644 --- a/src/boot/efi/meson.build +++ b/src/boot/efi/meson.build @@ -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], @@ -260,26 +252,52 @@ foreach arg : get_option('c_args') 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', + '-shared', + '-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'] # 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_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 @@ -308,7 +326,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, tuple[2], '-lefi', '-lgnuefi', libgcc_file_name], install : tuple[3], install_dir : bootlibdir)