[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen staging] x86/EFI: avoid use of GNU ld's --disable-reloc-section when possible



commit 1be65ec4c8bc172aadd6bc1b6553c668152899ae
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Apr 22 13:29:49 2021 +0200
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Apr 22 13:29:49 2021 +0200

    x86/EFI: avoid use of GNU ld's --disable-reloc-section when possible
    
    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().
    
    Note that in the case that we leave base relocation generation to ld,
    while efi/relocs-dummy.o then won't be linked into any executable
    anymore, it still needs generating (and hence dependencies need to be
    kept as they are) in order to have VIRT_BASE pulled out of it.
    
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Acked-by: Roger Pau Monné <roger.pau@xxxxxxxxxx>
---
 xen/arch/x86/Makefile       | 41 ++++++++++++++++++++++++++++++++---------
 xen/arch/x86/efi/check.c    | 14 ++++++++++++++
 xen/arch/x86/efi/efi-boot.h |  6 ++++--
 3 files changed, 50 insertions(+), 11 deletions(-)

diff --git a/xen/arch/x86/Makefile b/xen/arch/x86/Makefile
index b224b1cf89..5b47206ad1 100644
--- a/xen/arch/x86/Makefile
+++ b/xen/arch/x86/Makefile
@@ -123,18 +123,37 @@ $(TARGET): $(TARGET)-syms $(efi-y) boot/mkelf32
        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)
@@ -178,7 +197,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)
@@ -192,7 +211,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')
+endif
 
 ifneq ($(build_id_linker),)
 ifeq ($(call ld-ver-build-id,$(LD) $(filter -m%,$(EFI_LDFLAGS))),y)
@@ -213,16 +236,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
        $(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
diff --git a/xen/arch/x86/efi/check.c b/xen/arch/x86/efi/check.c
index 7fedd5a610..9e473faad3 100644
--- a/xen/arch/x86/efi/check.c
+++ b/xen/arch/x86/efi/check.c
@@ -2,3 +2,17 @@ int __attribute__((__ms_abi__)) test(int i)
 {
     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,
+};
diff --git a/xen/arch/x86/efi/efi-boot.h b/xen/arch/x86/efi/efi-boot.h
index 2541ba1f32..fb217031ff 100644
--- 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_image(unsigned long 
delta)
                 }
                 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;
+                }
                 break;
             default:
                 blexit(L"Unsupported relocation type");
--
generated by git-patchbot for /home/xen/git/xen.git#staging



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.