3 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
4 Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
10 #include <Library/PeCoffGetEntryPointLib.h>
11 #include <Library/PeiServicesLib.h>
12 #include <IndustryStandard/PeImage.h>
13 #include <Library/DebugLib.h>
15 #include <Ppi/EmuThunk.h>
16 #include <Protocol/EmuThunk.h>
21 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded
22 into system memory with the PE/COFF Loader Library functions.
24 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry
25 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then
26 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.
27 If Pe32Data is NULL, then ASSERT().
28 If EntryPoint is NULL, then ASSERT().
30 @param Pe32Data The pointer to the PE/COFF image that is loaded in system memory.
31 @param EntryPoint The pointer to entry point to the PE/COFF image to return.
33 @retval RETURN_SUCCESS EntryPoint was returned.
34 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.
39 PeCoffLoaderGetEntryPoint (
41 IN OUT VOID
**EntryPoint
44 EMU_THUNK_PPI
*ThunkPpi
;
46 EMU_THUNK_PROTOCOL
*Thunk
;
49 // Locate EmuThunkPpi for retrieving standard output handle
51 Status
= PeiServicesLocatePpi (
57 ASSERT_EFI_ERROR (Status
);
59 Thunk
= (EMU_THUNK_PROTOCOL
*)ThunkPpi
->Thunk ();
61 return Thunk
->PeCoffGetEntryPoint (Pe32Data
, EntryPoint
);
65 Returns the machine type of PE/COFF image.
66 This is copied from MDE BasePeCoffGetEntryPointLib, the code should be sync with it.
67 The reason is Emu package needs to load the image to memory to support source
71 @param Pe32Data Pointer to a PE/COFF header
73 @return Machine type or zero if not a valid iamge
78 PeCoffLoaderGetMachineType (
82 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
83 EFI_IMAGE_DOS_HEADER
*DosHdr
;
85 ASSERT (Pe32Data
!= NULL
);
87 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
88 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
89 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
92 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)(Pe32Data
);
95 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
96 return Hdr
.Te
->Machine
;
97 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
98 return Hdr
.Pe32
->FileHeader
.Machine
;
105 Returns a pointer to the PDB file name for a PE/COFF image that has been
106 loaded into system memory with the PE/COFF Loader Library functions.
108 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
109 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
110 returned. If the PE/COFF image specified by Pe32Data does not contain a
111 debug directory entry, then NULL is returned. If the debug directory entry
112 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
113 then NULL is returned.
114 If Pe32Data is NULL, then ASSERT().
116 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
119 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
120 if it cannot be retrieved.
125 PeCoffLoaderGetPdbPointer (
129 EFI_IMAGE_DOS_HEADER
*DosHdr
;
130 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
131 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
132 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
134 VOID
*CodeViewEntryPointer
;
136 UINT32 NumberOfRvaAndSizes
;
139 ASSERT (Pe32Data
!= NULL
);
142 DirectoryEntry
= NULL
;
144 NumberOfRvaAndSizes
= 0;
146 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
147 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
149 // DOS image header is present, so read the PE header after the DOS image header.
151 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
154 // DOS image header is not present, so PE header is at the image base.
156 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
159 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
160 if (Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
161 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
162 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
;
163 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) Hdr
.Te
+
164 Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
167 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
169 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
170 // It is due to backward-compatibility, for some system might
171 // generate PE32+ image with PE32 Magic.
173 switch (Hdr
.Pe32
->FileHeader
.Machine
) {
174 case EFI_IMAGE_MACHINE_IA32
:
176 // Assume PE32 image with IA32 Machine field.
178 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
180 case EFI_IMAGE_MACHINE_X64
:
181 case EFI_IMAGE_MACHINE_IA64
:
183 // Assume PE32+ image with X64 or IA64 Machine field
185 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
189 // For unknow Machine field, use Magic in optional Header
191 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
194 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
196 // Use PE32 offset get Debug Directory Entry
198 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
199 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
200 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
201 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
203 // Use PE32+ offset get Debug Directory Entry
205 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
206 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
207 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
210 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
211 DirectoryEntry
= NULL
;
218 if (DebugEntry
== NULL
|| DirectoryEntry
== NULL
) {
222 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
), DebugEntry
++) {
223 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
224 if (DebugEntry
->SizeOfData
> 0) {
225 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ ((UINTN
)Pe32Data
) + (UINTN
)TEImageAdjust
);
226 switch (* (UINT32
*) CodeViewEntryPointer
) {
227 case CODEVIEW_SIGNATURE_NB10
:
228 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
));
229 case CODEVIEW_SIGNATURE_RSDS
:
230 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
));
231 case CODEVIEW_SIGNATURE_MTOC
:
232 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
));
245 Returns the size of the PE/COFF headers
247 Returns the size of the PE/COFF header specified by Pe32Data.
248 If Pe32Data is NULL, then ASSERT().
250 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
253 @return Size of PE/COFF header in bytes or zero if not a valid image.
258 PeCoffGetSizeOfHeaders (
262 EFI_IMAGE_DOS_HEADER
*DosHdr
;
263 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
266 ASSERT (Pe32Data
!= NULL
);
268 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
269 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
271 // DOS image header is present, so read the PE header after the DOS image header.
273 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
276 // DOS image header is not present, so PE header is at the image base.
278 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
281 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
282 SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
283 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
284 SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
289 return (UINT32
) SizeOfHeaders
;