3 Copyright (c) 2006 - 2013, Intel Corporation. All rights reserved.<BR>
4 SPDX-License-Identifier: BSD-2-Clause-Patent
19 #include <IndustryStandard/PeImage.h>
20 #include <WinNtPeim.h>
21 #include <Ppi/NtPeiLoadFile.h>
22 #include <Library/PeCoffGetEntryPointLib.h>
23 #include <Library/PeiServicesLib.h>
24 #include <Library/DebugLib.h>
29 PeCoffLoaderGetEntryPoint (
31 IN OUT VOID
**EntryPoint
37 Loads a PE/COFF image into memory, this is not follow the original purpose of
38 PeCoffGetEntryPoint library class. But it's ok that Unix package not run on a real
39 platform and this is for source level debug.
43 Pe32Data - Pointer to a PE/COFF Image
45 EntryPoint - Pointer to the entry point of the PE/COFF image
49 EFI_SUCCESS if the EntryPoint was returned
50 EFI_INVALID_PARAMETER if the EntryPoint could not be found from Pe32Data
55 EFI_PEI_PPI_DESCRIPTOR
*PpiDescriptor
;
56 NT_PEI_LOAD_FILE_PPI
*PeiNtService
;
57 EFI_PHYSICAL_ADDRESS ImageAddress
;
59 EFI_PHYSICAL_ADDRESS ImageEntryPoint
;
61 ASSERT (Pe32Data
!= NULL
);
62 ASSERT (EntryPoint
!= NULL
);
64 Status
= PeiServicesLocatePpi (
65 &gNtPeiLoadFilePpiGuid
,
70 ASSERT_EFI_ERROR (Status
);
72 Status
= PeiNtService
->PeiLoadFileService (
78 if (EFI_ERROR (Status
)) {
82 *EntryPoint
= (VOID
*)(UINTN
)ImageEntryPoint
;
87 Returns the machine type of PE/COFF image.
88 This is copied from MDE BasePeCoffGetEntryPointLib, the code should be sync with it.
89 The reason is NT32 package needs to load the image to memory to support source
93 @param Pe32Data Pointer to a PE/COFF header
95 @return Machine type or zero if not a valid iamge
100 PeCoffLoaderGetMachineType (
104 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
105 EFI_IMAGE_DOS_HEADER
*DosHdr
;
107 ASSERT (Pe32Data
!= NULL
);
109 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
110 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
112 // DOS image header is present, so read the PE header after the DOS image header.
114 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
117 // DOS image header is not present, so PE header is at the image base.
119 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
122 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
123 return Hdr
.Te
->Machine
;
124 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
125 return Hdr
.Pe32
->FileHeader
.Machine
;
132 Returns a pointer to the PDB file name for a PE/COFF image that has been
133 loaded into system memory with the PE/COFF Loader Library functions.
135 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
136 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
137 returned. If the PE/COFF image specified by Pe32Data does not contain a
138 debug directory entry, then NULL is returned. If the debug directory entry
139 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
140 then NULL is returned.
141 If Pe32Data is NULL, then ASSERT().
143 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
146 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
147 if it cannot be retrieved.
152 PeCoffLoaderGetPdbPointer (
156 EFI_IMAGE_DOS_HEADER
*DosHdr
;
157 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
158 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
159 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
161 VOID
*CodeViewEntryPointer
;
163 UINT32 NumberOfRvaAndSizes
;
166 ASSERT (Pe32Data
!= NULL
);
169 DirectoryEntry
= NULL
;
171 NumberOfRvaAndSizes
= 0;
173 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
174 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
176 // DOS image header is present, so read the PE header after the DOS image header.
178 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
181 // DOS image header is not present, so PE header is at the image base.
183 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
186 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
187 if (Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
188 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
189 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
;
190 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) Hdr
.Te
+
191 Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
+
194 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
196 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
197 // It is due to backward-compatibility, for some system might
198 // generate PE32+ image with PE32 Magic.
200 switch (Hdr
.Pe32
->FileHeader
.Machine
) {
201 case IMAGE_FILE_MACHINE_I386
:
203 // Assume PE32 image with IA32 Machine field.
205 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
207 case IMAGE_FILE_MACHINE_X64
:
208 case IMAGE_FILE_MACHINE_IA64
:
210 // Assume PE32+ image with X64 or IA64 Machine field
212 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
216 // For unknow Machine field, use Magic in optional Header
218 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
221 if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
223 // Use PE32 offset get Debug Directory Entry
225 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
226 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
227 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
228 } else if (Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
230 // Use PE32+ offset get Debug Directory Entry
232 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
233 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
234 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) ((UINTN
) Pe32Data
+ DirectoryEntry
->VirtualAddress
);
237 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
238 DirectoryEntry
= NULL
;
245 if (DebugEntry
== NULL
|| DirectoryEntry
== NULL
) {
249 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
), DebugEntry
++) {
250 if (DebugEntry
->Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
251 if (DebugEntry
->SizeOfData
> 0) {
252 CodeViewEntryPointer
= (VOID
*) ((UINTN
) DebugEntry
->RVA
+ ((UINTN
)Pe32Data
) + (UINTN
)TEImageAdjust
);
253 switch (* (UINT32
*) CodeViewEntryPointer
) {
254 case CODEVIEW_SIGNATURE_NB10
:
255 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
));
256 case CODEVIEW_SIGNATURE_RSDS
:
257 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
));
258 case CODEVIEW_SIGNATURE_MTOC
:
259 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY
));
272 Returns the size of the PE/COFF headers
274 Returns the size of the PE/COFF header specified by Pe32Data.
275 If Pe32Data is NULL, then ASSERT().
277 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
280 @return Size of PE/COFF header in bytes or zero if not a valid image.
285 PeCoffGetSizeOfHeaders (
289 EFI_IMAGE_DOS_HEADER
*DosHdr
;
290 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
293 ASSERT (Pe32Data
!= NULL
);
295 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
296 if (DosHdr
->e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
298 // DOS image header is present, so read the PE header after the DOS image header.
300 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
303 // DOS image header is not present, so PE header is at the image base.
305 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
308 if (Hdr
.Te
->Signature
== EFI_TE_IMAGE_HEADER_SIGNATURE
) {
309 SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
)Hdr
.Te
->BaseOfCode
- (UINTN
)Hdr
.Te
->StrippedSize
;
310 } else if (Hdr
.Pe32
->Signature
== EFI_IMAGE_NT_SIGNATURE
) {
311 SizeOfHeaders
= Hdr
.Pe32
->OptionalHeader
.SizeOfHeaders
;
316 return (UINT32
) SizeOfHeaders
;