Home | History | Annotate | Download | only in BasePeCoffGetEntryPointLib
      1 /*++
      2 
      3 Copyright (c) 2004 - 2006, Intel Corporation. All rights reserved.<BR>
      4 This program and the accompanying materials
      5 are licensed and made available under the terms and conditions of the BSD License
      6 which accompanies this distribution.  The full text of the license may be found at
      7 http://opensource.org/licenses/bsd-license.php
      8 
      9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     11 
     12 
     13 Module Name:
     14 
     15   PeCoffGetEntryPoint.c
     16 
     17 Abstract:
     18 
     19   Pe/Coff loader
     20 
     21 --*/
     22 
     23 #include "EdkIIGlueBase.h"
     24 
     25 /**
     26   Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
     27   into system memory with the PE/COFF Loader Library functions.
     28 
     29   Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
     30   point in EntryPoint.  If the entry point could not be retrieved from the PE/COFF image, then
     31   return RETURN_INVALID_PARAMETER.  Otherwise return RETURN_SUCCESS.
     32   If Pe32Data is NULL, then ASSERT().
     33   If EntryPoint is NULL, then ASSERT().
     34 
     35   @param  Pe32Data                  Pointer to the PE/COFF image that is loaded in system memory.
     36   @param  EntryPoint                Pointer to entry point to the PE/COFF image to return.
     37 
     38   @retval RETURN_SUCCESS            EntryPoint was returned.
     39   @retval RETURN_INVALID_PARAMETER  The entry point could not be found in the PE/COFF image.
     40 
     41 **/
     42 RETURN_STATUS
     43 EFIAPI
     44 PeCoffLoaderGetEntryPoint (
     45   IN  VOID  *Pe32Data,
     46   OUT VOID  **EntryPoint
     47   )
     48 {
     49   EFI_IMAGE_DOS_HEADER                  *DosHeader;
     50   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Header;
     51 
     52   ASSERT (Pe32Data   != NULL);
     53   ASSERT (EntryPoint != NULL);
     54 
     55   DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
     56   if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
     57     //
     58     // DOS image header is present, so read the PE header after the DOS image header.
     59     //
     60     Header.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff));
     61   } else {
     62     //
     63     // DOS image header is not present, so PE header is at the image base.
     64     //
     65     Header.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
     66   }
     67 
     68   //
     69   // Calculate the entry point relative to the start of the image.
     70   // AddressOfEntryPoint is common for PE32 & PE32+
     71   //
     72   *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Header.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
     73   return RETURN_SUCCESS;
     74 }
     75 
     76 
     77 /**
     78   Returns the machine type of a PE/COFF image.
     79 
     80   Returns the machine type from the PE/COFF image specified by Pe32Data.
     81   If Pe32Data is NULL, then ASSERT().
     82 
     83   @param  Pe32Data   Pointer to the PE/COFF image that is loaded in system
     84                      memory.
     85 
     86   @return Machine type or zero if not a valid iamge.
     87 
     88 **/
     89 UINT16
     90 EFIAPI
     91 PeCoffLoaderGetMachineType (
     92   IN VOID  *Pe32Data
     93   )
     94 {
     95   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
     96   EFI_IMAGE_DOS_HEADER                 *DosHdr;
     97 
     98   DosHdr = (EFI_IMAGE_DOS_HEADER  *)Pe32Data;
     99   if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
    100     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + DosHdr->e_lfanew);
    101   } else {
    102     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data);
    103   }
    104 
    105   if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {
    106     return Hdr.Pe32->FileHeader.Machine;
    107   }
    108 
    109   return 0x0000;
    110 }
    111 
    112 /**
    113   Returns a pointer to the PDB file name for a PE/COFF image that has been
    114   loaded into system memory with the PE/COFF Loader Library functions.
    115 
    116   Returns the PDB file name for the PE/COFF image specified by Pe32Data.  If
    117   the PE/COFF image specified by Pe32Data is not a valid, then NULL is
    118   returned.  If the PE/COFF image specified by Pe32Data does not contain a
    119   debug directory entry, then NULL is returned.  If the debug directory entry
    120   in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
    121   then NULL is returned.
    122   If Pe32Data is NULL, then ASSERT().
    123 
    124   @param  Pe32Data   Pointer to the PE/COFF image that is loaded in system
    125                      memory.
    126 
    127   @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
    128           if it cannot be retrieved.
    129 
    130 **/
    131 VOID *
    132 EFIAPI
    133 PeCoffLoaderGetPdbPointer (
    134   IN VOID  *Pe32Data
    135   )
    136 {
    137   EFI_IMAGE_DOS_HEADER                  *DosHeader;
    138   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
    139   EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;
    140   EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;
    141   UINTN                                 DirCount;
    142   VOID                                  *CodeViewEntryPointer;
    143   INTN                                  TEImageAdjust;
    144   UINT32                                NumberOfRvaAndSizes;
    145 
    146   ASSERT (Pe32Data   != NULL);
    147 
    148   TEImageAdjust       = 0;
    149   DirectoryEntry      = NULL;
    150   DebugEntry          = NULL;
    151   NumberOfRvaAndSizes = 0;
    152 
    153   DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
    154   if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
    155     //
    156     // DOS image header is present, so read the PE header after the DOS image header.
    157     //
    158     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff));
    159   } else {
    160     //
    161     // DOS image header is not present, so PE header is at the image base.
    162     //
    163     Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
    164   }
    165 
    166   if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
    167     if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
    168       DirectoryEntry  = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
    169       TEImageAdjust   = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
    170       DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
    171                     Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
    172                     TEImageAdjust);
    173     }
    174   } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
    175     if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
    176       //
    177       // Use PE32 offset get Debug Directory Entry
    178       //
    179       NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
    180       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
    181       DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
    182     } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
    183       //
    184       // Use PE32+ offset get Debug Directory Entry
    185       //
    186       NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
    187       DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
    188       DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
    189     }
    190 
    191     if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
    192       DirectoryEntry = NULL;
    193       DebugEntry = NULL;
    194     }
    195   } else {
    196     return NULL;
    197   }
    198 
    199   if (DebugEntry == NULL || DirectoryEntry == NULL) {
    200     return NULL;
    201   }
    202 
    203   for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) {
    204     if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
    205       if (DebugEntry->SizeOfData > 0) {
    206         CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
    207         switch (* (UINT32 *) CodeViewEntryPointer) {
    208         case CODEVIEW_SIGNATURE_NB10:
    209           return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
    210         case CODEVIEW_SIGNATURE_RSDS:
    211           return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
    212         default:
    213           break;
    214         }
    215       }
    216     }
    217   }
    218 
    219   return NULL;
    220 }
    221 
    222 
    223