Skip to content

Commit fe330f0

Browse files
committed
sd-boot: Let the compiler invoke the linker for us
For LTO to work, the linker has to be called with some magic sauce arguments. And the easiest way to get those is to just let the compiler to the job for us.
1 parent 8fb4440 commit fe330f0

2 files changed

Lines changed: 42 additions & 22 deletions

File tree

meson_options.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -411,7 +411,9 @@ option('gnu-efi', type : 'combo', choices : ['auto', 'true', 'false'],
411411
description : 'gnu-efi support for sd-boot')
412412
option('efi-cc', type : 'array',
413413
description : 'the compiler to use for EFI modules')
414-
option('efi-ld', type : 'string', value : 'ld',
414+
# Note that LLD does not support PE/COFF relocations
415+
# https://lists.llvm.org/pipermail/llvm-dev/2021-March/149234.html
416+
option('efi-ld', type : 'combo', choices : ['bfd', 'gold'],
415417
description : 'the linker to use for EFI modules')
416418
option('efi-libdir', type : 'string',
417419
description : 'path to the EFI lib directory')

src/boot/efi/meson.build

Lines changed: 39 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -48,14 +48,6 @@ if efi_cc.length() == 0
4848
efi_cc = cc.cmd_array()
4949
endif
5050

51-
efi_ld = find_program(get_option('efi-ld'))
52-
efi_ld_name = efi_ld.path().split('/')[-1]
53-
if efi_ld_name == 'lld' or efi_ld_name == 'ld.lld'
54-
# LLVM/LLD does not support PE/COFF relocations
55-
# https://lists.llvm.org/pipermail/llvm-dev/2021-March/149234.html
56-
error('LLVM/lld does not support PE/COFF relocations. Use different linker for EFI image.')
57-
endif
58-
5951
efi_libdir = ''
6052
foreach dir : [get_option('efi-libdir'),
6153
'/usr/lib/gnuefi' / efi_arch[0],
@@ -260,26 +252,52 @@ foreach arg : get_option('c_args')
260252
endif
261253
endforeach
262254

263-
efi_ldflags = ['-T', efi_lds,
264-
'-shared',
265-
'-Bsymbolic',
266-
'-nostdlib',
267-
'--no-undefined',
268-
'--warn-common',
269-
'--fatal-warnings',
270-
'-znocombreloc',
271-
'--build-id=sha1',
272-
'-L', efi_libdir,
273-
efi_crt0]
255+
efi_ldflags = [
256+
'-fuse-ld=' + get_option('efi-ld'),
257+
'-L', efi_libdir,
258+
'-nostdlib',
259+
'-shared',
260+
'-T', efi_lds,
261+
'-Wl,--build-id=sha1',
262+
'-Wl,--fatal-warnings',
263+
'-Wl,--no-undefined',
264+
'-Wl,--warn-common',
265+
'-Wl,-Bsymbolic',
266+
'-z', 'nocombreloc',
267+
efi_crt0,
268+
]
274269
if efi_arch[1] in ['aarch64', 'arm', 'riscv64']
275270
# Aarch64, ARM32 and 64bit RISC-V don't have an EFI capable objcopy.
276271
# Use 'binary' instead, and add required symbols manually.
277-
efi_ldflags += ['--defsym=EFI_SUBSYSTEM=0xa']
272+
efi_ldflags += ['-Wl,--defsym=EFI_SUBSYSTEM=0xa']
278273
efi_format = ['-O', 'binary']
279274
else
280275
efi_format = ['--target=efi-app-@0@'.format(efi_arch[1])]
281276
endif
282277

278+
if run_command('grep', '-q', '__CTOR_LIST__', efi_lds).returncode() == 0
279+
# fedora has a patched gnu-efi that adds support for ELF constructors.
280+
# If ld is called by gcc something about these symbols breaks, resulting
281+
# in sd-boot freezing when gnu-efi runs the constructors. Force defining
282+
# them seems to work around this.
283+
efi_ldflags += [
284+
'-Wl,--defsym=_init_array=0',
285+
'-Wl,--defsym=_init_array_end=0',
286+
'-Wl,--defsym=_fini_array=0',
287+
'-Wl,--defsym=_fini_array_end=0',
288+
'-Wl,--defsym=__CTOR_LIST__=0',
289+
'-Wl,--defsym=__CTOR_END__=0',
290+
'-Wl,--defsym=__DTOR_LIST__=0',
291+
'-Wl,--defsym=__DTOR_END__=0',
292+
]
293+
endif
294+
295+
efi_cc_version = run_command(efi_cc, '--version').stdout().split('\n')[0]
296+
if efi_cc_version.contains('clang') and efi_cc_version.split('.')[0].split(' ')[-1].to_int() <= 10
297+
# clang <= 10 doesn't pass -T to the linker and then even complains about it being unused
298+
efi_ldflags += ['-Wl,-T,' + efi_lds, '-Wno-unused-command-line-argument']
299+
endif
300+
283301
systemd_boot_objects = []
284302
stub_objects = []
285303
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
308326
tuple[0],
309327
input : tuple[2],
310328
output : tuple[0],
311-
command : [efi_ld, '-o', '@OUTPUT@', efi_ldflags, tuple[2], '-lefi', '-lgnuefi', libgcc_file_name],
329+
command : [efi_cc, '-o', '@OUTPUT@', efi_ldflags, tuple[2], '-lefi', '-lgnuefi', libgcc_file_name],
312330
install : tuple[3],
313331
install_dir : bootlibdir)
314332

0 commit comments

Comments
 (0)