]> git.proxmox.com Git - mirror_edk2.git/commitdiff
Integrate the patch contributed by Andrew Fish to add ARM support.
authorqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 24 Aug 2009 15:33:43 +0000 (15:33 +0000)
committerqhuang8 <qhuang8@6f19259b-4bc3-4df7-8a09-765794883524>
Mon, 24 Aug 2009 15:33:43 +0000 (15:33 +0000)
git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@9182 6f19259b-4bc3-4df7-8a09-765794883524

Nt32Pkg/Library/Nt32PeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c

index a97ed6fe125027769b04008eab7658071292842d..5f89570e392f53648c84f2b0af14e663b6a10923 100644 (file)
-/**@file\r
-\r
-Copyright (c) 2006 - 2007, Intel Corporation\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
-\r
-Module Name:\r
-\r
-  PeCoffGetEntryPoint.c\r
-\r
-Abstract:\r
-\r
-  Tiano PE/COFF loader\r
-\r
-Revision History\r
-\r
-**/\r
-\r
-#include <PiPei.h>\r
-#include <IndustryStandard/PeImage.h>\r
-#include <WinNtPeim.h>\r
-#include <Ppi/NtPeiLoadFile.h>\r
-#include <Library/PeCoffGetEntryPointLib.h>\r
-#include <Library/PeiServicesLib.h>\r
-#include <Library/DebugLib.h>\r
-\r
-\r
-RETURN_STATUS\r
-EFIAPI\r
-PeCoffLoaderGetEntryPoint (\r
-  IN     VOID  *Pe32Data,\r
-  IN OUT VOID  **EntryPoint\r
-  )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Loads a PE/COFF image into memory, this is not follow the original purpose of \r
-  PeCoffGetEntryPoint library class.  But it's ok that Unix package not run on a real \r
-  platform and this is for source level debug.\r
-\r
-Arguments:\r
-\r
-  Pe32Data   - Pointer to a PE/COFF Image\r
-\r
-  EntryPoint - Pointer to the entry point of the PE/COFF image\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS            if the EntryPoint was returned\r
-  EFI_INVALID_PARAMETER  if the EntryPoint could not be found from Pe32Data\r
-\r
---*/\r
-{\r
-  EFI_STATUS              Status;\r
-  EFI_PEI_PPI_DESCRIPTOR  *PpiDescriptor;\r
-  NT_PEI_LOAD_FILE_PPI    *PeiNtService;\r
-  EFI_PHYSICAL_ADDRESS    ImageAddress;\r
-  UINT64                  ImageSize;\r
-  EFI_PHYSICAL_ADDRESS    ImageEntryPoint;\r
-\r
-  ASSERT (Pe32Data   != NULL);\r
-  ASSERT (EntryPoint != NULL);\r
-\r
-  Status = PeiServicesLocatePpi (\r
-             &gNtPeiLoadFilePpiGuid,\r
-             0,\r
-             &PpiDescriptor,\r
-             (VOID**)&PeiNtService\r
-             );\r
-  ASSERT_EFI_ERROR (Status);\r
-\r
-  Status = PeiNtService->PeiLoadFileService (\r
-                           Pe32Data,\r
-                           &ImageAddress,\r
-                           &ImageSize,\r
-                           &ImageEntryPoint\r
-                           );\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  *EntryPoint = (VOID*)(UINTN)ImageEntryPoint;\r
-  return Status;\r
-}\r
-\r
-/**\r
-  Returns the machine type of PE/COFF image. \r
-  This is copied from MDE BasePeCoffGetEntryPointLib, the code should be sync with it.\r
-  The reason is NT32 package needs to load the image to memory to support source\r
-  level debug.\r
-   \r
-\r
-  @param  Pe32Data   Pointer to a PE/COFF header\r
-\r
-  @return            Machine type or zero if not a valid iamge\r
-\r
-**/\r
-UINT16\r
-EFIAPI\r
-PeCoffLoaderGetMachineType (\r
-  IN  VOID  *Pe32Data\r
-  )\r
-{  \r
-  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;\r
-  EFI_IMAGE_DOS_HEADER                 *DosHdr;\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
-    return Hdr.Te->Machine;\r
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {\r
-    return Hdr.Pe32->FileHeader.Machine;\r
-  }\r
-\r
-  return 0x0000;\r
-}\r
-\r
-/**\r
-  Returns a pointer to the PDB file name for a PE/COFF image that has been\r
-  loaded into system memory with the PE/COFF Loader Library functions.\r
-\r
-  Returns the PDB file name for the PE/COFF image specified by Pe32Data.  If\r
-  the PE/COFF image specified by Pe32Data is not a valid, then NULL is\r
-  returned.  If the PE/COFF image specified by Pe32Data does not contain a\r
-  debug directory entry, then NULL is returned.  If the debug directory entry\r
-  in the PE/COFF image specified by Pe32Data does not contain a PDB file name,\r
-  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
-                     memory.\r
-\r
-  @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL\r
-          if it cannot be retrieved.\r
-\r
-**/\r
-VOID *\r
-EFIAPI\r
-PeCoffLoaderGetPdbPointer (\r
-  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
-\r
-  ASSERT (Pe32Data   != NULL);\r
-\r
-  TEImageAdjust       = 0;\r
-  DirectoryEntry      = NULL;\r
-  DebugEntry          = NULL;\r
-  NumberOfRvaAndSizes = 0;\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
-    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
-    }\r
-  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
-    //\r
-    // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.\r
-    //       It is due to backward-compatibility, for some system might\r
-    //       generate PE32+ image with PE32 Magic.\r
-    //\r
-    switch (Hdr.Pe32->FileHeader.Machine) {\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
-      //\r
-      // 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
-    } else if (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
-    }\r
-\r
-    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
-      DirectoryEntry = NULL;\r
-      DebugEntry = NULL;\r
-    }\r
-  } else {\r
-    return NULL;\r
-  }\r
-\r
-  if (DebugEntry == NULL || DirectoryEntry == NULL) {\r
-    return NULL;\r
-  }\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
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-  return NULL;\r
-}\r
+/**@file
+
+Copyright (c) 2006 - 2007, Intel Corporation
+All rights reserved. This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution.  The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+Module Name:
+
+  PeCoffGetEntryPoint.c
+
+Abstract:
+
+  Tiano PE/COFF loader
+
+Revision History
+
+**/
+
+#include <PiPei.h>
+#include <IndustryStandard/PeImage.h>
+#include <WinNtPeim.h>
+#include <Ppi/NtPeiLoadFile.h>
+#include <Library/PeCoffGetEntryPointLib.h>
+#include <Library/PeiServicesLib.h>
+#include <Library/DebugLib.h>
+
+
+RETURN_STATUS
+EFIAPI
+PeCoffLoaderGetEntryPoint (
+  IN     VOID  *Pe32Data,
+  IN OUT VOID  **EntryPoint
+  )
+/*++
+
+Routine Description:
+
+  Loads a PE/COFF image into memory, this is not follow the original purpose of 
+  PeCoffGetEntryPoint library class.  But it's ok that Unix package not run on a real 
+  platform and this is for source level debug.
+
+Arguments:
+
+  Pe32Data   - Pointer to a PE/COFF Image
+
+  EntryPoint - Pointer to the entry point of the PE/COFF image
+
+Returns:
+
+  EFI_SUCCESS            if the EntryPoint was returned
+  EFI_INVALID_PARAMETER  if the EntryPoint could not be found from Pe32Data
+
+--*/
+{
+  EFI_STATUS              Status;
+  EFI_PEI_PPI_DESCRIPTOR  *PpiDescriptor;
+  NT_PEI_LOAD_FILE_PPI    *PeiNtService;
+  EFI_PHYSICAL_ADDRESS    ImageAddress;
+  UINT64                  ImageSize;
+  EFI_PHYSICAL_ADDRESS    ImageEntryPoint;
+
+  ASSERT (Pe32Data   != NULL);
+  ASSERT (EntryPoint != NULL);
+
+  Status = PeiServicesLocatePpi (
+             &gNtPeiLoadFilePpiGuid,
+             0,
+             &PpiDescriptor,
+             (VOID**)&PeiNtService
+             );
+  ASSERT_EFI_ERROR (Status);
+
+  Status = PeiNtService->PeiLoadFileService (
+                           Pe32Data,
+                           &ImageAddress,
+                           &ImageSize,
+                           &ImageEntryPoint
+                           );
+  if (EFI_ERROR (Status)) {
+    return Status;
+  }
+
+  *EntryPoint = (VOID*)(UINTN)ImageEntryPoint;
+  return Status;
+}
+
+/**
+  Returns the machine type of PE/COFF image. 
+  This is copied from MDE BasePeCoffGetEntryPointLib, the code should be sync with it.
+  The reason is NT32 package needs to load the image to memory to support source
+  level debug.
+   
+
+  @param  Pe32Data   Pointer to a PE/COFF header
+
+  @return            Machine type or zero if not a valid iamge
+
+**/
+UINT16
+EFIAPI
+PeCoffLoaderGetMachineType (
+  IN  VOID  *Pe32Data
+  )
+{  
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION  Hdr;
+  EFI_IMAGE_DOS_HEADER                 *DosHdr;
+
+  ASSERT (Pe32Data   != NULL);
+
+  DosHdr = (EFI_IMAGE_DOS_HEADER  *)Pe32Data;
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+    //
+    // DOS image header is present, so read the PE header after the DOS image header.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
+  } else {
+    //
+    // DOS image header is not present, so PE header is at the image base.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
+  }
+
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+    return Hdr.Te->Machine;
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE)  {
+    return Hdr.Pe32->FileHeader.Machine;
+  }
+
+  return 0x0000;
+}
+
+/**
+  Returns a pointer to the PDB file name for a PE/COFF image that has been
+  loaded into system memory with the PE/COFF Loader Library functions.
+
+  Returns the PDB file name for the PE/COFF image specified by Pe32Data.  If
+  the PE/COFF image specified by Pe32Data is not a valid, then NULL is
+  returned.  If the PE/COFF image specified by Pe32Data does not contain a
+  debug directory entry, then NULL is returned.  If the debug directory entry
+  in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
+  then NULL is returned.
+  If Pe32Data is NULL, then ASSERT().
+
+  @param  Pe32Data   Pointer to the PE/COFF image that is loaded in system
+                     memory.
+
+  @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
+          if it cannot be retrieved.
+
+**/
+VOID *
+EFIAPI
+PeCoffLoaderGetPdbPointer (
+  IN VOID  *Pe32Data
+  )
+{
+  EFI_IMAGE_DOS_HEADER                  *DosHdr;
+  EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;
+  EFI_IMAGE_DATA_DIRECTORY              *DirectoryEntry;
+  EFI_IMAGE_DEBUG_DIRECTORY_ENTRY       *DebugEntry;
+  UINTN                                 DirCount;
+  VOID                                  *CodeViewEntryPointer;
+  INTN                                  TEImageAdjust;
+  UINT32                                NumberOfRvaAndSizes;
+  UINT16                                Magic;
+
+  ASSERT (Pe32Data   != NULL);
+
+  TEImageAdjust       = 0;
+  DirectoryEntry      = NULL;
+  DebugEntry          = NULL;
+  NumberOfRvaAndSizes = 0;
+
+  DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
+  if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
+    //
+    // DOS image header is present, so read the PE header after the DOS image header.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));
+  } else {
+    //
+    // DOS image header is not present, so PE header is at the image base.
+    //
+    Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
+  }
+
+  if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
+    if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
+      DirectoryEntry  = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
+      TEImageAdjust   = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
+      DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
+                    Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
+                    TEImageAdjust);
+    }
+  } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
+    //
+    // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
+    //       It is due to backward-compatibility, for some system might
+    //       generate PE32+ image with PE32 Magic.
+    //
+    switch (Hdr.Pe32->FileHeader.Machine) {
+    case IMAGE_FILE_MACHINE_I386:
+      //
+      // Assume PE32 image with IA32 Machine field.
+      //
+      Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;
+      break;
+    case IMAGE_FILE_MACHINE_X64:
+    case IMAGE_FILE_MACHINE_IA64:
+      //
+      // Assume PE32+ image with X64 or IA64 Machine field
+      //
+      Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;
+      break;
+    default:
+      //
+      // For unknow Machine field, use Magic in optional Header
+      //
+      Magic = Hdr.Pe32->OptionalHeader.Magic;
+    }
+
+    if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
+      //
+      // Use PE32 offset get Debug Directory Entry
+      //
+      NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+      DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
+    } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
+      //
+      // Use PE32+ offset get Debug Directory Entry
+      //
+      NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
+      DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
+      DebugEntry     = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);
+    }
+
+    if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
+      DirectoryEntry = NULL;
+      DebugEntry = NULL;
+    }
+  } else {
+    return NULL;
+  }
+
+  if (DebugEntry == NULL || DirectoryEntry == NULL) {
+    return NULL;
+  }
+
+  for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
+    if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
+      if (DebugEntry->SizeOfData > 0) {
+        CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
+        switch (* (UINT32 *) CodeViewEntryPointer) {
+        case CODEVIEW_SIGNATURE_NB10:
+          return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
+        case CODEVIEW_SIGNATURE_RSDS:
+          return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
+        case CODEVIEW_SIGNATURE_MTOC:              
+          return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
+          break;
+        default:
+          break;
+        }
+      }
+    }
+  }
+
+  return NULL;
+}