TianoCore EDK2 master
Loading...
Searching...
No Matches
PeiEmuPeCoffGetEntryPointLib.c
1/*++ @file
2
3Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
4Portions copyright (c) 2008 - 2011, Apple Inc. All rights reserved.<BR>
5SPDX-License-Identifier: BSD-2-Clause-Patent
6
7**/
8
9#include "PiPei.h"
13#include <Library/DebugLib.h>
14
15#include <Ppi/EmuThunk.h>
16#include <Protocol/EmuThunk.h>
17
35RETURN_STATUS
36EFIAPI
37PeCoffLoaderGetEntryPoint (
38 IN VOID *Pe32Data,
39 IN OUT VOID **EntryPoint
40 )
41{
42 EMU_THUNK_PPI *ThunkPpi;
43 EFI_STATUS Status;
44 EMU_THUNK_PROTOCOL *Thunk;
45
46 //
47 // Locate EmuThunkPpi for retrieving standard output handle
48 //
49 Status = PeiServicesLocatePpi (
50 &gEmuThunkPpiGuid,
51 0,
52 NULL,
53 (VOID **)&ThunkPpi
54 );
55 ASSERT_EFI_ERROR (Status);
56
57 Thunk = (EMU_THUNK_PROTOCOL *)ThunkPpi->Thunk ();
58
59 return Thunk->PeCoffGetEntryPoint (Pe32Data, EntryPoint);
60}
61
74UINT16
75EFIAPI
76PeCoffLoaderGetMachineType (
77 IN VOID *Pe32Data
78 )
79{
82
83 ASSERT (Pe32Data != NULL);
84
85 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
86 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
87 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
88 } else {
89 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data);
90 }
91
92 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
93 return Hdr.Te->Machine;
94 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
95 return Hdr.Pe32->FileHeader.Machine;
96 }
97
98 return 0x0000;
99}
100
120VOID *
121EFIAPI
122PeCoffLoaderGetPdbPointer (
123 IN VOID *Pe32Data
124 )
125{
126 EFI_IMAGE_DOS_HEADER *DosHdr;
128 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;
130 UINTN DirCount;
131 VOID *CodeViewEntryPointer;
132 INTN TEImageAdjust;
133 UINT32 NumberOfRvaAndSizes;
134 UINT16 Magic;
135
136 ASSERT (Pe32Data != NULL);
137
138 TEImageAdjust = 0;
139 DirectoryEntry = NULL;
140 DebugEntry = NULL;
141 NumberOfRvaAndSizes = 0;
142
143 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
144 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
145 //
146 // DOS image header is present, so read the PE header after the DOS image header.
147 //
148 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
149 } else {
150 //
151 // DOS image header is not present, so PE header is at the image base.
152 //
153 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
154 }
155
156 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
157 if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
158 DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
159 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
160 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Hdr.Te +
161 Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +
162 TEImageAdjust);
163 }
164 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
165 //
166 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
167 // It is due to backward-compatibility, for some system might
168 // generate PE32+ image with PE32 Magic.
169 //
170 switch (Hdr.Pe32->FileHeader.Machine) {
172 //
173 // Assume PE32 image with IA32 Machine field.
174 //
176 break;
179 //
180 // Assume PE32+ image with X64 or IA64 Machine field
181 //
183 break;
184 default:
185 //
186 // For unknow Machine field, use Magic in optional Header
187 //
188 Magic = Hdr.Pe32->OptionalHeader.Magic;
189 }
190
192 //
193 // Use PE32 offset get Debug Directory Entry
194 //
195 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;
196 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
197 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Pe32Data + DirectoryEntry->VirtualAddress);
198 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {
199 //
200 // Use PE32+ offset get Debug Directory Entry
201 //
202 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;
203 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);
204 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN)Pe32Data + DirectoryEntry->VirtualAddress);
205 }
206
207 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {
208 DirectoryEntry = NULL;
209 DebugEntry = NULL;
210 }
211 } else {
212 return NULL;
213 }
214
215 if ((DebugEntry == NULL) || (DirectoryEntry == NULL)) {
216 return NULL;
217 }
218
219 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
220 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {
221 if (DebugEntry->SizeOfData > 0) {
222 CodeViewEntryPointer = (VOID *)((UINTN)DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);
223 switch (*(UINT32 *)CodeViewEntryPointer) {
225 return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));
227 return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));
229 return (VOID *)((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));
230 default:
231 break;
232 }
233 }
234 }
235 }
236
237 return NULL;
238}
239
252UINT32
253EFIAPI
254PeCoffGetSizeOfHeaders (
255 IN VOID *Pe32Data
256 )
257{
258 EFI_IMAGE_DOS_HEADER *DosHdr;
260 UINTN SizeOfHeaders;
261
262 ASSERT (Pe32Data != NULL);
263
264 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;
265 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {
266 //
267 // DOS image header is present, so read the PE header after the DOS image header.
268 //
269 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + (UINTN)((DosHdr->e_lfanew) & 0x0ffff));
270 } else {
271 //
272 // DOS image header is not present, so PE header is at the image base.
273 //
274 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;
275 }
276
277 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {
278 SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;
279 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {
280 SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;
281 } else {
282 SizeOfHeaders = 0;
283 }
284
285 return (UINT32)SizeOfHeaders;
286}
UINT64 UINTN
INT64 INTN
EFI_STATUS EFIAPI PeiServicesLocatePpi(IN CONST EFI_GUID *Guid, IN UINTN Instance, IN OUT EFI_PEI_PPI_DESCRIPTOR **PpiDescriptor, IN OUT VOID **Ppi)
#define NULL
Definition: Base.h:319
#define IN
Definition: Base.h:279
#define OUT
Definition: Base.h:284
#define ASSERT_EFI_ERROR(StatusParameter)
Definition: DebugLib.h:462
#define CODEVIEW_SIGNATURE_NB10
Definition: PeImage.h:657
#define EFI_IMAGE_DEBUG_TYPE_CODEVIEW
The Visual C++ debug information.
Definition: PeImage.h:651
#define CODEVIEW_SIGNATURE_RSDS
Definition: PeImage.h:671
#define EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
Definition: PeImage.h:143
#define EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
Definition: PeImage.h:194
#define CODEVIEW_SIGNATURE_MTOC
Definition: PeImage.h:687
#define EFI_IMAGE_MACHINE_IA32
Definition: UefiBaseType.h:218
RETURN_STATUS EFI_STATUS
Definition: UefiBaseType.h:29
#define EFI_IMAGE_MACHINE_IA64
Definition: UefiBaseType.h:223
#define EFI_IMAGE_MACHINE_X64
Definition: UefiBaseType.h:233
EMU_PE_COFF_GET_ENTRY_POINT PeCoffGetEntryPoint
Definition: EmuThunk.h:220
UINT32 RVA
The address of the debug data when loaded, relative to the image base.
Definition: PeImage.h:647
UINT32 e_lfanew
File address of new exe header.
Definition: PeImage.h:76
UINT16 e_magic
Magic number.
Definition: PeImage.h:58
UINT16 Signature
The signature for TE format = "VZ".
Definition: PeImage.h:781
UINT32 BaseOfCode
From original image – required for ITP debug.
Definition: PeImage.h:787
EFI_IMAGE_DATA_DIRECTORY DataDirectory[2]
Only base relocation and debug directory.
Definition: PeImage.h:789
UINT16 StrippedSize
Number of bytes we removed from the header.
Definition: PeImage.h:785
UINT16 Machine
From the original file header.
Definition: PeImage.h:782