]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c
MdePkg: Apply uncrustify changes
[mirror_edk2.git] / MdePkg / Library / BasePeCoffGetEntryPointLib / PeCoffGetEntryPoint.c
index 7ed8f078fc8ac5adc92385093074c7e58bb002d3..00b645a1011ad0a309d9db5e08e1c349c86dd48b 100644 (file)
@@ -1,26 +1,22 @@
 /** @file\r
-  Tiano PE/COFF loader.\r
+  Provides the services to get the entry point to a PE/COFF image that has either been\r
+  loaded into memory or is executing at it's linked address.\r
 \r
-  Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
-  All rights reserved. This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+  Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
-\r
 #include <Base.h>\r
 \r
-\r
 #include <Library/PeCoffGetEntryPointLib.h>\r
 #include <Library/DebugLib.h>\r
 \r
 #include <IndustryStandard/PeImage.h>\r
 \r
+#define PE_COFF_IMAGE_ALIGN_SIZE  4\r
+\r
 /**\r
   Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
   into system memory with the PE/COFF Loader Library functions.\r
@@ -31,8 +27,8 @@
   If Pe32Data is NULL, then ASSERT().\r
   If EntryPoint is NULL, then ASSERT().\r
 \r
-  @param  Pe32Data                  Pointer to the PE/COFF image that is loaded in system memory.\r
-  @param  EntryPoint                Pointer to entry point to the PE/COFF image to return.\r
+  @param  Pe32Data                  The pointer to the PE/COFF image that is loaded in system memory.\r
+  @param  EntryPoint                The pointer to entry point to the PE/COFF image to return.\r
 \r
   @retval RETURN_SUCCESS            EntryPoint was returned.\r
   @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.\r
@@ -45,8 +41,8 @@ PeCoffLoaderGetEntryPoint (
   OUT VOID  **EntryPoint\r
   )\r
 {\r
-  EFI_IMAGE_DOS_HEADER                  *DosHdr;\r
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
 \r
   ASSERT (Pe32Data   != NULL);\r
   ASSERT (EntryPoint != NULL);\r
@@ -56,7 +52,7 @@ PeCoffLoaderGetEntryPoint (
     //\r
     // DOS image header is present, so read the PE header after the DOS image header.\r
     //\r
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));\r
   } else {\r
     //\r
     // DOS image header is not present, so PE header is at the image base.\r
@@ -69,7 +65,7 @@ PeCoffLoaderGetEntryPoint (
   // AddressOfEntryPoint is common for PE32 & PE32+\r
   //\r
   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
-    *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);\r
+    *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);\r
     return RETURN_SUCCESS;\r
   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
     *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));\r
@@ -79,17 +75,16 @@ PeCoffLoaderGetEntryPoint (
   return RETURN_UNSUPPORTED;\r
 }\r
 \r
-\r
 /**\r
   Returns the machine type of a PE/COFF image.\r
 \r
   Returns the machine type from the PE/COFF image specified by Pe32Data.\r
   If Pe32Data is NULL, then ASSERT().\r
 \r
-  @param  Pe32Data   Pointer to the PE/COFF image that is loaded in system\r
+  @param  Pe32Data   The pointer to the PE/COFF image that is loaded in system\r
                      memory.\r
 \r
-  @return Machine type or zero if not a valid iamge.\r
+  @return Machine type or zero if not a valid image.\r
 \r
 **/\r
 UINT16\r
@@ -108,7 +103,7 @@ PeCoffLoaderGetMachineType (
     //\r
     // DOS image header is present, so read the PE header after the DOS image header.\r
     //\r
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));\r
   } else {\r
     //\r
     // DOS image header is not present, so PE header is at the image base.\r
@@ -118,7 +113,7 @@ PeCoffLoaderGetMachineType (
 \r
   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
     return Hdr.Te->Machine;\r
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
     return Hdr.Pe32->FileHeader.Machine;\r
   }\r
 \r
@@ -137,7 +132,7 @@ PeCoffLoaderGetMachineType (
   then NULL is returned.\r
   If Pe32Data is NULL, then ASSERT().\r
 \r
-  @param  Pe32Data   Pointer to the PE/COFF image that is loaded in system\r
+  @param  Pe32Data   The pointer to the PE/COFF image that is loaded in system\r
                      memory.\r
 \r
   @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL\r
@@ -150,15 +145,15 @@ PeCoffLoaderGetPdbPointer (
   IN VOID  *Pe32Data\r
   )\r
 {\r
-  EFI_IMAGE_DOS_HEADER                  *DosHdr;\r
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
-  EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;\r
-  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;\r
-  UINTN                                 DirCount;\r
-  VOID                                  *CodeViewEntryPointer;\r
-  INTN                                  TEImageAdjust;\r
-  UINT32                                NumberOfRvaAndSizes;\r
-  UINT16                                Magic;\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  EFI_IMAGE_DATA_DIRECTORY             *DirectoryEntry;\r
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY      *DebugEntry;\r
+  UINTN                                DirCount;\r
+  VOID                                 *CodeViewEntryPointer;\r
+  INTN                                 TEImageAdjust;\r
+  UINT32                               NumberOfRvaAndSizes;\r
+  UINT16                               Magic;\r
 \r
   ASSERT (Pe32Data   != NULL);\r
 \r
@@ -172,7 +167,7 @@ PeCoffLoaderGetPdbPointer (
     //\r
     // DOS image header is present, so read the PE header after the DOS image header.\r
     //\r
-    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));\r
   } else {\r
     //\r
     // DOS image header is not present, so PE header is at the image base.\r
@@ -182,11 +177,11 @@ PeCoffLoaderGetPdbPointer (
 \r
   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
     if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
-      DirectoryEntry  = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
-      TEImageAdjust   = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
-      DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +\r
-                    Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
-                    TEImageAdjust);\r
+      DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
+      TEImageAdjust  = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
+      DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Hdr.Te +\r
+                                                           Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
+                                                           TEImageAdjust);\r
     }\r
   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
     //\r
@@ -195,24 +190,24 @@ PeCoffLoaderGetPdbPointer (
     //       generate PE32+ image with PE32 Magic.\r
     //\r
     switch (Hdr.Pe32->FileHeader.Machine) {\r
-    case EFI_IMAGE_MACHINE_IA32:\r
-      //\r
-      // Assume PE32 image with IA32 Machine field.\r
-      //\r
-      Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
-      break;\r
-    case EFI_IMAGE_MACHINE_X64:\r
-    case EFI_IMAGE_MACHINE_IPF:\r
-      //\r
-      // Assume PE32+ image with X64 or IPF Machine field\r
-      //\r
-      Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
-      break;\r
-    default:\r
-      //\r
-      // For unknow Machine field, use Magic in optional Header\r
-      //\r
-      Magic = Hdr.Pe32->OptionalHeader.Magic;\r
+      case IMAGE_FILE_MACHINE_I386:\r
+        //\r
+        // Assume PE32 image with IA32 Machine field.\r
+        //\r
+        Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
+        break;\r
+      case IMAGE_FILE_MACHINE_X64:\r
+      case IMAGE_FILE_MACHINE_IA64:\r
+        //\r
+        // Assume PE32+ image with x64 or IA64 Machine field\r
+        //\r
+        Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
+        break;\r
+      default:\r
+        //\r
+        // For unknow Machine field, use Magic in optional Header\r
+        //\r
+        Magic = Hdr.Pe32->OptionalHeader.Magic;\r
     }\r
 \r
     if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
@@ -220,40 +215,45 @@ PeCoffLoaderGetPdbPointer (
       // Use PE32 offset get Debug Directory Entry\r
       //\r
       NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
-      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
-      DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
+      DirectoryEntry      = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+      DebugEntry          = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Pe32Data + DirectoryEntry->VirtualAddress);\r
     } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
       //\r
       // Use PE32+ offset get Debug Directory Entry\r
       //\r
       NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
-      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
-      DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
+      DirectoryEntry      = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
+      DebugEntry          = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Pe32Data + DirectoryEntry->VirtualAddress);\r
     }\r
 \r
     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
       DirectoryEntry = NULL;\r
-      DebugEntry = NULL;\r
+      DebugEntry     = NULL;\r
     }\r
   } else {\r
     return NULL;\r
   }\r
 \r
-  if (DebugEntry == NULL || DirectoryEntry == NULL) {\r
+  if ((DebugEntry == NULL) || (DirectoryEntry == NULL)) {\r
     return NULL;\r
   }\r
 \r
+  //\r
+  // Scan the directory to find the debug entry.\r
+  //\r
   for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
     if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
       if (DebugEntry->SizeOfData > 0) {\r
-        CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);\r
-        switch (* (UINT32 *) CodeViewEntryPointer) {\r
-        case CODEVIEW_SIGNATURE_NB10:\r
-          return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));\r
-        case CODEVIEW_SIGNATURE_RSDS:\r
-          return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));\r
-        default:\r
-          break;\r
+        CodeViewEntryPointer = (VOID *)((UINTN)DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);\r
+        switch (*(UINT32 *)CodeViewEntryPointer) {\r
+          case CODEVIEW_SIGNATURE_NB10:\r
+            return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));\r
+          case CODEVIEW_SIGNATURE_RSDS:\r
+            return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));\r
+          case CODEVIEW_SIGNATURE_MTOC:\r
+            return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));\r
+          default:\r
+            break;\r
         }\r
       }\r
     }\r
@@ -262,4 +262,121 @@ PeCoffLoaderGetPdbPointer (
   return NULL;\r
 }\r
 \r
+/**\r
+  Returns the size of the PE/COFF headers\r
+\r
+  Returns the size of the PE/COFF header specified by Pe32Data.\r
+  If Pe32Data is NULL, then ASSERT().\r
+\r
+  @param  Pe32Data   The pointer to the PE/COFF image that is loaded in system\r
+                     memory.\r
+\r
+  @return Size of PE/COFF header in bytes or zero if not a valid image.\r
+\r
+**/\r
+UINT32\r
+EFIAPI\r
+PeCoffGetSizeOfHeaders (\r
+  IN VOID  *Pe32Data\r
+  )\r
+{\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+  UINTN                                SizeOfHeaders;\r
+\r
+  ASSERT (Pe32Data   != NULL);\r
+\r
+  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+    //\r
+    // DOS image header is present, so read the PE header after the DOS image header.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));\r
+  } else {\r
+    //\r
+    // DOS image header is not present, so PE header is at the image base.\r
+    //\r
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+  }\r
+\r
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
+    SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;\r
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+    SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
+  } else {\r
+    SizeOfHeaders = 0;\r
+  }\r
+\r
+  return (UINT32)SizeOfHeaders;\r
+}\r
+\r
+/**\r
+  Returns PE/COFF image base is loaded in system memory where the input address is in.\r
+\r
+  On DEBUG build, searches the PE/COFF image base forward the input address and\r
+  returns it.\r
+\r
+  @param  Address    Address located in one PE/COFF image.\r
+\r
+  @retval 0          RELEASE build or cannot find the PE/COFF image base.\r
+  @retval others     PE/COFF image base found.\r
+\r
+**/\r
+UINTN\r
+EFIAPI\r
+PeCoffSearchImageBase (\r
+  IN UINTN  Address\r
+  )\r
+{\r
+  UINTN  Pe32Data;\r
+\r
+  Pe32Data = 0;\r
+\r
+  DEBUG_CODE_BEGIN ();\r
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;\r
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
+\r
+  //\r
+  // Find Image Base\r
+  //\r
+  Pe32Data = Address & ~(PE_COFF_IMAGE_ALIGN_SIZE - 1);\r
+  while (Pe32Data != 0) {\r
+    DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
+    if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
+      //\r
+      // DOS image header is present, so read the PE header after the DOS image header.\r
+      //\r
+      Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));\r
+      //\r
+      // Make sure PE header address does not overflow and is less than the initial address.\r
+      //\r
+      if (((UINTN)Hdr.Pe32 > Pe32Data) && ((UINTN)Hdr.Pe32 < Address)) {\r
+        if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
+          break;\r
+        }\r
+      }\r
+    } else {\r
+      //\r
+      // DOS image header is not present, TE header is at the image base.\r
+      //\r
+      Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
+      if ((Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) &&\r
+          ((Hdr.Te->Machine == IMAGE_FILE_MACHINE_I386)  || (Hdr.Te->Machine == IMAGE_FILE_MACHINE_IA64) ||\r
+           (Hdr.Te->Machine == IMAGE_FILE_MACHINE_EBC)   || (Hdr.Te->Machine == IMAGE_FILE_MACHINE_X64)  ||\r
+           (Hdr.Te->Machine == IMAGE_FILE_MACHINE_ARM64) || (Hdr.Te->Machine == IMAGE_FILE_MACHINE_ARMTHUMB_MIXED))\r
+          )\r
+      {\r
+        break;\r
+      }\r
+    }\r
 \r
+    //\r
+    // Not found the image base, check the previous aligned address\r
+    //\r
+    Pe32Data -= PE_COFF_IMAGE_ALIGN_SIZE;\r
+  }\r
+\r
+  DEBUG_CODE_END ();\r
+\r
+  return Pe32Data;\r
+}\r