]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffLib/BasePeCoff.c
MdePkg/BasePeCoffLib: skip runtime relocation if reloc info is invalid
[mirror_edk2.git] / MdePkg / Library / BasePeCoffLib / BasePeCoff.c
index 32eca0ad2ef4062bd02c5f5c0edff04076fdf170..e2c62e1932a3b7226c4bee1ca177033a5587c4f0 100644 (file)
@@ -15,7 +15,7 @@
   PeCoffLoaderGetPeHeader() routine will do basic check for PE/COFF header.\r
   PeCoffLoaderGetImageInfo() routine will do basic check for whole PE/COFF image.\r
 \r
-  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.<BR>\r
   Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -46,36 +46,6 @@ PeCoffLoaderAdjustOffsetForTeImage (
   SectionHeader->PointerToRawData -= TeStrippedOffset;\r
 }\r
 \r
-/**\r
-  Retrieves the magic value from the PE/COFF header.\r
-\r
-  @param  Hdr             The buffer in which to return the PE32, PE32+, or TE header.\r
-\r
-  @return EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC - Image is PE32\r
-  @return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC - Image is PE32+\r
-\r
-**/\r
-UINT16\r
-PeCoffLoaderGetPeHeaderMagicValue (\r
-  IN  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr\r
-  )\r
-{\r
-  //\r
-  // NOTE: Some versions of Linux ELILO for Itanium have an incorrect magic value\r
-  //       in the PE/COFF Header.  If the MachineType is Itanium(IA64) and the\r
-  //       Magic value in the OptionalHeader is  EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC\r
-  //       then override the returned value to EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC\r
-  //\r
-  if (Hdr.Pe32->FileHeader.Machine == IMAGE_FILE_MACHINE_IA64 && Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
-    return EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-  }\r
-  //\r
-  // Return the magic value from the PC/COFF Optional Header\r
-  //\r
-  return Hdr.Pe32->OptionalHeader.Magic;\r
-}\r
-\r
-\r
 /**\r
   Retrieves the PE or TE Header from a PE/COFF or TE image.\r
 \r
@@ -101,7 +71,6 @@ PeCoffLoaderGetPeHeader (
   EFI_IMAGE_DOS_HEADER  DosHdr;\r
   UINTN                 Size;\r
   UINTN                 ReadSize;\r
-  UINT16                Magic;\r
   UINT32                SectionHeaderOffset;\r
   UINT32                Index;\r
   UINT32                HeaderWithoutDataDir;\r
@@ -222,9 +191,7 @@ PeCoffLoaderGetPeHeader (
     ImageContext->IsTeImage = FALSE;\r
     ImageContext->Machine = Hdr.Pe32->FileHeader.Machine;\r
 \r
-    Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
-\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // 1. Check OptionalHeader.NumberOfRvaAndSizes filed.\r
       //\r
@@ -339,7 +306,7 @@ PeCoffLoaderGetPeHeader (
       ImageContext->SectionAlignment  = Hdr.Pe32->OptionalHeader.SectionAlignment;\r
       ImageContext->SizeOfHeaders     = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
 \r
-    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
+    } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
       //\r
       // 1. Check FileHeader.NumberOfRvaAndSizes filed.\r
       //\r
@@ -605,7 +572,6 @@ PeCoffLoaderGetImageInfo (
   EFI_IMAGE_SECTION_HEADER              SectionHeader;\r
   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       DebugEntry;\r
   UINT32                                NumberOfRvaAndSizes;\r
-  UINT16                                Magic;\r
   UINT32                                TeStrippedOffset;\r
 \r
   if (ImageContext == NULL) {\r
@@ -622,14 +588,12 @@ PeCoffLoaderGetImageInfo (
     return Status;\r
   }\r
 \r
-  Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
-\r
   //\r
   // Retrieve the base address of the image\r
   //\r
   if (!(ImageContext->IsTeImage)) {\r
     TeStrippedOffset = 0;\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
@@ -678,7 +642,7 @@ PeCoffLoaderGetImageInfo (
   }\r
 \r
   if (!(ImageContext->IsTeImage)) {\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
@@ -952,7 +916,6 @@ PeCoffLoaderRelocateImage (
   CHAR8                                 *FixupData;\r
   PHYSICAL_ADDRESS                      BaseAddress;\r
   UINT32                                NumberOfRvaAndSizes;\r
-  UINT16                                Magic;\r
   UINT32                                TeStrippedOffset;\r
 \r
   ASSERT (ImageContext != NULL);\r
@@ -985,9 +948,8 @@ PeCoffLoaderRelocateImage (
   if (!(ImageContext->IsTeImage)) {\r
     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
     TeStrippedOffset = 0;\r
-    Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
 \r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
@@ -1040,7 +1002,7 @@ PeCoffLoaderRelocateImage (
                                                                             RelocDir->VirtualAddress + RelocDir->Size - 1,\r
                                                                             TeStrippedOffset\r
                                                                             );\r
-    if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {\r
+    if (RelocBase == NULL || RelocBaseEnd == NULL || (UINTN) RelocBaseEnd < (UINTN) RelocBase) {\r
       ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
       return RETURN_LOAD_ERROR;\r
     }\r
@@ -1060,7 +1022,7 @@ PeCoffLoaderRelocateImage (
     // Run the relocation information and apply the fixups\r
     //\r
     FixupData = ImageContext->FixupData;\r
-    while (RelocBase < RelocBaseEnd) {\r
+    while ((UINTN) RelocBase < (UINTN) RelocBaseEnd) {\r
 \r
       Reloc     = (UINT16 *) ((CHAR8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
       //\r
@@ -1089,7 +1051,7 @@ PeCoffLoaderRelocateImage (
       //\r
       // Run this relocation record\r
       //\r
-      while (Reloc < RelocEnd) {\r
+      while ((UINTN) Reloc < (UINTN) RelocEnd) {\r
         Fixup = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), TeStrippedOffset);\r
         if (Fixup == NULL) {\r
           ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
@@ -1230,7 +1192,6 @@ PeCoffLoaderLoadImage (
   UINTN                                 Size;\r
   UINT32                                TempDebugEntryRva;\r
   UINT32                                NumberOfRvaAndSizes;\r
-  UINT16                                Magic;\r
   EFI_IMAGE_RESOURCE_DIRECTORY          *ResourceDirectory;\r
   EFI_IMAGE_RESOURCE_DIRECTORY_ENTRY    *ResourceDirectoryEntry;\r
   EFI_IMAGE_RESOURCE_DIRECTORY_STRING   *ResourceDirectoryString;\r
@@ -1404,12 +1365,11 @@ PeCoffLoaderLoadImage (
   //\r
   // Get image's entry point\r
   //\r
-  Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
   if (!(ImageContext->IsTeImage)) {\r
     //\r
     // Sizes of AddressOfEntryPoint are different so we need to do this safely\r
     //\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
@@ -1444,7 +1404,7 @@ PeCoffLoaderLoadImage (
   // the optional header to verify a desired directory entry is there.\r
   //\r
   if (!(ImageContext->IsTeImage)) {\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
@@ -1565,7 +1525,7 @@ PeCoffLoaderLoadImage (
   //\r
   ImageContext->HiiResourceData = 0;\r
   if (!(ImageContext->IsTeImage)) {\r
-    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+    if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
       //\r
       // Use PE32 offset\r
       //\r
@@ -1711,6 +1671,7 @@ PeCoffLoaderRelocateImageForRuntime (
   EFI_IMAGE_DATA_DIRECTORY            *RelocDir;\r
   EFI_IMAGE_BASE_RELOCATION           *RelocBase;\r
   EFI_IMAGE_BASE_RELOCATION           *RelocBaseEnd;\r
+  EFI_IMAGE_BASE_RELOCATION           *RelocBaseOrig;\r
   UINT16                              *Reloc;\r
   UINT16                              *RelocEnd;\r
   CHAR8                               *Fixup;\r
@@ -1721,12 +1682,19 @@ PeCoffLoaderRelocateImageForRuntime (
   CHAR8                               *FixupData;\r
   UINTN                               Adjust;\r
   RETURN_STATUS                       Status;\r
-  UINT16                              Magic;\r
+  PE_COFF_LOADER_IMAGE_CONTEXT        ImageContext;\r
+\r
+  if (RelocationData == NULL || ImageBase == 0x0 || VirtImageBase == 0x0) {\r
+    return;\r
+  }\r
 \r
   OldBase = (CHAR8 *)((UINTN)ImageBase);\r
   NewBase = (CHAR8 *)((UINTN)VirtImageBase);\r
   Adjust = (UINTN) NewBase - (UINTN) OldBase;\r
 \r
+  ImageContext.ImageAddress = ImageBase;\r
+  ImageContext.ImageSize = ImageSize;\r
+\r
   //\r
   // Find the image's relocate dir info\r
   //\r
@@ -1750,9 +1718,7 @@ PeCoffLoaderRelocateImageForRuntime (
     return ;\r
   }\r
 \r
-  Magic = PeCoffLoaderGetPeHeaderMagicValue (Hdr);\r
-\r
-  if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
+  if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
     //\r
     // Use PE32 offset\r
     //\r
@@ -1773,10 +1739,23 @@ PeCoffLoaderRelocateImageForRuntime (
   // is present in the image. You have to check the NumberOfRvaAndSizes in\r
   // the optional header to verify a desired directory entry is there.\r
   //\r
+  RelocBase = NULL;\r
+  RelocBaseEnd = NULL;\r
   if (NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
     RelocDir      = DataDirectory + EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC;\r
-    RelocBase     = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase + RelocDir->VirtualAddress);\r
-    RelocBaseEnd  = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(ImageBase + RelocDir->VirtualAddress + RelocDir->Size);\r
+    if ((RelocDir != NULL) && (RelocDir->Size > 0)) {\r
+      RelocBase     = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (&ImageContext, RelocDir->VirtualAddress, 0);\r
+      RelocBaseEnd  = (EFI_IMAGE_BASE_RELOCATION *) PeCoffLoaderImageAddress (&ImageContext,\r
+                                                                              RelocDir->VirtualAddress + RelocDir->Size - 1,\r
+                                                                              0\r
+                                                                              );\r
+    }\r
+    if (RelocBase == NULL || RelocBaseEnd == NULL || (UINTN) RelocBaseEnd < (UINTN) RelocBase) {\r
+      //\r
+      // relocation block is not valid, just return\r
+      //\r
+      return;\r
+    }\r
   } else {\r
     //\r
     // Cannot find relocations, cannot continue to relocate the image, ASSERT for this invalid image.\r
@@ -1790,96 +1769,109 @@ PeCoffLoaderRelocateImageForRuntime (
   //\r
   ASSERT (RelocBase != NULL && RelocBaseEnd != NULL);\r
 \r
-  //\r
-  // Run the whole relocation block. And re-fixup data that has not been\r
-  // modified. The FixupData is used to see if the image has been modified\r
-  // since it was relocated. This is so data sections that have been updated\r
-  // by code will not be fixed up, since that would set them back to\r
-  // defaults.\r
-  //\r
-  FixupData = RelocationData;\r
-  while (RelocBase < RelocBaseEnd) {\r
+  if (Adjust != 0) {\r
     //\r
-    // Add check for RelocBase->SizeOfBlock field.\r
+    // Run the whole relocation block. And re-fixup data that has not been\r
+    // modified. The FixupData is used to see if the image has been modified\r
+    // since it was relocated. This is so data sections that have been updated\r
+    // by code will not be fixed up, since that would set them back to\r
+    // defaults.\r
     //\r
-    if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir->Size)) {\r
+    FixupData = RelocationData;\r
+    RelocBaseOrig = RelocBase;\r
+    while ((UINTN) RelocBase < (UINTN) RelocBaseEnd) {\r
       //\r
-      // Data invalid, cannot continue to relocate the image, just return.\r
+      // Add check for RelocBase->SizeOfBlock field.\r
       //\r
-      return;\r
-    }\r
-\r
-    Reloc     = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
-    RelocEnd  = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
-    FixupBase = (CHAR8 *) ((UINTN)ImageBase) + RelocBase->VirtualAddress;\r
+      if ((RelocBase->SizeOfBlock == 0) || (RelocBase->SizeOfBlock > RelocDir->Size)) {\r
+        //\r
+        // Data invalid, cannot continue to relocate the image, just return.\r
+        //\r
+        return;\r
+      }\r
 \r
-    //\r
-    // Run this relocation record\r
-    //\r
-    while (Reloc < RelocEnd) {\r
+      Reloc     = (UINT16 *) ((UINT8 *) RelocBase + sizeof (EFI_IMAGE_BASE_RELOCATION));\r
+      RelocEnd  = (UINT16 *) ((UINT8 *) RelocBase + RelocBase->SizeOfBlock);\r
+      if ((UINTN)RelocEnd > (UINTN)RelocBaseOrig + RelocDir->Size) {\r
+        return;\r
+      }\r
 \r
-      Fixup = FixupBase + (*Reloc & 0xFFF);\r
-      switch ((*Reloc) >> 12) {\r
+      FixupBase = PeCoffLoaderImageAddress (&ImageContext, RelocBase->VirtualAddress, 0);\r
+      if (FixupBase == NULL) {\r
+        return;\r
+      }\r
 \r
-      case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
-        break;\r
+      //\r
+      // Run this relocation record\r
+      //\r
+      while ((UINTN) Reloc < (UINTN) RelocEnd) {\r
 \r
-      case EFI_IMAGE_REL_BASED_HIGH:\r
-        Fixup16 = (UINT16 *) Fixup;\r
-        if (*(UINT16 *) FixupData == *Fixup16) {\r
-          *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));\r
+        Fixup = PeCoffLoaderImageAddress (&ImageContext, RelocBase->VirtualAddress + (*Reloc & 0xFFF), 0);\r
+        if (Fixup == NULL) {\r
+          return;\r
         }\r
+        switch ((*Reloc) >> 12) {\r
 \r
-        FixupData = FixupData + sizeof (UINT16);\r
-        break;\r
+        case EFI_IMAGE_REL_BASED_ABSOLUTE:\r
+          break;\r
 \r
-      case EFI_IMAGE_REL_BASED_LOW:\r
-        Fixup16 = (UINT16 *) Fixup;\r
-        if (*(UINT16 *) FixupData == *Fixup16) {\r
-          *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));\r
-        }\r
+        case EFI_IMAGE_REL_BASED_HIGH:\r
+          Fixup16 = (UINT16 *) Fixup;\r
+          if (*(UINT16 *) FixupData == *Fixup16) {\r
+            *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) ((UINT32) Adjust >> 16)));\r
+          }\r
 \r
-        FixupData = FixupData + sizeof (UINT16);\r
-        break;\r
+          FixupData = FixupData + sizeof (UINT16);\r
+          break;\r
 \r
-      case EFI_IMAGE_REL_BASED_HIGHLOW:\r
-        Fixup32       = (UINT32 *) Fixup;\r
-        FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
-        if (*(UINT32 *) FixupData == *Fixup32) {\r
-          *Fixup32 = *Fixup32 + (UINT32) Adjust;\r
-        }\r
+        case EFI_IMAGE_REL_BASED_LOW:\r
+          Fixup16 = (UINT16 *) Fixup;\r
+          if (*(UINT16 *) FixupData == *Fixup16) {\r
+            *Fixup16 = (UINT16) (*Fixup16 + ((UINT16) Adjust & 0xffff));\r
+          }\r
 \r
-        FixupData = FixupData + sizeof (UINT32);\r
-        break;\r
+          FixupData = FixupData + sizeof (UINT16);\r
+          break;\r
 \r
-      case EFI_IMAGE_REL_BASED_DIR64:\r
-        Fixup64       = (UINT64 *)Fixup;\r
-        FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));\r
-        if (*(UINT64 *) FixupData == *Fixup64) {\r
-          *Fixup64 = *Fixup64 + (UINT64)Adjust;\r
-        }\r
+        case EFI_IMAGE_REL_BASED_HIGHLOW:\r
+          Fixup32       = (UINT32 *) Fixup;\r
+          FixupData = ALIGN_POINTER (FixupData, sizeof (UINT32));\r
+          if (*(UINT32 *) FixupData == *Fixup32) {\r
+            *Fixup32 = *Fixup32 + (UINT32) Adjust;\r
+          }\r
 \r
-        FixupData = FixupData + sizeof (UINT64);\r
-        break;\r
+          FixupData = FixupData + sizeof (UINT32);\r
+          break;\r
 \r
-      default:\r
+        case EFI_IMAGE_REL_BASED_DIR64:\r
+          Fixup64       = (UINT64 *)Fixup;\r
+          FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));\r
+          if (*(UINT64 *) FixupData == *Fixup64) {\r
+            *Fixup64 = *Fixup64 + (UINT64)Adjust;\r
+          }\r
+\r
+          FixupData = FixupData + sizeof (UINT64);\r
+          break;\r
+\r
+        default:\r
+          //\r
+          // Only Itanium requires ConvertPeImage_Ex\r
+          //\r
+          Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
+          if (RETURN_ERROR (Status)) {\r
+            return ;\r
+          }\r
+        }\r
         //\r
-        // Only Itanium requires ConvertPeImage_Ex\r
+        // Next relocation record\r
         //\r
-        Status = PeHotRelocateImageEx (Reloc, Fixup, &FixupData, Adjust);\r
-        if (RETURN_ERROR (Status)) {\r
-          return ;\r
-        }\r
+        Reloc += 1;\r
       }\r
       //\r
-      // Next relocation record\r
+      // next reloc block\r
       //\r
-      Reloc += 1;\r
+      RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
     }\r
-    //\r
-    // next reloc block\r
-    //\r
-    RelocBase = (EFI_IMAGE_BASE_RELOCATION *) RelocEnd;\r
   }\r
 }\r
 \r