]> git.proxmox.com Git - mirror_edk2.git/blame - UnixPkg/Library/EdkUnixPeiPeCoffGetEntryPointLib/PeCoffGetEntryPoint.c
Fix the build warning of potential uninitialized variable of "SizeOfHeaders".
[mirror_edk2.git] / UnixPkg / Library / EdkUnixPeiPeCoffGetEntryPointLib / PeCoffGetEntryPoint.c
CommitLineData
804405e7 1/*++\r
2\r
7e35214b 3Copyright (c) 2006 - 2010, Intel Corporation\r
ccd55824 4Portions copyright (c) 2008-2009 Apple Inc. All rights reserved.\r
804405e7 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
13Module Name:\r
14\r
15 PeCoffGetEntryPoint.c\r
16\r
17Abstract:\r
18\r
19 Tiano PE/COFF loader\r
20\r
21Revision History\r
22\r
23--*/\r
24#include "PiPei.h"\r
25#include <Library/PeCoffGetEntryPointLib.h>\r
26#include <Library/PeiServicesLib.h>\r
27#include <Ppi/UnixPeiLoadFile.h>\r
28#include <IndustryStandard/PeImage.h>\r
29#include <Library/DebugLib.h>\r
30\r
31RETURN_STATUS\r
32EFIAPI\r
33PeCoffLoaderGetEntryPoint (\r
34 IN VOID *Pe32Data,\r
35 IN OUT VOID **EntryPoint\r
36 )\r
37/*++\r
38\r
39Routine Description:\r
40\r
41 Loads a PE/COFF image into memory, this is not follow the original purpose of \r
42 PeCoffGetEntryPoint library class. But it's ok that Unix package not run on a real \r
43 platform and this is for source level debug.\r
44\r
45Arguments:\r
46\r
47 Pe32Data - Pointer to a PE/COFF Image\r
48\r
49 EntryPoint - Pointer to the entry point of the PE/COFF image\r
50\r
51Returns:\r
52\r
53 EFI_SUCCESS if the EntryPoint was returned\r
54 EFI_INVALID_PARAMETER if the EntryPoint could not be found from Pe32Data\r
55\r
56--*/\r
57{\r
ccd55824 58 PEI_UNIX_THUNK_PPI *UnixThunkPpi;\r
804405e7 59 EFI_STATUS Status;\r
ccd55824 60 EFI_UNIX_THUNK_PROTOCOL *Unix;\r
804405e7 61\r
ccd55824 62 //\r
63 // Locate Unix ThunkPpi for retrieving standard output handle\r
64 //\r
804405e7 65 Status = PeiServicesLocatePpi (\r
ccd55824 66 &gPeiUnixThunkPpiGuid,\r
804405e7 67 0,\r
ccd55824 68 NULL,\r
69 (VOID **) &UnixThunkPpi\r
804405e7 70 );\r
804405e7 71 ASSERT_EFI_ERROR (Status);\r
72\r
ccd55824 73 Unix = (EFI_UNIX_THUNK_PROTOCOL *)UnixThunkPpi->UnixThunk ();\r
804405e7 74\r
ccd55824 75 return Unix->PeCoffGetEntryPoint (Pe32Data, EntryPoint);\r
804405e7 76}\r
77\r
78/**\r
79 Returns the machine type of PE/COFF image. \r
80 This is copied from MDE BasePeCoffGetEntryPointLib, the code should be sync with it.\r
81 The reason is Unix package needs to load the image to memory to support source\r
82 level debug.\r
83 \r
84\r
85 @param Pe32Data Pointer to a PE/COFF header\r
86\r
87 @return Machine type or zero if not a valid iamge\r
88\r
89**/\r
90UINT16\r
91EFIAPI\r
92PeCoffLoaderGetMachineType (\r
93 IN VOID *Pe32Data\r
94 )\r
95{ \r
96 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
97 EFI_IMAGE_DOS_HEADER *DosHdr;\r
98\r
99 ASSERT (Pe32Data != NULL);\r
100\r
101 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
102 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
103 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
104\r
105 } else {\r
106 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)(Pe32Data);\r
107 }\r
108\r
109 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
110 return Hdr.Te->Machine;\r
111 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
112 return Hdr.Pe32->FileHeader.Machine;\r
113 }\r
114\r
115 return 0x0000;\r
116}\r
117\r
118/**\r
119 Returns a pointer to the PDB file name for a PE/COFF image that has been\r
120 loaded into system memory with the PE/COFF Loader Library functions.\r
121\r
122 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If\r
123 the PE/COFF image specified by Pe32Data is not a valid, then NULL is\r
124 returned. If the PE/COFF image specified by Pe32Data does not contain a\r
125 debug directory entry, then NULL is returned. If the debug directory entry\r
126 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,\r
127 then NULL is returned.\r
128 If Pe32Data is NULL, then ASSERT().\r
129\r
130 @param Pe32Data Pointer to the PE/COFF image that is loaded in system\r
131 memory.\r
132\r
133 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL\r
134 if it cannot be retrieved.\r
135\r
136**/\r
137VOID *\r
138EFIAPI\r
139PeCoffLoaderGetPdbPointer (\r
140 IN VOID *Pe32Data\r
141 )\r
142{\r
143 EFI_IMAGE_DOS_HEADER *DosHdr;\r
144 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
145 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
146 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
147 UINTN DirCount;\r
148 VOID *CodeViewEntryPointer;\r
149 INTN TEImageAdjust;\r
150 UINT32 NumberOfRvaAndSizes;\r
151 UINT16 Magic;\r
152\r
153 ASSERT (Pe32Data != NULL);\r
154\r
155 TEImageAdjust = 0;\r
156 DirectoryEntry = NULL;\r
157 DebugEntry = NULL;\r
158 NumberOfRvaAndSizes = 0;\r
159\r
160 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
161 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
162 //\r
163 // DOS image header is present, so read the PE header after the DOS image header.\r
164 //\r
165 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
166 } else {\r
167 //\r
168 // DOS image header is not present, so PE header is at the image base.\r
169 //\r
170 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
171 }\r
172\r
173 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
174 if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
175 DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
176 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
177 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +\r
178 Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
179 TEImageAdjust);\r
180 }\r
181 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
182 //\r
183 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.\r
184 // It is due to backward-compatibility, for some system might\r
185 // generate PE32+ image with PE32 Magic.\r
186 //\r
187 switch (Hdr.Pe32->FileHeader.Machine) {\r
188 case EFI_IMAGE_MACHINE_IA32:\r
189 //\r
190 // Assume PE32 image with IA32 Machine field.\r
191 //\r
192 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
193 break;\r
194 case EFI_IMAGE_MACHINE_X64:\r
e54ce904 195 case EFI_IMAGE_MACHINE_IA64:\r
804405e7 196 //\r
e54ce904 197 // Assume PE32+ image with X64 or IA64 Machine field\r
804405e7 198 //\r
199 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
200 break;\r
201 default:\r
202 //\r
203 // For unknow Machine field, use Magic in optional Header\r
204 //\r
205 Magic = Hdr.Pe32->OptionalHeader.Magic;\r
206 }\r
207\r
208 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
209 //\r
210 // Use PE32 offset get Debug Directory Entry\r
211 //\r
212 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
213 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
214 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
215 } else if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
216 //\r
217 // Use PE32+ offset get Debug Directory Entry\r
218 //\r
219 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
220 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
221 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
222 }\r
223\r
224 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
225 DirectoryEntry = NULL;\r
226 DebugEntry = NULL;\r
227 }\r
228 } else {\r
229 return NULL;\r
230 }\r
231\r
232 if (DebugEntry == NULL || DirectoryEntry == NULL) {\r
233 return NULL;\r
234 }\r
235\r
236 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
237 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
238 if (DebugEntry->SizeOfData > 0) {\r
239 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);\r
240 switch (* (UINT32 *) CodeViewEntryPointer) {\r
241 case CODEVIEW_SIGNATURE_NB10:\r
242 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));\r
243 case CODEVIEW_SIGNATURE_RSDS:\r
244 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));\r
ccd55824 245 case CODEVIEW_SIGNATURE_MTOC:\r
246 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_MTOC_ENTRY));\r
804405e7 247 default:\r
248 break;\r
249 }\r
250 }\r
251 }\r
252 }\r
253\r
254 return NULL;\r
255}\r
225290eb
A
256\r
257\r
258/**\r
259 Returns the size of the PE/COFF headers\r
260\r
261 Returns the size of the PE/COFF header specified by Pe32Data.\r
262 If Pe32Data is NULL, then ASSERT().\r
263\r
264 @param Pe32Data Pointer to the PE/COFF image that is loaded in system\r
265 memory.\r
266\r
7e35214b 267 @return Size of PE/COFF header in bytes or zero if not a valid image.\r
225290eb
A
268\r
269**/\r
7e35214b 270UINT32\r
271EFIAPI\r
272PeCoffGetSizeOfHeaders (\r
273 IN VOID *Pe32Data\r
274 )\r
275{\r
276 EFI_IMAGE_DOS_HEADER *DosHdr;\r
277 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
278 UINTN SizeOfHeaders;\r
279\r
225290eb 280 ASSERT (Pe32Data != NULL);\r
7e35214b 281 \r
282 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
283 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
284 //\r
285 // DOS image header is present, so read the PE header after the DOS image header.\r
286 //\r
287 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHdr->e_lfanew) & 0x0ffff));\r
288 } else {\r
289 //\r
290 // DOS image header is not present, so PE header is at the image base.\r
291 //\r
292 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
293 }\r
294\r
295 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
296 SizeOfHeaders = sizeof (EFI_TE_IMAGE_HEADER) + (UINTN)Hdr.Te->BaseOfCode - (UINTN)Hdr.Te->StrippedSize;\r
297 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
298 SizeOfHeaders = Hdr.Pe32->OptionalHeader.SizeOfHeaders;\r
299 } else {\r
300 SizeOfHeaders = 0;\r
301 }\r
302\r
303 return SizeOfHeaders;\r
225290eb
A
304}\r
305\r