4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Provides the services to get the entry point to a PE/COFF image that has either been
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync loaded into memory or is executing at it's linked address.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Portions copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync This program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync are licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync which accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync http://opensource.org/licenses/bsd-license.php.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Base.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/PeCoffGetEntryPointLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <Library/DebugLib.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include <IndustryStandard/PeImage.h>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync into system memory with the PE/COFF Loader Library functions.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Pe32Data is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If EntryPoint is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param EntryPoint The pointer to entry point to the PE/COFF image to return.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_SUCCESS EntryPoint was returned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncRETURN_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderGetEntryPoint (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Pe32Data,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT VOID **EntryPoint
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DOS_HEADER *DosHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Pe32Data != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (EntryPoint != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is present, so read the PE header after the DOS image header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is not present, so PE header is at the image base.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Calculate the entry point relative to the start of the image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // AddressOfEntryPoint is common for PE32 & PE32+
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Te->AddressOfEntryPoint & 0x0ffffffff) + sizeof(EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Hdr.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return RETURN_UNSUPPORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Returns the machine type of a PE/COFF image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Returns the machine type from the PE/COFF image specified by Pe32Data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Pe32Data is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pe32Data The pointer to the PE/COFF image that is loaded in system
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Machine type or zero if not a valid image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT16
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderGetMachineType (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Pe32Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DOS_HEADER *DosHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Pe32Data != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is present, so read the PE header after the DOS image header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is not present, so PE header is at the image base.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Hdr.Te->Machine;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Hdr.Pe32->FileHeader.Machine;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return 0x0000;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Returns a pointer to the PDB file name for a PE/COFF image that has been
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync loaded into system memory with the PE/COFF Loader Library functions.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync the PE/COFF image specified by Pe32Data is not a valid, then NULL is
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync returned. If the PE/COFF image specified by Pe32Data does not contain a
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync debug directory entry, then NULL is returned. If the debug directory entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync then NULL is returned.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Pe32Data is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pe32Data The pointer to the PE/COFF image that is loaded in system
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if it cannot be retrieved.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID *
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffLoaderGetPdbPointer (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Pe32Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DOS_HEADER *DosHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN DirCount;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync VOID *CodeViewEntryPointer;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN TEImageAdjust;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Pe32Data != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TEImageAdjust = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is present, so read the PE header after the DOS image header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is not present, so PE header is at the image base.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync TEImageAdjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It is due to backward-compatibility, for some system might
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // generate PE32+ image with PE32 Magic.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Hdr.Pe32->FileHeader.Machine) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case IMAGE_FILE_MACHINE_I386:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume PE32 image with IA32 Machine field.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case IMAGE_FILE_MACHINE_X64:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case IMAGE_FILE_MACHINE_IA64:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Assume PE32+ image with x64 or IA64 Machine field
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // For unknow Machine field, use Magic in optional Header
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Magic = Hdr.Pe32->OptionalHeader.Magic;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32 offset get Debug Directory Entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Use PE32+ offset get Debug Directory Entry
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DirectoryEntry = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DebugEntry = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry == NULL || DirectoryEntry == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Scan the directory to find the debug entry.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DebugEntry->SizeOfData > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (* (UINT32 *) CodeViewEntryPointer) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case CODEVIEW_SIGNATURE_NB10:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case CODEVIEW_SIGNATURE_RSDS:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case CODEVIEW_SIGNATURE_MTOC:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Returns the size of the PE/COFF headers
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Returns the size of the PE/COFF header specified by Pe32Data.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If Pe32Data is NULL, then ASSERT().
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Pe32Data The pointer to the PE/COFF image that is loaded in system
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync memory.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @return Size of PE/COFF header in bytes or zero if not a valid image.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncUINT32
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncPeCoffGetSizeOfHeaders (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Pe32Data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_DOS_HEADER *DosHdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINTN SizeOfHeaders;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Pe32Data != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is present, so read the PE header after the DOS image header.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // DOS image header is not present, so PE header is at the image base.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync SizeOfHeaders = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return (UINT32) SizeOfHeaders;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync