]> git.proxmox.com Git - mirror_edk2.git/commitdiff
UefiPayloadPkg/PayloadLoader: Fix bug in locating relocation section
authorRay Ni <ray.ni@intel.com>
Tue, 29 Jun 2021 02:43:58 +0000 (10:43 +0800)
committermergify[bot] <37929162+mergify[bot]@users.noreply.github.com>
Wed, 30 Jun 2021 07:12:54 +0000 (07:12 +0000)
Per ELF spec, the DT_REL/DT_RELA tag in dynamic section stores the
virtual address of the relocation section.

But today's code logic treats it as the section offset and finds
the relocation section whose offset equals to DT_REL/DT_RELA.

The logic can work when the section offset equals to the section
virtual address. But when the ELF is generated from the link script
that reserves a sizeof(pe_header) in the file beginning, the section
offset doesn't equal to section virtual address. Such logic can
not find the relocation section.

The patch fixes this bug.

Signed-off-by: Ray Ni <ray.ni@intel.com>
Cc: Maurice Ma <maurice.ma@intel.com>
Reviewed-by: Guo Dong <guo.dong@intel.com>
Cc: Benjamin You <benjamin.you@intel.com>
UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf32Lib.c
UefiPayloadPkg/PayloadLoaderPeim/ElfLib/Elf64Lib.c

index 3fa100ce4a3b8a0885198ac90db43f744e1587e1..dd27d3ce5938049bba8fa6c50c4cbc8e06217bd3 100644 (file)
@@ -206,7 +206,7 @@ RelocateElf32Dynamic (
   Elf32_Shdr                   *DynShdr;\r
   Elf32_Shdr                   *RelShdr;\r
   Elf32_Dyn                    *Dyn;\r
-  UINT32                       RelaOffset;\r
+  UINT32                       RelaAddress;\r
   UINT32                       RelaCount;\r
   UINT32                       RelaSize;\r
   UINT32                       RelaEntrySize;\r
@@ -246,7 +246,7 @@ RelocateElf32Dynamic (
   //\r
   // 2. Locate the relocation section from the dynamic section.\r
   //\r
-  RelaOffset    = MAX_UINT32;\r
+  RelaAddress   = MAX_UINT32;\r
   RelaSize      = 0;\r
   RelaCount     = 0;\r
   RelaEntrySize = 0;\r
@@ -265,8 +265,8 @@ RelocateElf32Dynamic (
         // based on the original file value and the memory base address.\r
         // For consistency, files do not contain relocation entries to ``correct'' addresses in the dynamic structure.\r
         //\r
-        RelaOffset = Dyn->d_un.d_ptr - (UINT32) (UINTN) ElfCt->PreferredImageAddress;\r
-        RelaType   = (Dyn->d_tag == DT_RELA) ? SHT_RELA: SHT_REL;\r
+        RelaAddress = Dyn->d_un.d_ptr;\r
+        RelaType    = (Dyn->d_tag == DT_RELA) ? SHT_RELA: SHT_REL;\r
         break;\r
       case DT_RELACOUNT:\r
       case DT_RELCOUNT:\r
@@ -285,7 +285,7 @@ RelocateElf32Dynamic (
     }\r
   }\r
 \r
-  if (RelaOffset == MAX_UINT64) {\r
+  if (RelaAddress == MAX_UINT64) {\r
     ASSERT (RelaCount     == 0);\r
     ASSERT (RelaEntrySize == 0);\r
     ASSERT (RelaSize      == 0);\r
@@ -298,8 +298,16 @@ RelocateElf32Dynamic (
   //\r
   // Verify the existence of the relocation section.\r
   //\r
-  RelShdr = GetElf32SectionByRange (ElfCt->FileBase, RelaOffset, RelaSize);\r
-  ASSERT (RelShdr != NULL);\r
+  RelShdr = NULL;\r
+  for (Index = 0; Index < ElfCt->ShNum; Index++) {\r
+    RelShdr = GetElf32SectionByIndex (ElfCt->FileBase, Index);\r
+    ASSERT (RelShdr != NULL);\r
+    if ((RelShdr->sh_addr == RelaAddress) && (RelShdr->sh_size == RelaSize)) {\r
+      break;\r
+    }\r
+    RelShdr = NULL;\r
+  }\r
+\r
   if (RelShdr == NULL) {\r
     return EFI_UNSUPPORTED;\r
   }\r
index e364807007e7a8d8ac79fee2d94723e945f587d2..3f4f12903cec39c1e4e0e261b302deea5b9ade35 100644 (file)
@@ -215,7 +215,7 @@ RelocateElf64Dynamic (
   Elf64_Shdr                   *DynShdr;\r
   Elf64_Shdr                   *RelShdr;\r
   Elf64_Dyn                    *Dyn;\r
-  UINT64                       RelaOffset;\r
+  UINT64                       RelaAddress;\r
   UINT64                       RelaCount;\r
   UINT64                       RelaSize;\r
   UINT64                       RelaEntrySize;\r
@@ -255,7 +255,7 @@ RelocateElf64Dynamic (
   //\r
   // 2. Locate the relocation section from the dynamic section.\r
   //\r
-  RelaOffset    = MAX_UINT64;\r
+  RelaAddress    = MAX_UINT64;\r
   RelaSize      = 0;\r
   RelaCount     = 0;\r
   RelaEntrySize = 0;\r
@@ -274,8 +274,8 @@ RelocateElf64Dynamic (
         // based on the original file value and the memory base address.\r
         // For consistency, files do not contain relocation entries to ``correct'' addresses in the dynamic structure.\r
         //\r
-        RelaOffset = Dyn->d_un.d_ptr - (UINTN) ElfCt->PreferredImageAddress;\r
-        RelaType   = (Dyn->d_tag == DT_RELA) ? SHT_RELA: SHT_REL;\r
+        RelaAddress = Dyn->d_un.d_ptr;\r
+        RelaType    = (Dyn->d_tag == DT_RELA) ? SHT_RELA: SHT_REL;\r
         break;\r
       case DT_RELACOUNT:\r
       case DT_RELCOUNT:\r
@@ -294,7 +294,7 @@ RelocateElf64Dynamic (
     }\r
   }\r
 \r
-  if (RelaOffset == MAX_UINT64) {\r
+  if (RelaAddress == MAX_UINT64) {\r
     ASSERT (RelaCount     == 0);\r
     ASSERT (RelaEntrySize == 0);\r
     ASSERT (RelaSize      == 0);\r
@@ -307,8 +307,16 @@ RelocateElf64Dynamic (
   //\r
   // Verify the existence of the relocation section.\r
   //\r
-  RelShdr = GetElf64SectionByRange (ElfCt->FileBase, RelaOffset, RelaSize);\r
-  ASSERT (RelShdr != NULL);\r
+  RelShdr = NULL;\r
+  for (Index = 0; Index < ElfCt->ShNum; Index++) {\r
+    RelShdr = GetElf64SectionByIndex (ElfCt->FileBase, Index);\r
+    ASSERT (RelShdr != NULL);\r
+    if ((RelShdr->sh_addr == RelaAddress) && (RelShdr->sh_size == RelaSize)) {\r
+      break;\r
+    }\r
+    RelShdr = NULL;\r
+  }\r
+\r
   if (RelShdr == NULL) {\r
     return EFI_UNSUPPORTED;\r
   }\r