From: "Laszlo Ersek" <lersek@redhat.com>
To: devel@edk2.groups.io, ard.biesheuvel@arm.com
Cc: Bob Feng <bob.c.feng@intel.com>,
Liming Gao <liming.gao@intel.com>,
Leif Lindholm <leif@nuviainc.com>,
Ilias Apalodimas <ilias.apalodimas@linaro.org>,
Julien Grall <julien@xen.org>, Jiewen Yao <jiewen.yao@intel.com>
Subject: Re: [edk2-devel] [PATCH 3/4] ArmVirtPkg/PrePi: use standard PeCoff routines for self-relocation
Date: Tue, 9 Jun 2020 22:35:05 +0200 [thread overview]
Message-ID: <70e115e9-42d0-0bd2-7fdb-1be19c7af1db@redhat.com> (raw)
In-Reply-To: <20200608173413.1100679-4-ard.biesheuvel@arm.com>
On 06/08/20 19:34, Ard Biesheuvel wrote:
> Instead of having a GCC specific routine to perform self-relocation
> based on ELF metadata, use the PE/COFF metadata and the existing
> PeCoff library routines. This reduces the amount of bespoke assembler
> code that is a burden to maintain, and is not portable across the set
> of toolchains we support.
>
> This does require some special care, as we have no control over how
> the C code references global symbols, so we need to emit these
> references from the calling assembler code. Otherwise, they may be
> emitted as absolute references, in which case they need to be fixed
> up themselves, leading to a circular dependency.
>
> Signed-off-by: Ard Biesheuvel <ard.biesheuvel@arm.com>
> ---
> ArmVirtPkg/ArmVirtQemuKernel.dsc | 10 ++--
> ArmVirtPkg/ArmVirtXen.dsc | 10 ++--
> ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf | 4 +-
> ArmVirtPkg/PrePi/PrePi.c | 21 +++++++++
> ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S | 49 +++++---------------
> ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S | 47 +++++--------------
> 6 files changed, 54 insertions(+), 87 deletions(-)
>
> diff --git a/ArmVirtPkg/ArmVirtQemuKernel.dsc b/ArmVirtPkg/ArmVirtQemuKernel.dsc
> index 2a6fd6bc06be..9449a01d6e40 100644
> --- a/ArmVirtPkg/ArmVirtQemuKernel.dsc
> +++ b/ArmVirtPkg/ArmVirtQemuKernel.dsc
> @@ -83,14 +83,12 @@ [LibraryClasses.common.DXE_DRIVER]
> [LibraryClasses.common.UEFI_DRIVER]
> UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
>
> -[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.BASE]
> +[BuildOptions]
> #
> - # CLANG38 with LTO support enabled uses the GNU GOLD linker, which insists
> - # on emitting GOT based symbol references when running in shared mode, unless
> - # we override visibility to 'hidden' in all modules that make up the PrePi
> - # build.
> + # We need to avoid jump tables in SEC modules, so that the PE/COFF
> + # self-relocation code itself is guaranteed to be position independent.
> #
> - GCC:*_CLANG38_*_CC_FLAGS = -include $(WORKSPACE)/ArmVirtPkg/Include/Platform/Hidden.h
> + GCC:*_*_*_CC_FLAGS = -fno-jump-tables
>
> ################################################################################
> #
> diff --git a/ArmVirtPkg/ArmVirtXen.dsc b/ArmVirtPkg/ArmVirtXen.dsc
> index 8a489b253684..278f5d3828ce 100644
> --- a/ArmVirtPkg/ArmVirtXen.dsc
> +++ b/ArmVirtPkg/ArmVirtXen.dsc
> @@ -52,14 +52,12 @@ [LibraryClasses]
> [LibraryClasses.common.UEFI_DRIVER]
> UefiScsiLib|MdePkg/Library/UefiScsiLib/UefiScsiLib.inf
>
> -[BuildOptions.common.EDKII.SEC, BuildOptions.common.EDKII.BASE]
> +[BuildOptions]
> #
> - # CLANG38 with LTO support enabled uses the GNU GOLD linker, which insists
> - # on emitting GOT based symbol references when running in shared mode, unless
> - # we override visibility to 'hidden' in all modules that make up the PrePi
> - # build.
> + # We need to avoid jump tables in SEC modules, so that the PE/COFF
> + # self-relocation code itself is guaranteed to be position independent.
> #
> - GCC:*_CLANG38_*_CC_FLAGS = -include $(WORKSPACE)/ArmVirtPkg/Include/Platform/Hidden.h
> + GCC:*_*_*_CC_FLAGS = -fno-jump-tables
>
> ################################################################################
> #
> diff --git a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
> index 9e58e56fce09..7edf5018089d 100755
> --- a/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
> +++ b/ArmVirtPkg/PrePi/ArmVirtPrePiUniCoreRelocatable.inf
> @@ -46,6 +46,7 @@ [LibraryClasses]
> SerialPortLib
> ExtractGuidedSectionLib
> LzmaDecompressLib
> + PeCoffLib
> PrePiLib
> MemoryAllocationLib
> HobLib
> @@ -95,6 +96,3 @@ [Pcd]
> gArmVirtTokenSpaceGuid.PcdDeviceTreeInitialBaseAddress
> gArmTokenSpaceGuid.PcdFdBaseAddress
> gArmTokenSpaceGuid.PcdFvBaseAddress
> -
> -[BuildOptions]
> - GCC:*_*_*_DLINK_FLAGS = -Wl,-Bsymbolic,-pie,-T,$(MODULE_DIR)/Scripts/PrePi-PIE.lds
> diff --git a/ArmVirtPkg/PrePi/PrePi.c b/ArmVirtPkg/PrePi/PrePi.c
> index 72e35028c5bb..0cb064419759 100755
> --- a/ArmVirtPkg/PrePi/PrePi.c
> +++ b/ArmVirtPkg/PrePi/PrePi.c
> @@ -9,6 +9,7 @@
> #include <PiPei.h>
> #include <Pi/PiBootMode.h>
>
> +#include <Library/PeCoffLib.h>
> #include <Library/PrePiLib.h>
> #include <Library/PrintLib.h>
> #include <Library/PrePiHobListPointerLib.h>
> @@ -128,3 +129,23 @@ CEntryPoint (
> // DXE Core should always load and never return
> ASSERT (FALSE);
> }
> +
> +VOID
> +RelocatePeCoffImage (
> + IN UINTN ImageBase,
> + IN PE_COFF_LOADER_READ_FILE ImageRead
> + )
> +{
> + PE_COFF_LOADER_IMAGE_CONTEXT ImageContext;
> +
> + ZeroMem (&ImageContext, sizeof ImageContext);
> +
> + ImageContext.Handle = (EFI_HANDLE)ImageBase;
> + ImageContext.ImageRead = ImageRead;
> + PeCoffLoaderGetImageInfo (&ImageContext);
> +
> + if (ImageContext.ImageAddress != ImageBase) {
> + ImageContext.ImageAddress = ImageBase;
> + PeCoffLoaderRelocateImage (&ImageContext);
> + }
> +}
> diff --git a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
> index 34d6abecb0ac..7c5592b11a46 100644
> --- a/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
> +++ b/ArmVirtPkg/PrePi/AArch64/ModuleEntryPoint.S
> @@ -9,40 +9,6 @@
> #include <AsmMacroIoLibV8.h>
>
> ASM_FUNC(_ModuleEntryPoint)
> - //
> - // We are built as a ET_DYN PIE executable, so we need to process all
> - // relative relocations regardless of whether or not we are executing from
> - // the same offset we were linked at. This is only possible if we are
> - // running from RAM.
> - //
> - adr x8, __reloc_base
> - adr x9, __reloc_start
> - adr x10, __reloc_end
> -
> -.Lreloc_loop:
> - cmp x9, x10
> - bhs .Lreloc_done
> -
> - //
> - // AArch64 uses the ELF64 RELA format, which means each entry in the
> - // relocation table consists of
> - //
> - // UINT64 offset : the relative offset of the value that needs to
> - // be relocated
> - // UINT64 info : relocation type and symbol index (the latter is
> - // not used for R_AARCH64_RELATIVE relocations)
> - // UINT64 addend : value to be added to the value being relocated
> - //
> - ldp x11, x12, [x9], #24 // read offset into x11 and info into x12
> - cmp x12, #0x403 // check info == R_AARCH64_RELATIVE?
> - bne .Lreloc_loop // not a relative relocation? then skip
> -
> - ldr x12, [x9, #-8] // read addend into x12
> - add x12, x12, x8 // add reloc base to addend to get relocated value
> - str x12, [x11, x8] // write relocated value at offset
> - b .Lreloc_loop
> -.Lreloc_done:
> -
> bl ASM_PFX(DiscoverDramFromDt)
>
> // Get ID of this CPU in Multicore system
> @@ -170,15 +136,24 @@ ASM_PFX(DiscoverDramFromDt):
> str x1, [x8]
> str x7, [x9]
>
> + //
> + // The runtime address may be different from the link time address so fix
> + // up the PE/COFF relocations. Since we are calling a C function, use the
> + // window at the beginning of the FD image as a temp stack.
> + //
> + adr x0, ElfImageBase
> + adr x1, PeCoffLoaderImageReadFromMemory
> + mov sp, x7
> + bl RelocatePeCoffImage
> +
> //
> // Discover the memory size and offset from the DTB, and record in the
> // respective PCDs. This will also return false if a corrupt DTB is
> - // encountered. Since we are calling a C function, use the window at the
> - // beginning of the FD image as a temp stack.
> + // encountered.
> //
> + mov x0, x28
> adr x1, PcdGet64 (PcdSystemMemoryBase)
> adr x2, PcdGet64 (PcdSystemMemorySize)
> - mov sp, x7
> bl FindMemnode
> cbz x0, .Lout
>
> diff --git a/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S b/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S
> index 72d756fdb571..bf39de86e7d0 100644
> --- a/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S
> +++ b/ArmVirtPkg/PrePi/Arm/ModuleEntryPoint.S
> @@ -9,38 +9,6 @@
> #include <AsmMacroIoLib.h>
>
> ASM_FUNC(_ModuleEntryPoint)
> - //
> - // We are built as a ET_DYN PIE executable, so we need to process all
> - // relative relocations if we are executing from a different offset than we
> - // were linked at. This is only possible if we are running from RAM.
> - //
> - ADRL (r4, __reloc_base)
> - ADRL (r5, __reloc_start)
> - ADRL (r6, __reloc_end)
> -
> -.Lreloc_loop:
> - cmp r5, r6
> - bhs .Lreloc_done
> -
> - //
> - // AArch32 uses the ELF32 REL format, which means each entry in the
> - // relocation table consists of
> - //
> - // UINT32 offset : the relative offset of the value that needs to
> - // be relocated
> - // UINT32 info : relocation type and symbol index (the latter is
> - // not used for R_ARM_RELATIVE relocations)
> - //
> - ldrd r8, r9, [r5], #8 // read offset into r8 and info into r9
> - cmp r9, #23 // check info == R_ARM_RELATIVE?
> - bne .Lreloc_loop // not a relative relocation? then skip
> -
> - ldr r9, [r8, r4] // read addend into r9
> - add r9, r9, r1 // add image base to addend to get relocated value
> - str r9, [r8, r4] // write relocated value at offset
> - b .Lreloc_loop
> -.Lreloc_done:
> -
> // Do early platform specific actions
> bl ASM_PFX(ArmPlatformPeiBootAction)
>
> @@ -172,15 +140,24 @@ ASM_PFX(ArmPlatformPeiBootAction):
> str r1, [r8]
> str r5, [r7]
>
> + //
> + // The runtime address may be different from the link time address so fix
> + // up the PE/COFF relocations. Since we are calling a C function, use the
> + // window at the beginning of the FD image as a temp stack.
> + //
> + ADRL (r0, ElfImageBase)
> + ADRL (r1, PeCoffLoaderImageReadFromMemory)
> + mov sp, r5
> + bl RelocatePeCoffImage
> +
> //
> // Discover the memory size and offset from the DTB, and record in the
> // respective PCDs. This will also return false if a corrupt DTB is
> - // encountered. Since we are calling a C function, use the window at the
> - // beginning of the FD image as a temp stack.
> + // encountered.
> //
> + mov r0, r10
> ADRL (r1, PcdGet64 (PcdSystemMemoryBase))
> ADRL (r2, PcdGet64 (PcdSystemMemorySize))
> - mov sp, r5
> bl FindMemnode
> teq r0, #0
> beq .Lout
>
Acked-by: Laszlo Ersek <lersek@redhat.com>
next prev parent reply other threads:[~2020-06-09 20:35 UTC|newest]
Thread overview: 13+ messages / expand[flat|nested] mbox.gz Atom feed top
2020-06-08 17:34 [PATCH 0/4] ArmVirtPkg: use PE/COFF metadata for self relocation Ard Biesheuvel
2020-06-08 17:34 ` [PATCH 1/4] ArmVirtPkg: add FDF rule for self-relocating PrePi Ard Biesheuvel
2020-06-09 20:33 ` [edk2-devel] " Laszlo Ersek
2020-06-08 17:34 ` [PATCH 2/4] BaseTools/Scripts/GccBase.lds: export image base symbol Ard Biesheuvel
2020-06-10 21:48 ` Ard Biesheuvel
2020-06-12 5:22 ` [edk2-devel] " Bob Feng
2020-06-08 17:34 ` [PATCH 3/4] ArmVirtPkg/PrePi: use standard PeCoff routines for self-relocation Ard Biesheuvel
2020-06-09 20:35 ` Laszlo Ersek [this message]
2020-06-08 17:34 ` [PATCH 4/4] ArmVirtPkg: remove unused files Ard Biesheuvel
2020-06-09 20:36 ` [edk2-devel] " Laszlo Ersek
2020-06-09 0:00 ` [PATCH 0/4] ArmVirtPkg: use PE/COFF metadata for self relocation Yao, Jiewen
2020-06-09 10:29 ` Julien Grall
2020-06-10 20:35 ` [edk2-devel] " Sami Mujawar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-list from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=70e115e9-42d0-0bd2-7fdb-1be19c7af1db@redhat.com \
--to=devel@edk2.groups.io \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox