]> git.proxmox.com Git - mirror_edk2.git/blame - MdePkg/Library/BasePeCoffGetEntryPointLib/PeCoffGetEntryPoint.c
Removed MdePkg usage of ModuleName: in file headers
[mirror_edk2.git] / MdePkg / Library / BasePeCoffGetEntryPointLib / PeCoffGetEntryPoint.c
CommitLineData
e1f414b6 1/** @file\r
2 Tiano PE/COFF loader.\r
3\r
4 Copyright (c) 2006 - 2007, Intel Corporation<BR>\r
5 All rights reserved. This program and the accompanying materials\r
6 are licensed and made available under the terms and conditions of the BSD License\r
7 which accompanies this distribution. The full text of the license may be found at\r
8 http://opensource.org/licenses/bsd-license.php\r
9\r
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
e1f414b6 13**/\r
14\r
e1f414b6 15//\r
c7d265a9 16// The package level header files this module uses\r
17//\r
18#include <Base.h>\r
19//\r
20// The protocols, PPI and GUID defintions for this module\r
e1f414b6 21//\r
c7d265a9 22//\r
23// The Library classes this module consumes\r
24//\r
25#include <Library/PeCoffGetEntryPointLib.h>\r
26#include <Library/DebugLib.h>\r
27\r
28#include <IndustryStandard/PeImage.h>\r
e1f414b6 29\r
30/**\r
31 Retrieves and returns a pointer to the entry point to a PE/COFF image that has been loaded\r
32 into system memory with the PE/COFF Loader Library functions.\r
33\r
34 Retrieves the entry point to the PE/COFF image specified by Pe32Data and returns this entry\r
35 point in EntryPoint. If the entry point could not be retrieved from the PE/COFF image, then\r
36 return RETURN_INVALID_PARAMETER. Otherwise return RETURN_SUCCESS.\r
37 If Pe32Data is NULL, then ASSERT().\r
38 If EntryPoint is NULL, then ASSERT().\r
39\r
40 @param Pe32Data Pointer to the PE/COFF image that is loaded in system memory.\r
41 @param EntryPoint Pointer to entry point to the PE/COFF image to return.\r
42\r
43 @retval RETURN_SUCCESS EntryPoint was returned.\r
44 @retval RETURN_INVALID_PARAMETER The entry point could not be found in the PE/COFF image.\r
45\r
46**/\r
47RETURN_STATUS\r
48EFIAPI\r
49PeCoffLoaderGetEntryPoint (\r
50 IN VOID *Pe32Data,\r
51 OUT VOID **EntryPoint\r
52 )\r
53{\r
54 EFI_IMAGE_DOS_HEADER *DosHeader;\r
55 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Header;\r
56\r
57 ASSERT (Pe32Data != NULL);\r
58 ASSERT (EntryPoint != NULL);\r
59\r
60 DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
61 if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
62 //\r
63 // DOS image header is present, so read the PE header after the DOS image header.\r
64 //\r
65 Header.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff));\r
66 } else {\r
67 //\r
68 // DOS image header is not present, so PE header is at the image base.\r
69 //\r
70 Header.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
71 }\r
72\r
73 //\r
74 // Calculate the entry point relative to the start of the image.\r
75 // AddressOfEntryPoint is common for PE32 & PE32+\r
76 //\r
77 *EntryPoint = (VOID *)((UINTN)Pe32Data + (UINTN)(Header.Pe32->OptionalHeader.AddressOfEntryPoint & 0x0ffffffff));\r
78 return RETURN_SUCCESS;\r
79}\r
80\r
81\r
82/**\r
83 Returns the machine type of a PE/COFF image.\r
84\r
85 Returns the machine type from the PE/COFF image specified by Pe32Data.\r
86 If Pe32Data is NULL, then ASSERT().\r
87\r
88 @param Pe32Data Pointer to the PE/COFF image that is loaded in system\r
89 memory.\r
90\r
91 @return Machine type or zero if not a valid iamge.\r
92\r
93**/\r
94UINT16\r
95EFIAPI\r
96PeCoffLoaderGetMachineType (\r
97 IN VOID *Pe32Data\r
98 )\r
99{\r
100 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
101 EFI_IMAGE_DOS_HEADER *DosHdr;\r
102\r
103 DosHdr = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
104 if (DosHdr->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
105 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data + DosHdr->e_lfanew);\r
106 } else {\r
107 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN)Pe32Data);\r
108 }\r
109\r
110 if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
111 return Hdr.Pe32->FileHeader.Machine;\r
112 }\r
113\r
114 return 0x0000;\r
115}\r
116\r
117/**\r
118 Returns a pointer to the PDB file name for a PE/COFF image that has been\r
119 loaded into system memory with the PE/COFF Loader Library functions.\r
120\r
121 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If\r
122 the PE/COFF image specified by Pe32Data is not a valid, then NULL is\r
123 returned. If the PE/COFF image specified by Pe32Data does not contain a\r
124 debug directory entry, then NULL is returned. If the debug directory entry\r
125 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,\r
126 then NULL is returned.\r
127 If Pe32Data is NULL, then ASSERT().\r
128\r
129 @param Pe32Data Pointer to the PE/COFF image that is loaded in system\r
130 memory.\r
131\r
132 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL\r
133 if it cannot be retrieved.\r
134\r
135**/\r
136VOID *\r
137EFIAPI\r
138PeCoffLoaderGetPdbPointer (\r
139 IN VOID *Pe32Data\r
140 )\r
141{\r
142 EFI_IMAGE_DOS_HEADER *DosHeader;\r
143 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr;\r
144 EFI_IMAGE_DATA_DIRECTORY *DirectoryEntry;\r
145 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *DebugEntry;\r
146 UINTN DirCount;\r
147 VOID *CodeViewEntryPointer;\r
148 INTN TEImageAdjust;\r
149 UINT32 NumberOfRvaAndSizes;\r
150 UINT16 Magic;\r
151\r
152 ASSERT (Pe32Data != NULL);\r
153\r
154 TEImageAdjust = 0;\r
155 DirectoryEntry = NULL;\r
156 DebugEntry = NULL;\r
157 NumberOfRvaAndSizes = 0;\r
158\r
159 DosHeader = (EFI_IMAGE_DOS_HEADER *)Pe32Data;\r
160 if (DosHeader->e_magic == EFI_IMAGE_DOS_SIGNATURE) {\r
161 //\r
162 // DOS image header is present, so read the PE header after the DOS image header.\r
163 //\r
164 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)((UINTN) Pe32Data + (UINTN) ((DosHeader->e_lfanew) & 0x0ffff));\r
165 } else {\r
166 //\r
167 // DOS image header is not present, so PE header is at the image base.\r
168 //\r
169 Hdr.Pe32 = (EFI_IMAGE_NT_HEADERS32 *)Pe32Data;\r
170 }\r
171\r
172 if (Hdr.Te->Signature == EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
173 if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
174 DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
175 TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
176 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +\r
177 Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress +\r
178 TEImageAdjust);\r
179 }\r
180 } else if (Hdr.Pe32->Signature == EFI_IMAGE_NT_SIGNATURE) {\r
181 //\r
182 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.\r
183 // It is due to backward-compatibility, for some system might\r
184 // generate PE32+ image with PE32 Magic.\r
185 //\r
186 switch (Hdr.Pe32->FileHeader.Machine) {\r
187 case EFI_IMAGE_MACHINE_IA32:\r
188 //\r
189 // Assume PE32 image with IA32 Machine field.\r
190 //\r
191 Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
192 break;\r
193 case EFI_IMAGE_MACHINE_X64:\r
194 case EFI_IMAGE_MACHINE_IPF:\r
195 //\r
196 // Assume PE32+ image with X64 or IPF Machine field\r
197 //\r
198 Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
199 break;\r
200 default:\r
201 //\r
202 // For unknow Machine field, use Magic in optional Header\r
203 //\r
204 Magic = Hdr.Pe32->OptionalHeader.Magic;\r
205 }\r
206\r
207 if (Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
208 //\r
209 // Use PE32 offset get Debug Directory Entry\r
210 //\r
211 NumberOfRvaAndSizes = Hdr.Pe32->OptionalHeader.NumberOfRvaAndSizes;\r
212 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
213 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
214 } else if (Hdr.Pe32->OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC) {\r
215 //\r
216 // Use PE32+ offset get Debug Directory Entry\r
217 //\r
218 NumberOfRvaAndSizes = Hdr.Pe32Plus->OptionalHeader.NumberOfRvaAndSizes;\r
219 DirectoryEntry = (EFI_IMAGE_DATA_DIRECTORY *)&(Hdr.Pe32Plus->OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG]);\r
220 DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) ((UINTN) Pe32Data + DirectoryEntry->VirtualAddress);\r
221 }\r
222\r
223 if (NumberOfRvaAndSizes <= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG) {\r
224 DirectoryEntry = NULL;\r
225 DebugEntry = NULL;\r
226 }\r
227 } else {\r
228 return NULL;\r
229 }\r
230\r
231 if (DebugEntry == NULL || DirectoryEntry == NULL) {\r
232 return NULL;\r
233 }\r
234\r
235 for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount++, DebugEntry++) {\r
236 if (DebugEntry->Type == EFI_IMAGE_DEBUG_TYPE_CODEVIEW) {\r
237 if (DebugEntry->SizeOfData > 0) {\r
238 CodeViewEntryPointer = (VOID *) ((UINTN) DebugEntry->RVA + ((UINTN)Pe32Data) + (UINTN)TEImageAdjust);\r
239 switch (* (UINT32 *) CodeViewEntryPointer) {\r
240 case CODEVIEW_SIGNATURE_NB10:\r
241 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY));\r
242 case CODEVIEW_SIGNATURE_RSDS:\r
243 return (VOID *) ((CHAR8 *)CodeViewEntryPointer + sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY));\r
244 default:\r
245 break;\r
246 }\r
247 }\r
248 }\r
249 }\r
250\r
251 return NULL;\r
252}\r
253\r
254\r