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@suse.com>
Acked-by: Roger Pau Monné <roger.pau@citrix.com>
This commit is contained in:
Jan Beulich committed 2021-04-22 13:29:49 +02:00
1 parent f27d9db17f
commit 1be65ec4c8
3 files changed
+50 -11

No files matched your search

+32 -9
View File
@@ -123,17 +123,36 @@ $(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)
@@ -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
+14
View File
@@ -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,
};
+4 -2
View File
@@ -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");
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.