|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [PATCH 6/8] x86/EFI: avoid use of GNU ld's --disable-reloc-section when possible
On Thu, Apr 01, 2021 at 11:46:44AM +0200, Jan Beulich wrote:
> As of commit 6fa7408d72b3 ("ld: don't generate base relocations in PE
> output for absolute symbols") I'm feeling sufficiently confident in GNU
> ld to use its logic for generating base relocations, which was enabled
> for executables at some point last year (prior to that this would have
> got done only for DLLs).
>
> GNU ld, seeing the original relocations coming from the ELF object files,
> generates different relocation types for our page tables (64-bit ones,
> while mkreloc produces 32-bit ones). This requires also permitting and
> handling that type in efi_arch_relocate_image().
>
> Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
>
> --- a/xen/arch/x86/Makefile
> +++ b/xen/arch/x86/Makefile
> @@ -120,18 +120,37 @@ $(TARGET): $(TARGET)-syms $(efi-y) boot/
> mv $(TMP) $(TARGET)
>
> ifneq ($(efi-y),)
> +
> # Check if the compiler supports the MS ABI.
> export XEN_BUILD_EFI := $(shell $(CC) $(XEN_CFLAGS) -c efi/check.c -o
> efi/check.o 2>/dev/null && echo y)
> +CFLAGS-$(XEN_BUILD_EFI) += -DXEN_BUILD_EFI
> +
> # Check if the linker supports PE.
> EFI_LDFLAGS = $(patsubst -m%,-mi386pep,$(XEN_LDFLAGS)) --subsystem=10
> --strip-debug
> XEN_BUILD_PE := $(if $(XEN_BUILD_EFI),$(shell $(LD) $(EFI_LDFLAGS) -o
> efi/check.efi efi/check.o 2>/dev/null && echo y))
> -CFLAGS-$(XEN_BUILD_EFI) += -DXEN_BUILD_EFI
> -# Check if the linker produces fixups in PE by default (we need to disable
> it doing so for now).
> -XEN_NO_PE_FIXUPS := $(if $(XEN_BUILD_EFI), \
> - $(shell $(LD) $(EFI_LDFLAGS)
> --disable-reloc-section -o efi/check.efi efi/check.o 2>/dev/null && \
> - echo --disable-reloc-section))
> +
> +ifeq ($(XEN_BUILD_PE),y)
> +
> +# Check if the linker produces fixups in PE by default
> +nr-fixups := $(shell $(OBJDUMP) -p efi/check.efi | grep
> '^[[:blank:]]*reloc[[:blank:]]*[0-9][[:blank:]].*DIR64$$' | wc -l)
> +ifeq ($(nr-fixups),2)
> +MKRELOC := :
> +relocs-dummy :=
> +else
> +MKRELOC := efi/mkreloc
> +relocs-dummy := efi/relocs-dummy.o
> +# If the linker produced fixups but not precisely two of them, we need to
> +# disable it doing so. But if it didn't produce any fixups, it also wouldn't
> +# recognize the option.
> +ifneq ($(nr-fixups),0)
> +EFI_LDFLAGS += --disable-reloc-section
> +endif
> endif
>
> +endif # $(XEN_BUILD_PE)
> +
> +endif # $(efi-y)
> +
> ALL_OBJS := $(BASEDIR)/arch/x86/boot/built_in.o
> $(BASEDIR)/arch/x86/efi/built_in.o $(ALL_OBJS)
>
> ifeq ($(CONFIG_LTO),y)
> @@ -175,7 +194,7 @@ note.o: $(TARGET)-syms
> --rename-section=.data=.note.gnu.build-id -S $@.bin $@
> rm -f $@.bin
>
> -EFI_LDFLAGS += --image-base=$(1) --stack=0,0 --heap=0,0 $(XEN_NO_PE_FIXUPS)
> +EFI_LDFLAGS += --image-base=$(1) --stack=0,0 --heap=0,0
> EFI_LDFLAGS += --section-alignment=0x200000 --file-alignment=0x20
> EFI_LDFLAGS += --major-image-version=$(XEN_VERSION)
> EFI_LDFLAGS += --minor-image-version=$(XEN_SUBVERSION)
> @@ -189,7 +208,11 @@ EFI_LDFLAGS += --no-insert-timestamp
> endif
>
> $(TARGET).efi: VIRT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A
> VIRT_START$$,,p')
> +ifeq ($(MKRELOC),:)
> +$(TARGET).efi: ALT_BASE :=
> +else
> $(TARGET).efi: ALT_BASE = 0x$(shell $(NM) efi/relocs-dummy.o | sed -n 's, A
> ALT_START$$,,p')
Could you maybe check whether $(relocs-dummy) is set as the condition
here and use it here instead of efi/relocs-dummy.o?
> +endif
>
> ifneq ($(build_id_linker),)
> ifeq ($(call ld-ver-build-id,$(LD) $(filter -m%,$(EFI_LDFLAGS))),y)
> @@ -210,16 +233,16 @@ note_file_option ?= $(note_file)
> ifeq ($(XEN_BUILD_PE),y)
> $(TARGET).efi: prelink.o $(note_file) efi.lds efi/relocs-dummy.o efi/mkreloc
Do you need to also replace the target prerequisite to use $(relocs-dummy)?
> $(foreach base, $(VIRT_BASE) $(ALT_BASE), \
> - $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $<
> efi/relocs-dummy.o \
> + $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $<
> $(relocs-dummy) \
> $(BASEDIR)/common/symbols-dummy.o $(note_file_option)
> -o $(@D)/.$(@F).$(base).0 &&) :
> - efi/mkreloc $(foreach base,$(VIRT_BASE)
> $(ALT_BASE),$(@D)/.$(@F).$(base).0) >$(@D)/.$(@F).0r.S
> + $(MKRELOC) $(foreach base,$(VIRT_BASE)
> $(ALT_BASE),$(@D)/.$(@F).$(base).0) >$(@D)/.$(@F).0r.S
> $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).0 \
> | $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort
> >$(@D)/.$(@F).0s.S
> $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o
> $(foreach base, $(VIRT_BASE) $(ALT_BASE), \
> $(LD) $(call EFI_LDFLAGS,$(base)) -T efi.lds -N $< \
> $(@D)/.$(@F).0r.o $(@D)/.$(@F).0s.o $(note_file_option)
> -o $(@D)/.$(@F).$(base).1 &&) :
> - efi/mkreloc $(foreach base,$(VIRT_BASE)
> $(ALT_BASE),$(@D)/.$(@F).$(base).1) >$(@D)/.$(@F).1r.S
> + $(MKRELOC) $(foreach base,$(VIRT_BASE)
> $(ALT_BASE),$(@D)/.$(@F).$(base).1) >$(@D)/.$(@F).1r.S
> $(NM) -pa --format=sysv $(@D)/.$(@F).$(VIRT_BASE).1 \
> | $(BASEDIR)/tools/symbols $(all_symbols) --sysv --sort
> >$(@D)/.$(@F).1s.S
> $(MAKE) -f $(BASEDIR)/Rules.mk $(@D)/.$(@F).1r.o $(@D)/.$(@F).1s.o
> --- a/xen/arch/x86/efi/check.c
> +++ b/xen/arch/x86/efi/check.c
> @@ -2,3 +2,17 @@ int __attribute__((__ms_abi__)) test(int
> {
> return i;
> }
> +
> +/*
> + * Populate an array with "addresses" of relocatable and absolute values.
> + * This is to probe ld for (a) emitting base relocations at all and (b) not
> + * emitting base relocations for absolute symbols.
> + */
> +extern const unsigned char __image_base__[], __file_alignment__[],
> + __section_alignment__[];
> +const void *const data[] = {
> + __image_base__,
> + __file_alignment__,
> + __section_alignment__,
> + data,
> +};
> --- a/xen/arch/x86/efi/efi-boot.h
> +++ b/xen/arch/x86/efi/efi-boot.h
> @@ -86,10 +86,12 @@ static void __init efi_arch_relocate_ima
> }
> break;
> case PE_BASE_RELOC_DIR64:
> - if ( in_page_tables(addr) )
> - blexit(L"Unexpected relocation type");
> if ( delta )
> + {
> *(u64 *)addr += delta;
> + if ( in_page_tables(addr) )
> + *(u64 *)addr += xen_phys_start;
Doesn't the in_page_tables check and modification also apply when
delta == 0?
Maybe you could just break on !delta to reduce indentation if none of
this applies then?
Thanks, Roger.
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |