Discussion:
[edk2] [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
Ard Biesheuvel
2015-07-03 09:40:01 UTC
Permalink
This is a followup to the patch I sen yesterday:
http://article.gmane.org/gmane.comp.bios.tianocore.devel/16647

I should know better than to propose changes to MdePkg, but in this
case, I think the issues around the MemoryProtectionAttribute are
severe enough to warrant drastic measures.

Patches #1 and #2 are cleanup patches, they remove dead code that handles
relocations that are already handled by the callers of the respective
functions.

Patch #3 fixes a bug in BasePeCoffLib where it fails to take into account
that applying a EFI_IMAGE_REL_BASED_LOW relocation may result in a carry
that needs to be taken into account when handling the corresponding
EFI_IMAGE_REL_BASED_HIGH relocation.

Patch #4 works around a bug in BasePeCoffLib where the runtime re-relocation
may reapply EFI_IMAGE_REL_BASED_LOW or EFI_IMAGE_REL_BASED_HIGH relocations
even if the target location has been updated programmatically after the
image was loaded.

Patch #5 replaces the 'Adjust' argument of PeCoffLoaderRelocateImageForRuntime
with a ConvertPointer() callback function pointer so that the runtime relocation
can handle disjoint PE/COFF images in virtual memory.

Patch #6 updates RuntimeDxe to use the new PeCoffLoaderRelocateImageForRuntime
prototype.

Unfortunately, this series is not bisectable between #5 and #6. Working around
that is non-trivial and probably not worth the hassle.

Ard Biesheuvel (6):
MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64
MdePkg/BasePeCoffLib: remove redundant handling of
EFI_IMAGE_REL_BASED_DIR64
MdePkg/BasePeCoffLib: account for carry in high/low relocation pairs
MdePkg/BasePeCoffLib: fix handling of high/low relocation pairs
MdePkg/BasePeCoffLib: relocate for runtime using ConvertPointer
callback
MdeModulePkg/RuntimeDxe: update to new RelocateImageForRuntime()
prototype

MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +-
MdePkg/Include/Library/PeCoffLib.h | 28 ++++-
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 +--
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 86 +++++++++----
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 +--
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 42 +++----
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 20 +--
9 files changed, 138 insertions(+), 217 deletions(-)
delete mode 100644 MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
--
1.9.1
Ard Biesheuvel
2015-07-03 09:40:02 UTC
Permalink
The AARCH64 specific implementations of PeCoffLoaderRelocateImageEx and
PeHotRelocateImageEx only handle EFI_IMAGE_REL_BASED_DIR64 relocations.
Since these are already handled by the respective callers, this is
essentially dead code and can be removed.

So add IMAGE_FILE_MACHINE_ARM64 support to the list of supported machines
of the generic version, and use it for AARCH64 as well.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 4 +-
3 files changed, 3 insertions(+), 133 deletions(-)

diff --git a/MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
deleted file mode 100644
index 7e4b4db45328..000000000000
--- a/MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/** @file
- Specific relocation fixups for ARM architecture.
-
- Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
- Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
- Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
-
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "BasePeCoffLibInternals.h"
-#include <Library/BaseLib.h>
-
-// Note: Currently only large memory model is supported by UEFI relocation code.
-
-/**
- Performs an AARCH64-based specific relocation fixup and is a no-op on other
- instruction sets.
-
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
-
- @return Status code.
-
-**/
-RETURN_STATUS
-PeCoffLoaderRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
- )
-{
- UINT64 *Fixup64;
-
- switch ((*Reloc) >> 12) {
-
- case EFI_IMAGE_REL_BASED_DIR64:
- Fixup64 = (UINT64 *) Fixup;
- *Fixup64 = *Fixup64 + (UINT64) Adjust;
- if (*FixupData != NULL) {
- *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
- *(UINT64 *)(*FixupData) = *Fixup64;
- *FixupData = *FixupData + sizeof(UINT64);
- }
- break;
-
- default:
- return RETURN_UNSUPPORTED;
- }
-
- return RETURN_SUCCESS;
-}
-
-/**
- Returns TRUE if the machine type of PE/COFF image is supported. Supported
- does not mean the image can be executed it means the PE/COFF loader supports
- loading and relocating of the image type. It's up to the caller to support
- the entry point.
-
- @param Machine Machine type from the PE Header.
-
- @return TRUE if this PE/COFF loader can load the image
-
-**/
-BOOLEAN
-PeCoffLoaderImageFormatSupported (
- IN UINT16 Machine
- )
-{
- if ((Machine == IMAGE_FILE_MACHINE_ARM64) || (Machine == IMAGE_FILE_MACHINE_EBC)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Performs an ARM-based specific re-relocation fixup and is a no-op on other
- instruction sets. This is used to re-relocated the image into the EFI virtual
- space for runtime calls.
-
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
-
- @return Status code.
-
-**/
-RETURN_STATUS
-PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
- )
-{
- UINT64 *Fixup64;
-
- switch ((*Reloc) >> 12) {
- case EFI_IMAGE_REL_BASED_DIR64:
- Fixup64 = (UINT64 *) Fixup;
- *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
- if (*(UINT64 *) (*FixupData) == *Fixup64) {
- *Fixup64 = *Fixup64 + (UINT64) Adjust;
- }
-
- *FixupData = *FixupData + sizeof (UINT64);
- break;
-
- default:
- DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n"));
- return RETURN_UNSUPPORTED;
- }
-
- return RETURN_SUCCESS;
-}
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
index 576d72826c32..ff0580fbdf56 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
@@ -40,7 +40,7 @@ [Sources]
BasePeCoffLibInternals.h
BasePeCoff.c

-[Sources.IA32, Sources.X64, Sources.EBC]
+[Sources.IA32, Sources.X64, Sources.EBC, Sources.AARCH64]
PeCoffLoaderEx.c

[Sources.IPF]
@@ -49,9 +49,6 @@ [Sources.IPF]
[Sources.ARM]
Arm/PeCoffLoaderEx.c

-[Sources.AARCH64]
- AArch64/PeCoffLoaderEx.c
-
[Packages]
MdePkg/MdePkg.dec

diff --git a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
index 2ed58844d5d4..01825c85392b 100644
--- a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
@@ -44,7 +44,7 @@ PeCoffLoaderRelocateImageEx (
loading and relocating of the image type. It's up to the caller to support
the entry point.

- The IA32/X64 version PE/COFF loader/relocater both support IA32, X64 and EBC images.
+ The generic version PE/COFF loader/relocater supports IA32, X64, AARCH64 and EBC images.

@param Machine The machine type from the PE Header.

@@ -57,7 +57,7 @@ PeCoffLoaderImageFormatSupported (
)
{
if ((Machine == IMAGE_FILE_MACHINE_I386) || (Machine == IMAGE_FILE_MACHINE_X64) ||
- (Machine == IMAGE_FILE_MACHINE_EBC)) {
+ (Machine == IMAGE_FILE_MACHINE_ARM64) || (Machine == IMAGE_FILE_MACHINE_EBC)) {
return TRUE;
}
--
1.9.1
Olivier Martin
2015-07-06 10:07:58 UTC
Permalink
Reviewed-By: Olivier Martin <***@arm.com>

Harry had to do a similar clean-up when he added support for LLVM: https://github.com/ARM-software/edk2/commit/54cb35d53e691a856381efa2c0756d7bd7e2347a


-----Original Message-----
From: Ard Biesheuvel [mailto:***@linaro.org]
Sent: 03 July 2015 10:40
To: edk2-***@lists.sourceforge.net; ***@intel.com; ***@intel.com; ***@intel.com; ***@intel.com
Cc: ***@redhat.com; Olivier Martin; Ard Biesheuvel
Subject: [PATCH 1/6] MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64

The AARCH64 specific implementations of PeCoffLoaderRelocateImageEx and PeHotRelocateImageEx only handle EFI_IMAGE_REL_BASED_DIR64 relocations.
Since these are already handled by the respective callers, this is essentially dead code and can be removed.

So add IMAGE_FILE_MACHINE_ARM64 support to the list of supported machines of the generic version, and use it for AARCH64 as well.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 4 +-
3 files changed, 3 insertions(+), 133 deletions(-)

diff --git a/MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
deleted file mode 100644
index 7e4b4db45328..000000000000
--- a/MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
+++ /dev/null
@@ -1,127 +0,0 @@
-/** @file
- Specific relocation fixups for ARM architecture.
-
- Copyright (c) 2006 - 2009, Intel Corporation. All rights reserved.<BR>
- Portions copyright (c) 2008 - 2010, Apple Inc. All rights reserved.<BR>
- Portions copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>
-
- This program and the accompanying materials
- are licensed and made available under the terms and conditions of the BSD License
- which accompanies this distribution. The full text of the license may be found at
- http://opensource.org/licenses/bsd-license.php.
-
- THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
- WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
-
-**/
-
-#include "BasePeCoffLibInternals.h"
-#include <Library/BaseLib.h>
-
-// Note: Currently only large memory model is supported by UEFI relocation code.
-
-/**
- Performs an AARCH64-based specific relocation fixup and is a no-op on other
- instruction sets.
-
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
-
- @return Status code.
-
-**/
-RETURN_STATUS
-PeCoffLoaderRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
- )
-{
- UINT64 *Fixup64;
-
- switch ((*Reloc) >> 12) {
-
- case EFI_IMAGE_REL_BASED_DIR64:
- Fixup64 = (UINT64 *) Fixup;
- *Fixup64 = *Fixup64 + (UINT64) Adjust;
- if (*FixupData != NULL) {
- *FixupData = ALIGN_POINTER(*FixupData, sizeof(UINT64));
- *(UINT64 *)(*FixupData) = *Fixup64;
- *FixupData = *FixupData + sizeof(UINT64);
- }
- break;
-
- default:
- return RETURN_UNSUPPORTED;
- }
-
- return RETURN_SUCCESS;
-}
-
-/**
- Returns TRUE if the machine type of PE/COFF image is supported. Supported
- does not mean the image can be executed it means the PE/COFF loader supports
- loading and relocating of the image type. It's up to the caller to support
- the entry point.
-
- @param Machine Machine type from the PE Header.
-
- @return TRUE if this PE/COFF loader can load the image
-
-**/
-BOOLEAN
-PeCoffLoaderImageFormatSupported (
- IN UINT16 Machine
- )
-{
- if ((Machine == IMAGE_FILE_MACHINE_ARM64) || (Machine == IMAGE_FILE_MACHINE_EBC)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Performs an ARM-based specific re-relocation fixup and is a no-op on other
- instruction sets. This is used to re-relocated the image into the EFI virtual
- space for runtime calls.
-
- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
-
- @return Status code.
-
-**/
-RETURN_STATUS
-PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
- )
-{
- UINT64 *Fixup64;
-
- switch ((*Reloc) >> 12) {
- case EFI_IMAGE_REL_BASED_DIR64:
- Fixup64 = (UINT64 *) Fixup;
- *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
- if (*(UINT64 *) (*FixupData) == *Fixup64) {
- *Fixup64 = *Fixup64 + (UINT64) Adjust;
- }
-
- *FixupData = *FixupData + sizeof (UINT64);
- break;
-
- default:
- DEBUG ((EFI_D_ERROR, "PeHotRelocateEx:unknown fixed type\n"));
- return RETURN_UNSUPPORTED;
- }
-
- return RETURN_SUCCESS;
-}
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
index 576d72826c32..ff0580fbdf56 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf
@@ -40,7 +40,7 @@ [Sources]
BasePeCoffLibInternals.h
BasePeCoff.c

-[Sources.IA32, Sources.X64, Sources.EBC]
+[Sources.IA32, Sources.X64, Sources.EBC, Sources.AARCH64]
PeCoffLoaderEx.c

[Sources.IPF]
@@ -49,9 +49,6 @@ [Sources.IPF]
[Sources.ARM]
Arm/PeCoffLoaderEx.c

-[Sources.AARCH64]
- AArch64/PeCoffLoaderEx.c
-
[Packages]
MdePkg/MdePkg.dec

diff --git a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
index 2ed58844d5d4..01825c85392b 100644
--- a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
@@ -44,7 +44,7 @@ PeCoffLoaderRelocateImageEx (
loading and relocating of the image type. It's up to the caller to support
the entry point.

- The IA32/X64 version PE/COFF loader/relocater both support IA32, X64 and EBC images.
+ The generic version PE/COFF loader/relocater supports IA32, X64, AARCH64 and EBC images.

@param Machine The machine type from the PE Header.

@@ -57,7 +57,7 @@ PeCoffLoaderImageFormatSupported (
)
{
if ((Machine == IMAGE_FILE_MACHINE_I386) || (Machine == IMAGE_FILE_MACHINE_X64) ||
- (Machine == IMAGE_FILE_MACHINE_EBC)) {
+ (Machine == IMAGE_FILE_MACHINE_ARM64) || (Machine ==
+ IMAGE_FILE_MACHINE_EBC)) {
return TRUE;
}

--
1.9.1


-- IMPORTANT NOTICE: The contents of this email and any attachments are confidential and may also be privileged. If you are not the intended recipient, please notify the sender immediately and do not disclose the contents to any other person, use it for any purpose, or store or copy the information in any medium. Thank you.

ARM Limited, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2557590
ARM Holdings plc, Registered office 110 Fulbourn Road, Cambridge CB1 9NJ, Registered in England & Wales, Company No: 2548782
Ard Biesheuvel
2015-07-03 09:40:03 UTC
Permalink
The IPF implementation of PeHotRelocateImageEx () handles relocations
of type EFI_IMAGE_REL_BASED_DIR64. However, since the caller already
handles this type, this is essentially dead code and can be removed.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 10 ----------
1 file changed, 10 deletions(-)

diff --git a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
index 96e122b69814..a590f3906fab 100644
--- a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
@@ -267,16 +267,6 @@ PeHotRelocateImageEx (
UINT64 FixupVal;

switch ((*Reloc) >> 12) {
- case EFI_IMAGE_REL_BASED_DIR64:
- Fixup64 = (UINT64 *) Fixup;
- *FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
- if (*(UINT64 *) (*FixupData) == *Fixup64) {
- *Fixup64 = *Fixup64 + (UINT64) Adjust;
- }
-
- *FixupData = *FixupData + sizeof (UINT64);
- break;
-
case EFI_IMAGE_REL_BASED_IA64_IMM64:
Fixup64 = (UINT64 *) Fixup;
*FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
--
1.9.1
Ard Biesheuvel
2015-07-03 09:40:04 UTC
Permalink
Relocations of types EFI_IMAGE_REL_BASED_HIGH and EFI_IMAGE_REL_BASED_LOW
occur in pairs, where each of the pair relocates a 16-bit word half of a
32-bit dword.

Since the target of the relocation arithmetic is a 32-bit quantity,
we should handle a carry that may occur in the low word relocation,
by taking the carry into account when relocating the high word.

Since we know the relocation pair refers to a single value, we can
simply perform the addition for the entire value when handling the high
relocation, and truncate the result to 16-bits.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index 33cad23a014e..28c84062d125 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -1103,7 +1103,8 @@ PeCoffLoaderRelocateImage (

case EFI_IMAGE_REL_BASED_HIGH:
Fixup16 = (UINT16 *) Fixup;
- *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
+ Fixup32 = (UINT32 *) (Fixup16 - 1);
+ *Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) >> 16);
if (FixupData != NULL) {
*(UINT16 *) FixupData = *Fixup16;
FixupData = FixupData + sizeof (UINT16);
@@ -1828,8 +1829,9 @@ PeCoffLoaderRelocateImageForRuntime (

case EFI_IMAGE_REL_BASED_HIGH:
Fixup16 = (UINT16 *) Fixup;
+ Fixup32 = (UINT32 *) (Fixup16 - 1);
if (*(UINT16 *) FixupData == *Fixup16) {
- *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));
+ *Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) >> 16);
}

FixupData = FixupData + sizeof (UINT16);
--
1.9.1
Ard Biesheuvel
2015-07-03 09:40:05 UTC
Permalink
PeCoffLoaderRelocateImageForRuntime () reapplies relocations to
prepare PE/COFF images for being invoked via a runtime virtual
mapping. Since the image has already been executed at this point,
it takes care to only update pointers that hold the same value they
held at image load time.

However, this check is incorrect for pairs of EFI_IMAGE_REL_BASED_HIGH
and EFI_IMAGE_REL_BASED_LOW relocations, since the check does not take
into account that the update may have affected only the other half of
the 32-bit word the pair refers to. For instance, if the load time
value and the current value are different in absolute value but equal
modulo 64 KB, the EFI_IMAGE_REL_BASED_LOW will be reapplied
inadvertently.

So record the entire 32-bit value in the fixup data for each of the
relocations, and compare the entire 32-bit value before applying
either of the them. To handle false negatives in the comparisons that
occur when the other relocation of a pair has been handled already,
keep a per-page record of which 32-bit words have been partially
relocated.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 47 ++++++++++++++++----
1 file changed, 38 insertions(+), 9 deletions(-)

diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index 28c84062d125..23cb691ad729 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -1106,17 +1106,20 @@ PeCoffLoaderRelocateImage (
Fixup32 = (UINT32 *) (Fixup16 - 1);
*Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) >> 16);
if (FixupData != NULL) {
- *(UINT16 *) FixupData = *Fixup16;
- FixupData = FixupData + sizeof (UINT16);
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
+ *(UINT32 *) FixupData = *Fixup32 + (UINT32) Adjust;
+ FixupData = FixupData + sizeof (UINT32);
}
break;

case EFI_IMAGE_REL_BASED_LOW:
Fixup16 = (UINT16 *) Fixup;
- *Fixup16 = (UINT16) (*Fixup16 + (UINT16) Adjust);
+ Fixup32 = (UINT32 *) Fixup16;
+ *Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) & 0xffff);
if (FixupData != NULL) {
- *(UINT16 *) FixupData = *Fixup16;
- FixupData = FixupData + sizeof (UINT16);
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
+ *(UINT32 *) FixupData = *Fixup32 + (UINT32) Adjust;
+ FixupData = FixupData + sizeof (UINT32);
}
break;

@@ -1725,6 +1728,8 @@ PeCoffLoaderRelocateImageForRuntime (
UINTN Adjust;
RETURN_STATUS Status;
UINT16 Magic;
+ UINT8 HighLowMask [SIZE_4KB / (8 * sizeof(UINT32))];
+ UINTN HighLowMaskIndex;

OldBase = (CHAR8 *)((UINTN)ImageBase);
NewBase = (CHAR8 *)((UINTN)VirtImageBase);
@@ -1816,6 +1821,8 @@ PeCoffLoaderRelocateImageForRuntime (
RelocEnd = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);
FixupBase = (CHAR8 *) ((UINTN)ImageBase) + RelocBase->VirtualAddress;

+ ZeroMem (HighLowMask, sizeof (HighLowMask));
+
//
// Run this relocation record
//
@@ -1830,20 +1837,42 @@ PeCoffLoaderRelocateImageForRuntime (
case EFI_IMAGE_REL_BASED_HIGH:
Fixup16 = (UINT16 *) Fixup;
Fixup32 = (UINT32 *) (Fixup16 - 1);
- if (*(UINT16 *) FixupData == *Fixup16) {
+ HighLowMaskIndex = ((UINTN) Fixup32 & SIZE_4KB) >> 2;
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
+ if (*(UINT32 *) FixupData == *Fixup32 ||
+ (HighLowMask [HighLowMaskIndex >> 3] & (1 << (HighLowMaskIndex & 7))) != 0) {
+
*Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) >> 16);
+
+ //
+ // Mark this location in the page as requiring the low relocation to
+ // be reapplied as well. This is necessary since the *Fixup comparison
+ // with its FixupData will fail now that we have updated the high word.
+ //
+ HighLowMask [HighLowMaskIndex >> 3] |= (1 << (HighLowMaskIndex & 7));
}

- FixupData = FixupData + sizeof (UINT16);
+ FixupData = FixupData + sizeof (UINT32);
break;

case EFI_IMAGE_REL_BASED_LOW:
Fixup16 = (UINT16 *) Fixup;
- if (*(UINT16 *) FixupData == *Fixup16) {
+ HighLowMaskIndex = ((UINTN) Fixup16 & SIZE_4KB) >> 2;
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
+ if (*(UINT32 *) FixupData == *(UINT32 *)Fixup ||
+ (HighLowMask [HighLowMaskIndex >> 3] & (1 << (HighLowMaskIndex & 7))) != 0) {
+
*Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
+
+ //
+ // Mark this location in the page as requiring the high relocation to
+ // be reapplied as well. This is necessary since the *Fixup comparison
+ // with its FixupData will fail now that we have updated the low word.
+ //
+ HighLowMask [HighLowMaskIndex >> 3] |= (1 << (HighLowMaskIndex & 7));
}

- FixupData = FixupData + sizeof (UINT16);
+ FixupData = FixupData + sizeof (UINT32);
break;

case EFI_IMAGE_REL_BASED_HIGHLOW:
--
1.9.1
Ard Biesheuvel
2015-07-03 09:40:06 UTC
Permalink
The OS is not required to preserve the relative offsets between
RuntimeServicesCode and RuntimeServicesData memory regions when
switching to virtual mode. This does not present any problems as
long as PE/COFF images in memory are covered by only a single region.

However, with the introduction of the MemoryProtectionAttribute feature
in UEFI v2.5, the firmware may decide to split those regions into
separate code and data regions. So rather than reapplying the relocations
for the entire image based on a single adjustment value (which is derived
from the physical to virtual shift of ImageBase), we need to invoke
ConvertPointer () on each relocation target.

So modify PeCoffLoaderRelocateImageForRuntime () to take a callback
function pointer instead of a fixed adjustment value, and invoke the
callback for each re-relocated value.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdePkg/Include/Library/PeCoffLib.h | 28 ++++++++++++----
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 ++++++-----
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 35 +++++++++++---------
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 ++++-----
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 32 +++++++++---------
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 16 ++++-----
6 files changed, 83 insertions(+), 63 deletions(-)

diff --git a/MdePkg/Include/Library/PeCoffLib.h b/MdePkg/Include/Library/PeCoffLib.h
index 9ed6d61be01c..ed75f3613306 100644
--- a/MdePkg/Include/Library/PeCoffLib.h
+++ b/MdePkg/Include/Library/PeCoffLib.h
@@ -335,6 +335,22 @@ PeCoffLoaderImageReadFromMemory (
OUT VOID *Buffer
);

+/**
+ Translates a physical to virtual address for PE/COFF runtime re-relocation
+
+ @param[in, out] Address A pointer to a pointer that is to be fixed to be the value needed
+ for the new virtual address mappings being applied.
+
+ @retval EFI_SUCCESS The pointer pointed to by Address was modified.
+ @retval EFI_INVALID_PARAMETER Address is NULL.
+ @retval EFI_NOT_FOUND The value pointed to by Address could not be converted.
+
+**/
+typedef
+RETURN_STATUS
+(EFIAPI *PE_COFF_LOADER_CONVERT_POINTER) (
+ IN OUT VOID **Address
+ );

/**
Reapply fixups on a fixed up PE32/PE32+ image to allow virutal calling at EFI
@@ -352,8 +368,8 @@ PeCoffLoaderImageReadFromMemory (

@param ImageBase The base address of a PE/COFF image that has been loaded
and relocated into system memory.
- @param VirtImageBase The request virtual address that the PE/COFF image is to
- be fixed up for.
+ @param ConvertPointer Address of a PE_COFF_LOADER_CONVERT_POINTER callback function
+ that performs physical to virtual conversions
@param ImageSize The size, in bytes, of the PE/COFF image.
@param RelocationData A pointer to the relocation data that was collected when the PE/COFF
image was relocated using PeCoffLoaderRelocateImage().
@@ -362,10 +378,10 @@ PeCoffLoaderImageReadFromMemory (
VOID
EFIAPI
PeCoffLoaderRelocateImageForRuntime (
- IN PHYSICAL_ADDRESS ImageBase,
- IN PHYSICAL_ADDRESS VirtImageBase,
- IN UINTN ImageSize,
- IN VOID *RelocationData
+ IN PHYSICAL_ADDRESS ImageBase,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer,
+ IN UINTN ImageSize,
+ IN VOID *RelocationData
);

/**
diff --git a/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
index d6bf42738d2b..ba09e1f16018 100644
--- a/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c
@@ -205,20 +205,20 @@ PeCoffLoaderImageFormatSupported (
instruction sets. This is used to re-relocated the image into the EFI virtual
space for runtime calls.

- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function

@return Status code.

**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
)
{
UINT16 *Fixup16;
@@ -231,7 +231,8 @@ PeHotRelocateImageEx (
case EFI_IMAGE_REL_BASED_ARM_MOV32T:
*FixupData = ALIGN_POINTER (*FixupData, sizeof (UINT64));
if (*(UINT64 *) (*FixupData) == ReadUnaligned64 ((UINT64 *)Fixup16)) {
- FixupVal = ThumbMovwMovtImmediateAddress (Fixup16) + (UINT32)Adjust;
+ FixupVal = ThumbMovwMovtImmediateAddress (Fixup16);
+ ConvertPointer ((VOID **) &FixupVal);
ThumbMovwMovtImmediatePatch (Fixup16, FixupVal);
}
break;
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
index 23cb691ad729..e4de6fae7ce9 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoff.c
@@ -1692,8 +1692,8 @@ PeCoffLoaderLoadImage (

@param ImageBase The base address of a PE/COFF image that has been loaded
and relocated into system memory.
- @param VirtImageBase The request virtual address that the PE/COFF image is to
- be fixed up for.
+ @param ConvertPointer Address of a PE_COFF_LOADER_CONVERT_POINTER callback function
+ that performs physical to virtual conversions
@param ImageSize The size, in bytes, of the PE/COFF image.
@param RelocationData A pointer to the relocation data that was collected when the PE/COFF
image was relocated using PeCoffLoaderRelocateImage().
@@ -1702,14 +1702,13 @@ PeCoffLoaderLoadImage (
VOID
EFIAPI
PeCoffLoaderRelocateImageForRuntime (
- IN PHYSICAL_ADDRESS ImageBase,
- IN PHYSICAL_ADDRESS VirtImageBase,
- IN UINTN ImageSize,
- IN VOID *RelocationData
+ IN PHYSICAL_ADDRESS ImageBase,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer,
+ IN UINTN ImageSize,
+ IN VOID *RelocationData
)
{
CHAR8 *OldBase;
- CHAR8 *NewBase;
EFI_IMAGE_DOS_HEADER *DosHdr;
EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
UINT32 NumberOfRvaAndSizes;
@@ -1725,15 +1724,13 @@ PeCoffLoaderRelocateImageForRuntime (
UINT32 *Fixup32;
UINT64 *Fixup64;
CHAR8 *FixupData;
- UINTN Adjust;
RETURN_STATUS Status;
UINT16 Magic;
UINT8 HighLowMask [SIZE_4KB / (8 * sizeof(UINT32))];
UINTN HighLowMaskIndex;
+ UINTN ConvertAddress;

OldBase = (CHAR8 *)((UINTN)ImageBase);
- NewBase = (CHAR8 *)((UINTN)VirtImageBase);
- Adjust = (UINTN) NewBase - (UINTN) OldBase;

//
// Find the image's relocate dir info
@@ -1842,7 +1839,9 @@ PeCoffLoaderRelocateImageForRuntime (
if (*(UINT32 *) FixupData == *Fixup32 ||
(HighLowMask [HighLowMaskIndex >> 3] & (1 << (HighLowMaskIndex & 7))) != 0) {

- *Fixup16 = (UINT16) ((*Fixup32 + (UINT32) Adjust) >> 16);
+ ConvertAddress = *(UINT32 *) FixupData;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup16 = (UINT16) (ConvertAddress >> 16);

//
// Mark this location in the page as requiring the low relocation to
@@ -1862,7 +1861,9 @@ PeCoffLoaderRelocateImageForRuntime (
if (*(UINT32 *) FixupData == *(UINT32 *)Fixup ||
(HighLowMask [HighLowMaskIndex >> 3] & (1 << (HighLowMaskIndex & 7))) != 0) {

- *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));
+ ConvertAddress = *(UINT32 *) FixupData;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup16 = (UINT16) (ConvertAddress & 0xffff);

//
// Mark this location in the page as requiring the high relocation to
@@ -1879,7 +1880,9 @@ PeCoffLoaderRelocateImageForRuntime (
Fixup32 = (UINT32 *) Fixup;
FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));
if (*(UINT32 *) FixupData == *Fixup32) {
- *Fixup32 = *Fixup32 + (UINT32) Adjust;
+ ConvertAddress = *Fixup32;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup32 = (UINT32) ConvertAddress;
}

FixupData = FixupData + sizeof (UINT32);
@@ -1889,7 +1892,9 @@ PeCoffLoaderRelocateImageForRuntime (
Fixup64 = (UINT64 *)Fixup;
FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
if (*(UINT64 *) FixupData == *Fixup64) {
- *Fixup64 = *Fixup64 + (UINT64)Adjust;
+ ConvertAddress = (UINTN) *Fixup64;
+ ConvertPointer ((VOID **) &ConvertAddress);
+ *Fixup64 = ConvertAddress;
}

FixupData = FixupData + sizeof (UINT64);
@@ -1899,7 +1904,7 @@ PeCoffLoaderRelocateImageForRuntime (
//
// Only Itanium requires ConvertPeImage_Ex
//
- Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);
+ Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, ConvertPointer);
if (RETURN_ERROR (Status)) {
return ;
}
diff --git a/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h b/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
index 0851acc18c19..9ffc59318f9b 100644
--- a/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
+++ b/MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h
@@ -50,20 +50,20 @@ PeCoffLoaderRelocateImageEx (
instruction sets. This is used to re-relocated the image into the EFI virtual
space for runtime calls.

- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function

@return Status code.

**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
);


diff --git a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
index a590f3906fab..bd371a33a445 100644
--- a/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c
@@ -242,25 +242,23 @@ PeCoffLoaderImageFormatSupported (


/**
- ImageRead function that operates on a memory buffer whos base is passed into
- FileHandle.
-
- @param Reloc Ponter to baes of the input stream
- @param Fixup Offset to the start of the buffer
- @param FixupData The number of bytes to copy into the buffer
- @param Adjust Location to place results of read
-
- @retval RETURN_SUCCESS Data is read from FileOffset from the Handle into
- the buffer.
- @retval RETURN_UNSUPPORTED Un-recoganized relocation entry
- type.
+ Performs an Itanium-based specific re-relocation fixup and is a no-op on other
+ instruction sets. This is used to re-relocated the image into the EFI virtual
+ space for runtime calls.
+
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function
+
+ @return Status code.
**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
)
{
UINT64 *Fixup64;
@@ -325,7 +323,7 @@ PeHotRelocateImageEx (
//
// Update 64-bit address
//
- FixupVal += Adjust;
+ ConvertPointer ((VOID **) &FixupVal);

//
// Insert IMM64 into bundle
diff --git a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
index 01825c85392b..8ddf6fe722f8 100644
--- a/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
+++ b/MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c
@@ -69,20 +69,20 @@ PeCoffLoaderImageFormatSupported (
instruction sets. This is used to re-relocated the image into the EFI virtual
space for runtime calls.

- @param Reloc The pointer to the relocation record.
- @param Fixup The pointer to the address to fix up.
- @param FixupData The pointer to a buffer to log the fixups.
- @param Adjust The offset to adjust the fixup.
+ @param Reloc The pointer to the relocation record.
+ @param Fixup The pointer to the address to fix up.
+ @param FixupData The pointer to a buffer to log the fixups.
+ @param ConvertPointer Pointer to a physical to virtual conversion function

@return Status code.

**/
RETURN_STATUS
PeHotRelocateImageEx (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
+ IN UINT16 *Reloc,
+ IN OUT CHAR8 *Fixup,
+ IN OUT CHAR8 **FixupData,
+ IN PE_COFF_LOADER_CONVERT_POINTER ConvertPointer
)
{
return RETURN_UNSUPPORTED;
--
1.9.1
Ard Biesheuvel
2015-07-03 09:40:07 UTC
Permalink
When reapplying PE/COFF relocations for the switch to virtual mode, we
should not assume that the virtual memory image is identical to the
PE/COFF file image, since PE/COFF sections may no longer be adjacent in
virtual memory.

The prototype and implementation of PeCoffLoaderRelocateImageForRuntime
have been updated to account for this, so update the call site as well.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Ard Biesheuvel <***@linaro.org>
---
MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +++++++++++-
1 file changed, 11 insertions(+), 1 deletion(-)

diff --git a/MdeModulePkg/Core/RuntimeDxe/Runtime.c b/MdeModulePkg/Core/RuntimeDxe/Runtime.c
index c61301cf80d8..e660138f1189 100644
--- a/MdeModulePkg/Core/RuntimeDxe/Runtime.c
+++ b/MdeModulePkg/Core/RuntimeDxe/Runtime.c
@@ -212,6 +212,16 @@ RuntimeDriverConvertInternalPointer (
return RuntimeDriverConvertPointer (0x0, ConvertAddress);
}

+STATIC
+RETURN_STATUS
+EFIAPI
+RuntimeDriverConvertPecoffPointer (
+ IN OUT VOID **Address
+ )
+{
+ return (RETURN_STATUS) RuntimeDriverConvertPointer (0x0, Address);
+}
+
/**

Changes the runtime addressing mode of EFI firmware from physical to virtual.
@@ -314,7 +324,7 @@ RuntimeDriverSetVirtualAddressMap (

PeCoffLoaderRelocateImageForRuntime (
(EFI_PHYSICAL_ADDRESS) (UINTN) RuntimeImage->ImageBase,
- VirtImageBase,
+ RuntimeDriverConvertPecoffPointer,
(UINTN) RuntimeImage->ImageSize,
RuntimeImage->RelocationData
);
--
1.9.1
Gao, Liming
2015-07-06 06:25:38 UTC
Permalink
Ard:
Have you GIT branch for those changes? Then, I can easily review those changes.

Thanks
Liming
-----Original Message-----
From: Ard Biesheuvel [mailto:***@linaro.org]
Sent: Friday, July 03, 2015 5:40 PM
To: edk2-***@lists.sourceforge.net; Kinney, Michael D; Yao, Jiewen; Gao, Liming; Justen, Jordan L
Cc: ***@redhat.com; ***@arm.com; Ard Biesheuvel
Subject: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images

This is a followup to the patch I sen yesterday:
http://article.gmane.org/gmane.comp.bios.tianocore.devel/16647

I should know better than to propose changes to MdePkg, but in this case, I think the issues around the MemoryProtectionAttribute are severe enough to warrant drastic measures.

Patches #1 and #2 are cleanup patches, they remove dead code that handles relocations that are already handled by the callers of the respective functions.

Patch #3 fixes a bug in BasePeCoffLib where it fails to take into account that applying a EFI_IMAGE_REL_BASED_LOW relocation may result in a carry that needs to be taken into account when handling the corresponding EFI_IMAGE_REL_BASED_HIGH relocation.

Patch #4 works around a bug in BasePeCoffLib where the runtime re-relocation may reapply EFI_IMAGE_REL_BASED_LOW or EFI_IMAGE_REL_BASED_HIGH relocations even if the target location has been updated programmatically after the image was loaded.

Patch #5 replaces the 'Adjust' argument of PeCoffLoaderRelocateImageForRuntime
with a ConvertPointer() callback function pointer so that the runtime relocation can handle disjoint PE/COFF images in virtual memory.

Patch #6 updates RuntimeDxe to use the new PeCoffLoaderRelocateImageForRuntime
prototype.

Unfortunately, this series is not bisectable between #5 and #6. Working around that is non-trivial and probably not worth the hassle.

Ard Biesheuvel (6):
MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64
MdePkg/BasePeCoffLib: remove redundant handling of
EFI_IMAGE_REL_BASED_DIR64
MdePkg/BasePeCoffLib: account for carry in high/low relocation pairs
MdePkg/BasePeCoffLib: fix handling of high/low relocation pairs
MdePkg/BasePeCoffLib: relocate for runtime using ConvertPointer
callback
MdeModulePkg/RuntimeDxe: update to new RelocateImageForRuntime()
prototype

MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +-
MdePkg/Include/Library/PeCoffLib.h | 28 ++++-
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 +--
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 86 +++++++++----
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 +--
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 42 +++----
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 20 +--
9 files changed, 138 insertions(+), 217 deletions(-) delete mode 100644 MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c

--
1.9.1
Ard Biesheuvel
2015-07-06 07:11:50 UTC
Permalink
Post by Gao, Liming
Have you GIT branch for those changes? Then, I can easily review those changes.
Sure

I pushed it here:
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/pecoff-runtime-relocation

Thanks,
Ard.
Post by Gao, Liming
-----Original Message-----
Sent: Friday, July 03, 2015 5:40 PM
Subject: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
http://article.gmane.org/gmane.comp.bios.tianocore.devel/16647
I should know better than to propose changes to MdePkg, but in this case, I think the issues around the MemoryProtectionAttribute are severe enough to warrant drastic measures.
Patches #1 and #2 are cleanup patches, they remove dead code that handles relocations that are already handled by the callers of the respective functions.
Patch #3 fixes a bug in BasePeCoffLib where it fails to take into account that applying a EFI_IMAGE_REL_BASED_LOW relocation may result in a carry that needs to be taken into account when handling the corresponding EFI_IMAGE_REL_BASED_HIGH relocation.
Patch #4 works around a bug in BasePeCoffLib where the runtime re-relocation may reapply EFI_IMAGE_REL_BASED_LOW or EFI_IMAGE_REL_BASED_HIGH relocations even if the target location has been updated programmatically after the image was loaded.
Patch #5 replaces the 'Adjust' argument of PeCoffLoaderRelocateImageForRuntime
with a ConvertPointer() callback function pointer so that the runtime relocation can handle disjoint PE/COFF images in virtual memory.
Patch #6 updates RuntimeDxe to use the new PeCoffLoaderRelocateImageForRuntime
prototype.
Unfortunately, this series is not bisectable between #5 and #6. Working around that is non-trivial and probably not worth the hassle.
MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64
MdePkg/BasePeCoffLib: remove redundant handling of
EFI_IMAGE_REL_BASED_DIR64
MdePkg/BasePeCoffLib: account for carry in high/low relocation pairs
MdePkg/BasePeCoffLib: fix handling of high/low relocation pairs
MdePkg/BasePeCoffLib: relocate for runtime using ConvertPointer
callback
MdeModulePkg/RuntimeDxe: update to new RelocateImageForRuntime()
prototype
MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +-
MdePkg/Include/Library/PeCoffLib.h | 28 ++++-
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 +--
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 86 +++++++++----
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 +--
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 42 +++----
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 20 +--
9 files changed, 138 insertions(+), 217 deletions(-) delete mode 100644 MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
--
1.9.1
Gao, Liming
2015-07-07 01:57:25 UTC
Permalink
Ard:
So, in this case, PE image space will not be continuous. Its code and data section are in the different region. I know RelocatImage is for the absolute address data access. But, I am still curious how PE image handles the relative address data access?

For patch 1 & 2, I agree those changes.
For patch 3 & 4, I need more time to review them.
For patch 5, PeCoffLoaderRelocateImageForRuntime() API is changed. This is an incompatible change. Now, it only impacts BasePeCoffLib and RuntimeDriver. I am not sure whether there is any other code to consume/produce it.
For patch 6, how about update RuntimeDriverConvertInternalPointer() for this usage? And, remove unreferenced local variable VirtImageBase.

Thanks
Liming
-----Original Message-----
From: Ard Biesheuvel [mailto:***@linaro.org]
Sent: Monday, July 6, 2015 3:12 PM
To: Gao, Liming
Cc: edk2-***@lists.sourceforge.net; Kinney, Michael D; Yao, Jiewen; Justen, Jordan L; ***@redhat.com; ***@arm.com
Subject: Re: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
Post by Gao, Liming
Have you GIT branch for those changes? Then, I can easily review those changes.
Sure

I pushed it here:
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/pecoff-runtime-relocation

Thanks,
Ard.
Post by Gao, Liming
-----Original Message-----
Sent: Friday, July 03, 2015 5:40 PM
Subject: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
http://article.gmane.org/gmane.comp.bios.tianocore.devel/16647
I should know better than to propose changes to MdePkg, but in this case, I think the issues around the MemoryProtectionAttribute are severe enough to warrant drastic measures.
Patches #1 and #2 are cleanup patches, they remove dead code that handles relocations that are already handled by the callers of the respective functions.
Patch #3 fixes a bug in BasePeCoffLib where it fails to take into account that applying a EFI_IMAGE_REL_BASED_LOW relocation may result in a carry that needs to be taken into account when handling the corresponding EFI_IMAGE_REL_BASED_HIGH relocation.
Patch #4 works around a bug in BasePeCoffLib where the runtime re-relocation may reapply EFI_IMAGE_REL_BASED_LOW or EFI_IMAGE_REL_BASED_HIGH relocations even if the target location has been updated programmatically after the image was loaded.
Patch #5 replaces the 'Adjust' argument of PeCoffLoaderRelocateImageForRuntime
with a ConvertPointer() callback function pointer so that the runtime relocation can handle disjoint PE/COFF images in virtual memory.
Patch #6 updates RuntimeDxe to use the new PeCoffLoaderRelocateImageForRuntime
prototype.
Unfortunately, this series is not bisectable between #5 and #6. Working around that is non-trivial and probably not worth the hassle.
MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64
MdePkg/BasePeCoffLib: remove redundant handling of
EFI_IMAGE_REL_BASED_DIR64
MdePkg/BasePeCoffLib: account for carry in high/low relocation pairs
MdePkg/BasePeCoffLib: fix handling of high/low relocation pairs
MdePkg/BasePeCoffLib: relocate for runtime using ConvertPointer
callback
MdeModulePkg/RuntimeDxe: update to new RelocateImageForRuntime()
prototype
MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +-
MdePkg/Include/Library/PeCoffLib.h | 28 ++++-
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 +--
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 86 +++++++++----
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 +--
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 42 +++----
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 20 +--
9 files changed, 138 insertions(+), 217 deletions(-) delete mode 100644 MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
--
1.9.1
Ard Biesheuvel
2015-07-07 08:32:05 UTC
Permalink
Post by Gao, Liming
So, in this case, PE image space will not be continuous. Its code and data section are in the different region. I know RelocatImage is for the absolute address data access. But, I am still curious how PE image handles the relative address data access?
That is indeed the question. On non-PIC ARM and AARCH64 builds, only
branch instructions are relative, and the ELF to PE/COFF conversion
ensures that there is only a single .code segment. On other archs and
toolchains, this may not be guaranteed at all. I guess we could
enhance GenFw to disallow relative references between code and data
sections, but that does not help the non-ELF based toolchains.

Bottom line is that there is no 100% correct solution for this. Using
ConvertPointer() instead of a single adjustment value is obviously
correct for existing cases, and fixes the observed issues at least
under ArmVirtQemu and OVMF under X86.
Post by Gao, Liming
For patch 1 & 2, I agree those changes.
OK
Post by Gao, Liming
For patch 3 & 4, I need more time to review them.
OK. Note that high/low relocations are probably never used in the
first place, since the observed issues are so severe that they would
probably have been noticed by now. This also means I could not test
this code, unfortunately.
Post by Gao, Liming
For patch 5, PeCoffLoaderRelocateImageForRuntime() API is changed. This is an incompatible change. Now, it only impacts BasePeCoffLib and RuntimeDriver. I am not sure whether there is any other code to consume/produce it.
OK. We could retain the old version, and add
PeCoffLoaderRelocateImageForRuntimeEx() if you prefer?
Post by Gao, Liming
For patch 6, how about update RuntimeDriverConvertInternalPointer() for this usage? And, remove unreferenced local variable VirtImageBase.
Yes, that would work. I will change that in the next version.
--
Ard.
Post by Gao, Liming
-----Original Message-----
Sent: Monday, July 6, 2015 3:12 PM
To: Gao, Liming
Subject: Re: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
Post by Gao, Liming
Have you GIT branch for those changes? Then, I can easily review those changes.
Sure
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/pecoff-runtime-relocation
Thanks,
Ard.
Post by Gao, Liming
-----Original Message-----
Sent: Friday, July 03, 2015 5:40 PM
Subject: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
http://article.gmane.org/gmane.comp.bios.tianocore.devel/16647
I should know better than to propose changes to MdePkg, but in this case, I think the issues around the MemoryProtectionAttribute are severe enough to warrant drastic measures.
Patches #1 and #2 are cleanup patches, they remove dead code that handles relocations that are already handled by the callers of the respective functions.
Patch #3 fixes a bug in BasePeCoffLib where it fails to take into account that applying a EFI_IMAGE_REL_BASED_LOW relocation may result in a carry that needs to be taken into account when handling the corresponding EFI_IMAGE_REL_BASED_HIGH relocation.
Patch #4 works around a bug in BasePeCoffLib where the runtime re-relocation may reapply EFI_IMAGE_REL_BASED_LOW or EFI_IMAGE_REL_BASED_HIGH relocations even if the target location has been updated programmatically after the image was loaded.
Patch #5 replaces the 'Adjust' argument of PeCoffLoaderRelocateImageForRuntime
with a ConvertPointer() callback function pointer so that the runtime relocation can handle disjoint PE/COFF images in virtual memory.
Patch #6 updates RuntimeDxe to use the new PeCoffLoaderRelocateImageForRuntime
prototype.
Unfortunately, this series is not bisectable between #5 and #6. Working around that is non-trivial and probably not worth the hassle.
MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64
MdePkg/BasePeCoffLib: remove redundant handling of
EFI_IMAGE_REL_BASED_DIR64
MdePkg/BasePeCoffLib: account for carry in high/low relocation pairs
MdePkg/BasePeCoffLib: fix handling of high/low relocation pairs
MdePkg/BasePeCoffLib: relocate for runtime using ConvertPointer
callback
MdeModulePkg/RuntimeDxe: update to new RelocateImageForRuntime()
prototype
MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +-
MdePkg/Include/Library/PeCoffLib.h | 28 ++++-
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 +--
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 86 +++++++++----
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 +--
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 42 +++----
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 20 +--
9 files changed, 138 insertions(+), 217 deletions(-) delete mode 100644 MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
--
1.9.1
Gao, Liming
2015-07-08 02:31:29 UTC
Permalink
Ard:
For Patch 5 & 6, Zimmer Vincent will clarify OS-Loader on Properties Table in USWG, then provide the further direction

Thanks
Liming
-----Original Message-----
From: Ard Biesheuvel [mailto:***@linaro.org]
Sent: Tuesday, July 7, 2015 4:32 PM
To: Gao, Liming
Cc: edk2-***@lists.sourceforge.net; Kinney, Michael D; Yao, Jiewen; Justen, Jordan L; ***@redhat.com; ***@arm.com
Subject: Re: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
Post by Gao, Liming
So, in this case, PE image space will not be continuous. Its code and data section are in the different region. I know RelocatImage is for the absolute address data access. But, I am still curious how PE image handles the relative address data access?
That is indeed the question. On non-PIC ARM and AARCH64 builds, only branch instructions are relative, and the ELF to PE/COFF conversion ensures that there is only a single .code segment. On other archs and toolchains, this may not be guaranteed at all. I guess we could enhance GenFw to disallow relative references between code and data sections, but that does not help the non-ELF based toolchains.

Bottom line is that there is no 100% correct solution for this. Using
ConvertPointer() instead of a single adjustment value is obviously correct for existing cases, and fixes the observed issues at least under ArmVirtQemu and OVMF under X86.
Post by Gao, Liming
For patch 1 & 2, I agree those changes.
OK
Post by Gao, Liming
For patch 3 & 4, I need more time to review them.
OK. Note that high/low relocations are probably never used in the first place, since the observed issues are so severe that they would probably have been noticed by now. This also means I could not test this code, unfortunately.
Post by Gao, Liming
For patch 5, PeCoffLoaderRelocateImageForRuntime() API is changed. This is an incompatible change. Now, it only impacts BasePeCoffLib and RuntimeDriver. I am not sure whether there is any other code to consume/produce it.
OK. We could retain the old version, and add
PeCoffLoaderRelocateImageForRuntimeEx() if you prefer?
Post by Gao, Liming
For patch 6, how about update RuntimeDriverConvertInternalPointer() for this usage? And, remove unreferenced local variable VirtImageBase.
Yes, that would work. I will change that in the next version.

--
Ard.
Post by Gao, Liming
-----Original Message-----
Sent: Monday, July 6, 2015 3:12 PM
To: Gao, Liming
Subject: Re: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
Post by Gao, Liming
Have you GIT branch for those changes? Then, I can easily review those changes.
Sure
https://git.linaro.org/people/ard.biesheuvel/uefi-next.git/shortlog/refs/heads/pecoff-runtime-relocation
Thanks,
Ard.
Post by Gao, Liming
-----Original Message-----
Sent: Friday, July 03, 2015 5:40 PM
Subject: [PATCH 0/6] fix runtime relocation of disjoint PE/COFF images
http://article.gmane.org/gmane.comp.bios.tianocore.devel/16647
I should know better than to propose changes to MdePkg, but in this case, I think the issues around the MemoryProtectionAttribute are severe enough to warrant drastic measures.
Patches #1 and #2 are cleanup patches, they remove dead code that handles relocations that are already handled by the callers of the respective functions.
Patch #3 fixes a bug in BasePeCoffLib where it fails to take into account that applying a EFI_IMAGE_REL_BASED_LOW relocation may result in a carry that needs to be taken into account when handling the corresponding EFI_IMAGE_REL_BASED_HIGH relocation.
Patch #4 works around a bug in BasePeCoffLib where the runtime re-relocation may reapply EFI_IMAGE_REL_BASED_LOW or EFI_IMAGE_REL_BASED_HIGH relocations even if the target location has been updated programmatically after the image was loaded.
Patch #5 replaces the 'Adjust' argument of PeCoffLoaderRelocateImageForRuntime
with a ConvertPointer() callback function pointer so that the runtime relocation can handle disjoint PE/COFF images in virtual memory.
Patch #6 updates RuntimeDxe to use the new PeCoffLoaderRelocateImageForRuntime
prototype.
Unfortunately, this series is not bisectable between #5 and #6. Working around that is non-trivial and probably not worth the hassle.
MdePkg/BasePeCoffLib: remove redundant PeCoffLoaderEx.c for AARCH64
MdePkg/BasePeCoffLib: remove redundant handling of
EFI_IMAGE_REL_BASED_DIR64
MdePkg/BasePeCoffLib: account for carry in high/low relocation pairs
MdePkg/BasePeCoffLib: fix handling of high/low relocation pairs
MdePkg/BasePeCoffLib: relocate for runtime using ConvertPointer
callback
MdeModulePkg/RuntimeDxe: update to new RelocateImageForRuntime()
prototype
MdeModulePkg/Core/RuntimeDxe/Runtime.c | 12 +-
MdePkg/Include/Library/PeCoffLib.h | 28 ++++-
MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c | 127 --------------------
MdePkg/Library/BasePeCoffLib/Arm/PeCoffLoaderEx.c | 19 +--
MdePkg/Library/BasePeCoffLib/BasePeCoff.c | 86 +++++++++----
MdePkg/Library/BasePeCoffLib/BasePeCoffLib.inf | 5 +-
MdePkg/Library/BasePeCoffLib/BasePeCoffLibInternals.h | 16 +--
MdePkg/Library/BasePeCoffLib/Ipf/PeCoffLoaderEx.c | 42 +++----
MdePkg/Library/BasePeCoffLib/PeCoffLoaderEx.c | 20 +--
9 files changed, 138 insertions(+), 217 deletions(-) delete mode 100644 MdePkg/Library/BasePeCoffLib/AArch64/PeCoffLoaderEx.c
--
1.9.1
Loading...