3 Functions to get info and load PE/COFF image.
5 Copyright (c) 2004 - 2008, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include <Common/UefiBaseTypes.h>
17 #include <CommonLib.h>
18 #include <IndustryStandard/PeImage.h>
19 #include "PeCoffLib.h"
23 EFI_IMAGE_OPTIONAL_HEADER32
*Optional32
;
24 EFI_IMAGE_OPTIONAL_HEADER64
*Optional64
;
25 } EFI_IMAGE_OPTIONAL_HEADER_POINTER
;
29 PeCoffLoaderGetPeHeader (
30 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
31 OUT EFI_IMAGE_OPTIONAL_HEADER_UNION
**PeHdr
,
32 OUT EFI_TE_IMAGE_HEADER
**TeHdr
37 PeCoffLoaderCheckImageType (
38 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
39 IN EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
,
40 IN EFI_TE_IMAGE_HEADER
*TeHdr
45 PeCoffLoaderImageAddress (
46 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
51 PeCoffLoaderRelocateIa32Image (
54 IN OUT CHAR8
**FixupData
,
59 PeCoffLoaderRelocateX64Image (
62 IN OUT CHAR8
**FixupData
,
67 PeCoffLoaderRelocateIpfImage (
70 IN OUT CHAR8
**FixupData
,
76 PeCoffLoaderGetPeHeader (
77 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
78 OUT EFI_IMAGE_OPTIONAL_HEADER_UNION
**PeHdr
,
79 OUT EFI_TE_IMAGE_HEADER
**TeHdr
85 Retrieves the PE or TE Header from a PE/COFF or TE image
89 ImageContext - The context of the image being loaded
91 PeHdr - The buffer in which to return the PE header
93 TeHdr - The buffer in which to return the TE header
97 RETURN_SUCCESS if the PE or TE Header is read,
98 Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
102 RETURN_STATUS Status
;
103 EFI_IMAGE_DOS_HEADER DosHdr
;
106 ImageContext
->IsTeImage
= FALSE
;
108 // Read the DOS image headers
110 Size
= sizeof (EFI_IMAGE_DOS_HEADER
);
111 Status
= ImageContext
->ImageRead (
112 ImageContext
->Handle
,
117 if (RETURN_ERROR (Status
)) {
118 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
122 ImageContext
->PeCoffHeaderOffset
= 0;
123 if (DosHdr
.e_magic
== EFI_IMAGE_DOS_SIGNATURE
) {
125 // DOS image header is present, so read the PE header after the DOS image header
127 ImageContext
->PeCoffHeaderOffset
= DosHdr
.e_lfanew
;
130 // Get the PE/COFF Header pointer
132 *PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*) ((UINTN
)ImageContext
->Handle
+ ImageContext
->PeCoffHeaderOffset
);
133 if ((*PeHdr
)->Pe32
.Signature
!= EFI_IMAGE_NT_SIGNATURE
) {
135 // Check the PE/COFF Header Signature. If not, then try to get a TE header
137 *TeHdr
= (EFI_TE_IMAGE_HEADER
*)*PeHdr
;
138 if ((*TeHdr
)->Signature
!= EFI_TE_IMAGE_HEADER_SIGNATURE
) {
139 return RETURN_UNSUPPORTED
;
141 ImageContext
->IsTeImage
= TRUE
;
144 return RETURN_SUCCESS
;
149 PeCoffLoaderCheckImageType (
150 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
151 IN EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
,
152 IN EFI_TE_IMAGE_HEADER
*TeHdr
158 Checks the PE or TE header of a PE/COFF or TE image to determine if it supported
162 ImageContext - The context of the image being loaded
164 PeHdr - The buffer in which to return the PE header
166 TeHdr - The buffer in which to return the TE header
170 RETURN_SUCCESS if the PE/COFF or TE image is supported
171 RETURN_UNSUPPORTED of the PE/COFF or TE image is not supported.
176 // See if the machine type is supported.
177 // We support a native machine type (IA-32/Itanium-based)
179 if (ImageContext
->IsTeImage
== FALSE
) {
180 ImageContext
->Machine
= PeHdr
->Pe32
.FileHeader
.Machine
;
182 ImageContext
->Machine
= TeHdr
->Machine
;
185 if (ImageContext
->Machine
!= EFI_IMAGE_MACHINE_IA32
&& \
186 ImageContext
->Machine
!= EFI_IMAGE_MACHINE_IA64
&& \
187 ImageContext
->Machine
!= EFI_IMAGE_MACHINE_X64
&& \
188 ImageContext
->Machine
!= EFI_IMAGE_MACHINE_ARMT
&& \
189 ImageContext
->Machine
!= EFI_IMAGE_MACHINE_EBC
) {
190 if (ImageContext
->Machine
== IMAGE_FILE_MACHINE_ARM
) {
192 // There are two types of ARM images. Pure ARM and ARM/Thumb.
193 // If we see the ARM say it is the ARM/Thumb so there is only
194 // a single machine type we need to check for ARM.
196 ImageContext
->Machine
= EFI_IMAGE_MACHINE_ARMT
;
197 if (ImageContext
->IsTeImage
== FALSE
) {
198 PeHdr
->Pe32
.FileHeader
.Machine
= ImageContext
->Machine
;
200 TeHdr
->Machine
= ImageContext
->Machine
;
205 // unsupported PeImage machine type
207 return RETURN_UNSUPPORTED
;
212 // See if the image type is supported. We support EFI Applications,
213 // EFI Boot Service Drivers, EFI Runtime Drivers and EFI SAL Drivers.
215 if (ImageContext
->IsTeImage
== FALSE
) {
216 ImageContext
->ImageType
= PeHdr
->Pe32
.OptionalHeader
.Subsystem
;
218 ImageContext
->ImageType
= (UINT16
) (TeHdr
->Subsystem
);
221 if (ImageContext
->ImageType
!= EFI_IMAGE_SUBSYSTEM_EFI_APPLICATION
&& \
222 ImageContext
->ImageType
!= EFI_IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER
&& \
223 ImageContext
->ImageType
!= EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
&& \
224 ImageContext
->ImageType
!= EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER
) {
226 // upsupported PeImage subsystem type
228 return RETURN_UNSUPPORTED
;
231 return RETURN_SUCCESS
;
236 PeCoffLoaderGetImageInfo (
237 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
243 Retrieves information on a PE/COFF image
247 This - Calling context
248 ImageContext - The context of the image being loaded
252 RETURN_SUCCESS - The information on the PE/COFF image was collected.
253 RETURN_INVALID_PARAMETER - ImageContext is NULL.
254 RETURN_UNSUPPORTED - The PE/COFF image is not supported.
255 Otherwise - The error status from reading the PE/COFF image using the
256 ImageContext->ImageRead() function
260 RETURN_STATUS Status
;
261 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
262 EFI_TE_IMAGE_HEADER
*TeHdr
;
263 EFI_IMAGE_DATA_DIRECTORY
*DebugDirectoryEntry
;
266 UINTN DebugDirectoryEntryRva
;
267 UINTN DebugDirectoryEntryFileOffset
;
268 UINTN SectionHeaderOffset
;
269 EFI_IMAGE_SECTION_HEADER SectionHeader
;
270 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY DebugEntry
;
271 EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader
;
275 DebugDirectoryEntry
= NULL
;
276 DebugDirectoryEntryRva
= 0;
278 if (NULL
== ImageContext
) {
279 return RETURN_INVALID_PARAMETER
;
284 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
286 Status
= PeCoffLoaderGetPeHeader (ImageContext
, &PeHdr
, &TeHdr
);
287 if (RETURN_ERROR (Status
)) {
292 // Verify machine type
294 Status
= PeCoffLoaderCheckImageType (ImageContext
, PeHdr
, TeHdr
);
295 if (RETURN_ERROR (Status
)) {
298 OptionHeader
.Header
= (VOID
*) &(PeHdr
->Pe32
.OptionalHeader
);
301 // Retrieve the base address of the image
303 if (!(ImageContext
->IsTeImage
)) {
304 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
305 ImageContext
->ImageAddress
= (PHYSICAL_ADDRESS
) OptionHeader
.Optional32
->ImageBase
;
307 ImageContext
->ImageAddress
= (PHYSICAL_ADDRESS
) OptionHeader
.Optional64
->ImageBase
;
310 ImageContext
->ImageAddress
= (PHYSICAL_ADDRESS
) (TeHdr
->ImageBase
+ TeHdr
->StrippedSize
- sizeof (EFI_TE_IMAGE_HEADER
));
313 // Initialize the alternate destination address to 0 indicating that it
314 // should not be used.
316 ImageContext
->DestinationAddress
= 0;
319 // Initialize the codeview pointer.
321 ImageContext
->CodeView
= NULL
;
322 ImageContext
->PdbPointer
= NULL
;
325 // Three cases with regards to relocations:
326 // - Image has base relocs, RELOCS_STRIPPED==0 => image is relocatable
327 // - Image has no base relocs, RELOCS_STRIPPED==1 => Image is not relocatable
328 // - Image has no base relocs, RELOCS_STRIPPED==0 => Image is relocatable but
329 // has no base relocs to apply
330 // Obviously having base relocations with RELOCS_STRIPPED==1 is invalid.
332 // Look at the file header to determine if relocations have been stripped, and
333 // save this info in the image context for later use.
335 if ((!(ImageContext
->IsTeImage
)) && ((PeHdr
->Pe32
.FileHeader
.Characteristics
& EFI_IMAGE_FILE_RELOCS_STRIPPED
) != 0)) {
336 ImageContext
->RelocationsStripped
= TRUE
;
337 } else if ((ImageContext
->IsTeImage
) && (TeHdr
->DataDirectory
[0].Size
== 0)) {
338 ImageContext
->RelocationsStripped
= TRUE
;
340 ImageContext
->RelocationsStripped
= FALSE
;
343 if (!(ImageContext
->IsTeImage
)) {
345 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
346 ImageContext
->ImageSize
= (UINT64
) OptionHeader
.Optional32
->SizeOfImage
;
347 ImageContext
->SectionAlignment
= OptionHeader
.Optional32
->SectionAlignment
;
348 ImageContext
->SizeOfHeaders
= OptionHeader
.Optional32
->SizeOfHeaders
;
351 // Modify ImageSize to contain .PDB file name if required and initialize
354 if (OptionHeader
.Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
355 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(OptionHeader
.Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
356 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
359 ImageContext
->ImageSize
= (UINT64
) OptionHeader
.Optional64
->SizeOfImage
;
360 ImageContext
->SectionAlignment
= OptionHeader
.Optional64
->SectionAlignment
;
361 ImageContext
->SizeOfHeaders
= OptionHeader
.Optional64
->SizeOfHeaders
;
364 // Modify ImageSize to contain .PDB file name if required and initialize
367 if (OptionHeader
.Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
) {
368 DebugDirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*) &(OptionHeader
.Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
369 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
373 if (DebugDirectoryEntryRva
!= 0) {
375 // Determine the file offset of the debug directory... This means we walk
376 // the sections to find which section contains the RVA of the debug
379 DebugDirectoryEntryFileOffset
= 0;
381 SectionHeaderOffset
= (UINTN
)(
382 ImageContext
->PeCoffHeaderOffset
+
384 sizeof (EFI_IMAGE_FILE_HEADER
) +
385 PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
388 for (Index
= 0; Index
< PeHdr
->Pe32
.FileHeader
.NumberOfSections
; Index
++) {
390 // Read section header from file
392 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
393 Status
= ImageContext
->ImageRead (
394 ImageContext
->Handle
,
399 if (RETURN_ERROR (Status
)) {
400 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
404 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
405 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
406 DebugDirectoryEntryFileOffset
=
407 DebugDirectoryEntryRva
- SectionHeader
.VirtualAddress
+ SectionHeader
.PointerToRawData
;
411 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
414 if (DebugDirectoryEntryFileOffset
!= 0) {
415 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) {
417 // Read next debug directory entry
419 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
420 Status
= ImageContext
->ImageRead (
421 ImageContext
->Handle
,
422 DebugDirectoryEntryFileOffset
+ Index
,
426 if (RETURN_ERROR (Status
)) {
427 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
431 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
432 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
);
433 if (DebugEntry
.RVA
== 0 && DebugEntry
.FileOffset
!= 0) {
434 ImageContext
->ImageSize
+= DebugEntry
.SizeOfData
;
437 return RETURN_SUCCESS
;
443 ImageContext
->ImageSize
= 0;
444 ImageContext
->SectionAlignment
= 4096;
445 ImageContext
->SizeOfHeaders
= sizeof (EFI_TE_IMAGE_HEADER
) + (UINTN
) TeHdr
->BaseOfCode
- (UINTN
) TeHdr
->StrippedSize
;
447 DebugDirectoryEntry
= &TeHdr
->DataDirectory
[1];
448 DebugDirectoryEntryRva
= DebugDirectoryEntry
->VirtualAddress
;
449 SectionHeaderOffset
= (UINTN
) (sizeof (EFI_TE_IMAGE_HEADER
));
451 DebugDirectoryEntryFileOffset
= 0;
453 for (Index
= 0; Index
< TeHdr
->NumberOfSections
;) {
455 // Read section header from file
457 Size
= sizeof (EFI_IMAGE_SECTION_HEADER
);
458 Status
= ImageContext
->ImageRead (
459 ImageContext
->Handle
,
464 if (RETURN_ERROR (Status
)) {
465 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
469 if (DebugDirectoryEntryRva
>= SectionHeader
.VirtualAddress
&&
470 DebugDirectoryEntryRva
< SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
) {
471 DebugDirectoryEntryFileOffset
= DebugDirectoryEntryRva
-
472 SectionHeader
.VirtualAddress
+
473 SectionHeader
.PointerToRawData
+
474 sizeof (EFI_TE_IMAGE_HEADER
) -
478 // File offset of the debug directory was found, if this is not the last
479 // section, then skip to the last section for calculating the image size.
481 if (Index
< (UINTN
) TeHdr
->NumberOfSections
- 1) {
482 SectionHeaderOffset
+= (TeHdr
->NumberOfSections
- 1 - Index
) * sizeof (EFI_IMAGE_SECTION_HEADER
);
483 Index
= TeHdr
->NumberOfSections
- 1;
489 // In Te image header there is not a field to describe the ImageSize.
490 // Actually, the ImageSize equals the RVA plus the VirtualSize of
491 // the last section mapped into memory (Must be rounded up to
492 // a mulitple of Section Alignment). Per the PE/COFF specification, the
493 // section headers in the Section Table must appear in order of the RVA
494 // values for the corresponding sections. So the ImageSize can be determined
495 // by the RVA and the VirtualSize of the last section header in the
498 if ((++Index
) == (UINTN
) TeHdr
->NumberOfSections
) {
499 ImageContext
->ImageSize
= (SectionHeader
.VirtualAddress
+ SectionHeader
.Misc
.VirtualSize
+
500 ImageContext
->SectionAlignment
- 1) & ~(ImageContext
->SectionAlignment
- 1);
503 SectionHeaderOffset
+= sizeof (EFI_IMAGE_SECTION_HEADER
);
506 if (DebugDirectoryEntryFileOffset
!= 0) {
507 for (Index
= 0; Index
< DebugDirectoryEntry
->Size
; Index
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
)) {
509 // Read next debug directory entry
511 Size
= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
);
512 Status
= ImageContext
->ImageRead (
513 ImageContext
->Handle
,
514 DebugDirectoryEntryFileOffset
,
518 if (RETURN_ERROR (Status
)) {
519 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
523 if (DebugEntry
.Type
== EFI_IMAGE_DEBUG_TYPE_CODEVIEW
) {
524 ImageContext
->DebugDirectoryEntryRva
= (UINT32
) (DebugDirectoryEntryRva
+ Index
);
525 return RETURN_SUCCESS
;
531 return RETURN_SUCCESS
;
536 PeCoffLoaderImageAddress (
537 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
,
544 Converts an image address to the loaded address
548 ImageContext - The context of the image being loaded
550 Address - The address to be converted to the loaded address
554 NULL if the address can not be converted, otherwise, the converted address
558 if (Address
>= ImageContext
->ImageSize
) {
559 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
563 return (UINT8
*) ((UINTN
) ImageContext
->ImageAddress
+ Address
);
568 PeCoffLoaderRelocateImage (
569 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
575 Relocates a PE/COFF image in memory
579 This - Calling context
581 ImageContext - Contains information on the loaded image to relocate
585 RETURN_SUCCESS if the PE/COFF image was relocated
586 RETURN_LOAD_ERROR if the image is not a valid PE/COFF image
587 RETURN_UNSUPPORTED not support
591 RETURN_STATUS Status
;
592 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
593 EFI_TE_IMAGE_HEADER
*TeHdr
;
594 EFI_IMAGE_DATA_DIRECTORY
*RelocDir
;
596 EFI_IMAGE_BASE_RELOCATION
*RelocBase
;
597 EFI_IMAGE_BASE_RELOCATION
*RelocBaseEnd
;
605 PHYSICAL_ADDRESS BaseAddress
;
607 EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader
;
614 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
617 // If there are no relocation entries, then we are done
619 if (ImageContext
->RelocationsStripped
) {
620 return RETURN_SUCCESS
;
624 // If the destination address is not 0, use that rather than the
625 // image address as the relocation target.
627 if (ImageContext
->DestinationAddress
) {
628 BaseAddress
= ImageContext
->DestinationAddress
;
630 BaseAddress
= ImageContext
->ImageAddress
;
633 if (!(ImageContext
->IsTeImage
)) {
634 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)((UINTN
)ImageContext
->ImageAddress
+
635 ImageContext
->PeCoffHeaderOffset
);
636 OptionHeader
.Header
= (VOID
*) &(PeHdr
->Pe32
.OptionalHeader
);
637 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
638 Adjust
= (UINT64
) BaseAddress
- OptionHeader
.Optional32
->ImageBase
;
639 OptionHeader
.Optional32
->ImageBase
= (UINT32
) BaseAddress
;
640 MachineType
= ImageContext
->Machine
;
642 // Find the relocation block
644 // Per the PE/COFF spec, you can't assume that a given data directory
645 // is present in the image. You have to check the NumberOfRvaAndSizes in
646 // the optional header to verify a desired directory entry is there.
648 if (OptionHeader
.Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
649 RelocDir
= &OptionHeader
.Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
650 RelocBase
= PeCoffLoaderImageAddress (ImageContext
, RelocDir
->VirtualAddress
);
651 RelocBaseEnd
= PeCoffLoaderImageAddress (
653 RelocDir
->VirtualAddress
+ RelocDir
->Size
- 1
657 // Set base and end to bypass processing below.
659 RelocBase
= RelocBaseEnd
= 0;
662 Adjust
= (UINT64
) BaseAddress
- OptionHeader
.Optional64
->ImageBase
;
663 OptionHeader
.Optional64
->ImageBase
= BaseAddress
;
664 MachineType
= ImageContext
->Machine
;
666 // Find the relocation block
668 // Per the PE/COFF spec, you can't assume that a given data directory
669 // is present in the image. You have to check the NumberOfRvaAndSizes in
670 // the optional header to verify a desired directory entry is there.
672 if (OptionHeader
.Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
673 RelocDir
= &OptionHeader
.Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
674 RelocBase
= PeCoffLoaderImageAddress (ImageContext
, RelocDir
->VirtualAddress
);
675 RelocBaseEnd
= PeCoffLoaderImageAddress (
677 RelocDir
->VirtualAddress
+ RelocDir
->Size
- 1
681 // Set base and end to bypass processing below.
683 RelocBase
= RelocBaseEnd
= 0;
687 TeHdr
= (EFI_TE_IMAGE_HEADER
*) (UINTN
) (ImageContext
->ImageAddress
);
688 Adjust
= (UINT64
) (BaseAddress
- TeHdr
->ImageBase
);
689 TeHdr
->ImageBase
= (UINT64
) (BaseAddress
);
690 MachineType
= TeHdr
->Machine
;
693 // Find the relocation block
695 RelocDir
= &TeHdr
->DataDirectory
[0];
696 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*)(UINTN
)(
697 ImageContext
->ImageAddress
+
698 RelocDir
->VirtualAddress
+
699 sizeof(EFI_TE_IMAGE_HEADER
) -
702 RelocBaseEnd
= (EFI_IMAGE_BASE_RELOCATION
*) ((UINTN
) RelocBase
+ (UINTN
) RelocDir
->Size
- 1);
706 // Run the relocation information and apply the fixups
708 FixupData
= ImageContext
->FixupData
;
709 while (RelocBase
< RelocBaseEnd
) {
711 Reloc
= (UINT16
*) ((CHAR8
*) RelocBase
+ sizeof (EFI_IMAGE_BASE_RELOCATION
));
712 RelocEnd
= (UINT16
*) ((CHAR8
*) RelocBase
+ RelocBase
->SizeOfBlock
);
713 if (!(ImageContext
->IsTeImage
)) {
714 FixupBase
= PeCoffLoaderImageAddress (ImageContext
, RelocBase
->VirtualAddress
);
716 FixupBase
= (CHAR8
*)(UINTN
)(ImageContext
->ImageAddress
+
717 RelocBase
->VirtualAddress
+
718 sizeof(EFI_TE_IMAGE_HEADER
) -
723 if ((CHAR8
*) RelocEnd
< (CHAR8
*) ((UINTN
) ImageContext
->ImageAddress
) ||
724 (CHAR8
*) RelocEnd
> (CHAR8
*)((UINTN
)ImageContext
->ImageAddress
+
725 (UINTN
)ImageContext
->ImageSize
)) {
726 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
727 return RETURN_LOAD_ERROR
;
731 // Run this relocation record
733 while (Reloc
< RelocEnd
) {
735 Fixup
= FixupBase
+ (*Reloc
& 0xFFF);
736 switch ((*Reloc
) >> 12) {
737 case EFI_IMAGE_REL_BASED_ABSOLUTE
:
740 case EFI_IMAGE_REL_BASED_HIGH
:
741 F16
= (UINT16
*) Fixup
;
742 *F16
= (UINT16
) (*F16
+ ((UINT16
) ((UINT32
) Adjust
>> 16)));
743 if (FixupData
!= NULL
) {
744 *(UINT16
*) FixupData
= *F16
;
745 FixupData
= FixupData
+ sizeof (UINT16
);
749 case EFI_IMAGE_REL_BASED_LOW
:
750 F16
= (UINT16
*) Fixup
;
751 *F16
= (UINT16
) (*F16
+ (UINT16
) Adjust
);
752 if (FixupData
!= NULL
) {
753 *(UINT16
*) FixupData
= *F16
;
754 FixupData
= FixupData
+ sizeof (UINT16
);
758 case EFI_IMAGE_REL_BASED_HIGHLOW
:
759 F32
= (UINT32
*) Fixup
;
760 *F32
= *F32
+ (UINT32
) Adjust
;
761 if (FixupData
!= NULL
) {
762 FixupData
= ALIGN_POINTER (FixupData
, sizeof (UINT32
));
763 *(UINT32
*) FixupData
= *F32
;
764 FixupData
= FixupData
+ sizeof (UINT32
);
768 case EFI_IMAGE_REL_BASED_HIGHADJ
:
770 // Return the same EFI_UNSUPPORTED return code as
771 // PeCoffLoaderRelocateImageEx() returns if it does not recognize
772 // the relocation type.
774 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
775 return RETURN_UNSUPPORTED
;
778 switch (MachineType
) {
779 case EFI_IMAGE_MACHINE_IA32
:
780 case EFI_IMAGE_MACHINE_ARMT
:
781 Status
= PeCoffLoaderRelocateIa32Image (Reloc
, Fixup
, &FixupData
, Adjust
);
783 case EFI_IMAGE_MACHINE_X64
:
784 Status
= PeCoffLoaderRelocateX64Image (Reloc
, Fixup
, &FixupData
, Adjust
);
786 case EFI_IMAGE_MACHINE_IA64
:
787 Status
= PeCoffLoaderRelocateIpfImage (Reloc
, Fixup
, &FixupData
, Adjust
);
790 Status
= RETURN_UNSUPPORTED
;
793 if (RETURN_ERROR (Status
)) {
794 ImageContext
->ImageError
= IMAGE_ERROR_FAILED_RELOCATION
;
800 // Next relocation record
808 RelocBase
= (EFI_IMAGE_BASE_RELOCATION
*) RelocEnd
;
811 return RETURN_SUCCESS
;
816 PeCoffLoaderLoadImage (
817 IN OUT PE_COFF_LOADER_IMAGE_CONTEXT
*ImageContext
823 Loads a PE/COFF image into memory
827 This - Calling context
829 ImageContext - Contains information on image to load into memory
833 RETURN_SUCCESS if the PE/COFF image was loaded
834 RETURN_BUFFER_TOO_SMALL if the caller did not provide a large enough buffer
835 RETURN_LOAD_ERROR if the image is a runtime driver with no relocations
836 RETURN_INVALID_PARAMETER if the image address is invalid
840 RETURN_STATUS Status
;
841 EFI_IMAGE_OPTIONAL_HEADER_UNION
*PeHdr
;
842 EFI_TE_IMAGE_HEADER
*TeHdr
;
843 PE_COFF_LOADER_IMAGE_CONTEXT CheckContext
;
844 EFI_IMAGE_SECTION_HEADER
*FirstSection
;
845 EFI_IMAGE_SECTION_HEADER
*Section
;
846 UINTN NumberOfSections
;
851 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
852 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
854 UINT32 TempDebugEntryRva
;
855 EFI_IMAGE_OPTIONAL_HEADER_POINTER OptionHeader
;
859 OptionHeader
.Header
= NULL
;
863 ImageContext
->ImageError
= IMAGE_ERROR_SUCCESS
;
866 // Copy the provided context info into our local version, get what we
867 // can from the original image, and then use that to make sure everything
870 CopyMem (&CheckContext
, ImageContext
, sizeof (PE_COFF_LOADER_IMAGE_CONTEXT
));
872 Status
= PeCoffLoaderGetImageInfo (&CheckContext
);
873 if (RETURN_ERROR (Status
)) {
878 // Make sure there is enough allocated space for the image being loaded
880 if (ImageContext
->ImageSize
< CheckContext
.ImageSize
) {
881 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_SIZE
;
882 return RETURN_BUFFER_TOO_SMALL
;
886 // If there's no relocations, then make sure it's not a runtime driver,
887 // and that it's being loaded at the linked address.
889 if (CheckContext
.RelocationsStripped
) {
891 // If the image does not contain relocations and it is a runtime driver
892 // then return an error.
894 if (CheckContext
.ImageType
== EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER
) {
895 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SUBSYSTEM
;
896 return RETURN_LOAD_ERROR
;
899 // If the image does not contain relocations, and the requested load address
900 // is not the linked address, then return an error.
902 if (CheckContext
.ImageAddress
!= ImageContext
->ImageAddress
) {
903 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_IMAGE_ADDRESS
;
904 return RETURN_INVALID_PARAMETER
;
908 // Make sure the allocated space has the proper section alignment
910 if (!(ImageContext
->IsTeImage
)) {
911 if ((ImageContext
->ImageAddress
& (CheckContext
.SectionAlignment
- 1)) != 0) {
912 ImageContext
->ImageError
= IMAGE_ERROR_INVALID_SECTION_ALIGNMENT
;
913 return RETURN_INVALID_PARAMETER
;
917 // Read the entire PE/COFF or TE header into memory
919 if (!(ImageContext
->IsTeImage
)) {
920 Status
= ImageContext
->ImageRead (
921 ImageContext
->Handle
,
923 &ImageContext
->SizeOfHeaders
,
924 (VOID
*) (UINTN
) ImageContext
->ImageAddress
927 PeHdr
= (EFI_IMAGE_OPTIONAL_HEADER_UNION
*)
928 ((UINTN
)ImageContext
->ImageAddress
+ ImageContext
->PeCoffHeaderOffset
);
930 OptionHeader
.Header
= (VOID
*) &(PeHdr
->Pe32
.OptionalHeader
);
932 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
933 (UINTN
)ImageContext
->ImageAddress
+
934 ImageContext
->PeCoffHeaderOffset
+
936 sizeof(EFI_IMAGE_FILE_HEADER
) +
937 PeHdr
->Pe32
.FileHeader
.SizeOfOptionalHeader
939 NumberOfSections
= (UINTN
) (PeHdr
->Pe32
.FileHeader
.NumberOfSections
);
941 Status
= ImageContext
->ImageRead (
942 ImageContext
->Handle
,
944 &ImageContext
->SizeOfHeaders
,
945 (VOID
*) (UINTN
) ImageContext
->ImageAddress
948 TeHdr
= (EFI_TE_IMAGE_HEADER
*) (UINTN
) (ImageContext
->ImageAddress
);
950 FirstSection
= (EFI_IMAGE_SECTION_HEADER
*) (
951 (UINTN
)ImageContext
->ImageAddress
+
952 sizeof(EFI_TE_IMAGE_HEADER
)
954 NumberOfSections
= (UINTN
) (TeHdr
->NumberOfSections
);
958 if (RETURN_ERROR (Status
)) {
959 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
960 return RETURN_LOAD_ERROR
;
964 // Load each section of the image
966 Section
= FirstSection
;
967 for (Index
= 0, MaxEnd
= NULL
; Index
< NumberOfSections
; Index
++) {
970 // Compute sections address
972 Base
= PeCoffLoaderImageAddress (ImageContext
, Section
->VirtualAddress
);
973 End
= PeCoffLoaderImageAddress (
975 Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
- 1
977 if (ImageContext
->IsTeImage
) {
978 Base
= (CHAR8
*) ((UINTN
) Base
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
) TeHdr
->StrippedSize
);
979 End
= (CHAR8
*) ((UINTN
) End
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
) TeHdr
->StrippedSize
);
986 // If the base start or end address resolved to 0, then fail.
988 if ((Base
== NULL
) || (End
== NULL
)) {
989 ImageContext
->ImageError
= IMAGE_ERROR_SECTION_NOT_LOADED
;
990 return RETURN_LOAD_ERROR
;
996 Size
= (UINTN
) Section
->Misc
.VirtualSize
;
997 if ((Size
== 0) || (Size
> Section
->SizeOfRawData
)) {
998 Size
= (UINTN
) Section
->SizeOfRawData
;
1001 if (Section
->SizeOfRawData
) {
1002 if (!(ImageContext
->IsTeImage
)) {
1003 Status
= ImageContext
->ImageRead (
1004 ImageContext
->Handle
,
1005 Section
->PointerToRawData
,
1010 Status
= ImageContext
->ImageRead (
1011 ImageContext
->Handle
,
1012 Section
->PointerToRawData
+ sizeof (EFI_TE_IMAGE_HEADER
) - (UINTN
) TeHdr
->StrippedSize
,
1018 if (RETURN_ERROR (Status
)) {
1019 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1025 // If raw size is less then virt size, zero fill the remaining
1028 if (Size
< Section
->Misc
.VirtualSize
) {
1029 ZeroMem (Base
+ Size
, Section
->Misc
.VirtualSize
- Size
);
1039 // Get image's entry point
1041 if (!(ImageContext
->IsTeImage
)) {
1042 ImageContext
->EntryPoint
= (PHYSICAL_ADDRESS
) (UINTN
) PeCoffLoaderImageAddress (
1044 PeHdr
->Pe32
.OptionalHeader
.AddressOfEntryPoint
1047 ImageContext
->EntryPoint
= (PHYSICAL_ADDRESS
) (
1048 (UINTN
)ImageContext
->ImageAddress
+
1049 (UINTN
)TeHdr
->AddressOfEntryPoint
+
1050 (UINTN
)sizeof(EFI_TE_IMAGE_HEADER
) -
1051 (UINTN
) TeHdr
->StrippedSize
1056 // Determine the size of the fixup data
1058 // Per the PE/COFF spec, you can't assume that a given data directory
1059 // is present in the image. You have to check the NumberOfRvaAndSizes in
1060 // the optional header to verify a desired directory entry is there.
1062 if (!(ImageContext
->IsTeImage
)) {
1063 if (PeHdr
->Pe32
.OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
) {
1064 if (OptionHeader
.Optional32
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
1065 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)
1066 &OptionHeader
.Optional32
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1067 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1069 ImageContext
->FixupDataSize
= 0;
1072 if (OptionHeader
.Optional64
->NumberOfRvaAndSizes
> EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
) {
1073 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)
1074 &OptionHeader
.Optional64
->DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC
];
1075 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1077 ImageContext
->FixupDataSize
= 0;
1081 DirectoryEntry
= &TeHdr
->DataDirectory
[0];
1082 ImageContext
->FixupDataSize
= DirectoryEntry
->Size
/ sizeof (UINT16
) * sizeof (UINTN
);
1085 // Consumer must allocate a buffer for the relocation fixup log.
1086 // Only used for runtime drivers.
1088 ImageContext
->FixupData
= NULL
;
1091 // Load the Codeview info if present
1093 if (ImageContext
->DebugDirectoryEntryRva
!= 0) {
1094 if (!(ImageContext
->IsTeImage
)) {
1095 DebugEntry
= PeCoffLoaderImageAddress (
1097 ImageContext
->DebugDirectoryEntryRva
1100 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)(UINTN
)(
1101 ImageContext
->ImageAddress
+
1102 ImageContext
->DebugDirectoryEntryRva
+
1103 sizeof(EFI_TE_IMAGE_HEADER
) -
1108 if (DebugEntry
!= NULL
) {
1109 TempDebugEntryRva
= DebugEntry
->RVA
;
1110 if (DebugEntry
->RVA
== 0 && DebugEntry
->FileOffset
!= 0) {
1112 if ((UINTN
) Section
->SizeOfRawData
< Section
->Misc
.VirtualSize
) {
1113 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->Misc
.VirtualSize
;
1115 TempDebugEntryRva
= Section
->VirtualAddress
+ Section
->SizeOfRawData
;
1119 if (TempDebugEntryRva
!= 0) {
1120 if (!(ImageContext
->IsTeImage
)) {
1121 ImageContext
->CodeView
= PeCoffLoaderImageAddress (ImageContext
, TempDebugEntryRva
);
1123 ImageContext
->CodeView
= (VOID
*)(
1124 (UINTN
)ImageContext
->ImageAddress
+
1125 (UINTN
)TempDebugEntryRva
+
1126 (UINTN
)sizeof(EFI_TE_IMAGE_HEADER
) -
1127 (UINTN
) TeHdr
->StrippedSize
1131 if (ImageContext
->CodeView
== NULL
) {
1132 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1133 return RETURN_LOAD_ERROR
;
1136 if (DebugEntry
->RVA
== 0) {
1137 Size
= DebugEntry
->SizeOfData
;
1138 if (!(ImageContext
->IsTeImage
)) {
1139 Status
= ImageContext
->ImageRead (
1140 ImageContext
->Handle
,
1141 DebugEntry
->FileOffset
,
1143 ImageContext
->CodeView
1146 Status
= ImageContext
->ImageRead (
1147 ImageContext
->Handle
,
1148 DebugEntry
->FileOffset
+ sizeof (EFI_TE_IMAGE_HEADER
) - TeHdr
->StrippedSize
,
1150 ImageContext
->CodeView
1153 // Should we apply fix up to this field according to the size difference between PE and TE?
1154 // Because now we maintain TE header fields unfixed, this field will also remain as they are
1155 // in original PE image.
1159 if (RETURN_ERROR (Status
)) {
1160 ImageContext
->ImageError
= IMAGE_ERROR_IMAGE_READ
;
1161 return RETURN_LOAD_ERROR
;
1164 DebugEntry
->RVA
= TempDebugEntryRva
;
1167 switch (*(UINT32
*) ImageContext
->CodeView
) {
1168 case CODEVIEW_SIGNATURE_NB10
:
1169 ImageContext
->PdbPointer
= (CHAR8
*) ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
);
1172 case CODEVIEW_SIGNATURE_RSDS
:
1173 ImageContext
->PdbPointer
= (CHAR8
*) ImageContext
->CodeView
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
);
1187 Returns a pointer to the PDB file name for a raw PE/COFF image that is not
1188 loaded into system memory with the PE/COFF Loader Library functions.
1190 Returns the PDB file name for the PE/COFF image specified by Pe32Data. If
1191 the PE/COFF image specified by Pe32Data is not a valid, then NULL is
1192 returned. If the PE/COFF image specified by Pe32Data does not contain a
1193 debug directory entry, then NULL is returned. If the debug directory entry
1194 in the PE/COFF image specified by Pe32Data does not contain a PDB file name,
1195 then NULL is returned.
1196 If Pe32Data is NULL, then return NULL.
1198 @param Pe32Data Pointer to the PE/COFF image that is loaded in system
1201 @return The PDB file name for the PE/COFF image specified by Pe32Data or NULL
1202 if it cannot be retrieved.
1207 PeCoffLoaderGetPdbPointer (
1211 EFI_IMAGE_DOS_HEADER
*DosHdr
;
1212 EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION Hdr
;
1213 EFI_IMAGE_DATA_DIRECTORY
*DirectoryEntry
;
1214 EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*DebugEntry
;
1216 VOID
*CodeViewEntryPointer
;
1218 UINT32 NumberOfRvaAndSizes
;
1220 EFI_IMAGE_SECTION_HEADER
*SectionHeader
;
1221 UINT32 Index
, Index1
;
1223 if (Pe32Data
== NULL
) {
1228 DirectoryEntry
= NULL
;
1230 NumberOfRvaAndSizes
= 0;
1233 SectionHeader
= NULL
;
1235 DosHdr
= (EFI_IMAGE_DOS_HEADER
*)Pe32Data
;
1236 if (EFI_IMAGE_DOS_SIGNATURE
== DosHdr
->e_magic
) {
1238 // DOS image header is present, so read the PE header after the DOS image header.
1240 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)((UINTN
) Pe32Data
+ (UINTN
) ((DosHdr
->e_lfanew
) & 0x0ffff));
1243 // DOS image header is not present, so PE header is at the image base.
1245 Hdr
.Pe32
= (EFI_IMAGE_NT_HEADERS32
*)Pe32Data
;
1248 if (EFI_TE_IMAGE_HEADER_SIGNATURE
== Hdr
.Te
->Signature
) {
1249 if (Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
].VirtualAddress
!= 0) {
1250 DirectoryEntry
= &Hdr
.Te
->DataDirectory
[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG
];
1251 TEImageAdjust
= sizeof (EFI_TE_IMAGE_HEADER
) - Hdr
.Te
->StrippedSize
;
1254 // Get the DebugEntry offset in the raw data image.
1256 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (Hdr
.Te
+ 1);
1257 Index
= Hdr
.Te
->NumberOfSections
;
1258 for (Index1
= 0; Index1
< Index
; Index1
++) {
1259 if ((DirectoryEntry
->VirtualAddress
>= SectionHeader
[Index1
].VirtualAddress
) &&
1260 (DirectoryEntry
->VirtualAddress
< (SectionHeader
[Index1
].VirtualAddress
+ SectionHeader
[Index1
].Misc
.VirtualSize
))) {
1261 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*)((UINTN
) Hdr
.Te
+
1262 DirectoryEntry
->VirtualAddress
-
1263 SectionHeader
[Index1
].VirtualAddress
+
1264 SectionHeader
[Index1
].PointerToRawData
+
1270 } else if (EFI_IMAGE_NT_SIGNATURE
== Hdr
.Pe32
->Signature
) {
1272 // NOTE: We use Machine field to identify PE32/PE32+, instead of Magic.
1273 // It is due to backward-compatibility, for some system might
1274 // generate PE32+ image with PE32 Magic.
1276 switch (Hdr
.Pe32
->FileHeader
.Machine
) {
1277 case EFI_IMAGE_MACHINE_IA32
:
1278 case EFI_IMAGE_MACHINE_ARMT
:
1280 // Assume PE32 image with IA32 Machine field.
1282 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
;
1284 case EFI_IMAGE_MACHINE_X64
:
1285 case EFI_IMAGE_MACHINE_IPF
:
1287 // Assume PE32+ image with X64 or IPF Machine field
1289 Magic
= EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
;
1293 // For unknow Machine field, use Magic in optional Header
1295 Magic
= Hdr
.Pe32
->OptionalHeader
.Magic
;
1298 SectionHeader
= (EFI_IMAGE_SECTION_HEADER
*) (
1299 (UINT8
*) Hdr
.Pe32
+
1301 sizeof (EFI_IMAGE_FILE_HEADER
) +
1302 Hdr
.Pe32
->FileHeader
.SizeOfOptionalHeader
1304 Index
= Hdr
.Pe32
->FileHeader
.NumberOfSections
;
1306 if (EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC
== Magic
) {
1308 // Use PE32 offset get Debug Directory Entry
1310 NumberOfRvaAndSizes
= Hdr
.Pe32
->OptionalHeader
.NumberOfRvaAndSizes
;
1311 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
1312 } else if (Hdr
.Pe32
->OptionalHeader
.Magic
== EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC
) {
1314 // Use PE32+ offset get Debug Directory Entry
1316 NumberOfRvaAndSizes
= Hdr
.Pe32Plus
->OptionalHeader
.NumberOfRvaAndSizes
;
1317 DirectoryEntry
= (EFI_IMAGE_DATA_DIRECTORY
*)&(Hdr
.Pe32Plus
->OptionalHeader
.DataDirectory
[EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
]);
1320 if (NumberOfRvaAndSizes
<= EFI_IMAGE_DIRECTORY_ENTRY_DEBUG
|| DirectoryEntry
->VirtualAddress
== 0) {
1321 DirectoryEntry
= NULL
;
1325 // Get the DebugEntry offset in the raw data image.
1327 for (Index1
= 0; Index1
< Index
; Index1
++) {
1328 if ((DirectoryEntry
->VirtualAddress
>= SectionHeader
[Index1
].VirtualAddress
) &&
1329 (DirectoryEntry
->VirtualAddress
< (SectionHeader
[Index1
].VirtualAddress
+ SectionHeader
[Index1
].Misc
.VirtualSize
))) {
1330 DebugEntry
= (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
*) (
1332 DirectoryEntry
->VirtualAddress
-
1333 SectionHeader
[Index1
].VirtualAddress
+
1334 SectionHeader
[Index1
].PointerToRawData
);
1343 if (NULL
== DebugEntry
|| NULL
== DirectoryEntry
) {
1348 // Scan the directory to find the debug entry.
1350 for (DirCount
= 0; DirCount
< DirectoryEntry
->Size
; DirCount
+= sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY
), DebugEntry
++) {
1351 if (EFI_IMAGE_DEBUG_TYPE_CODEVIEW
== DebugEntry
->Type
) {
1352 if (DebugEntry
->SizeOfData
> 0) {
1354 // Get the DebugEntry offset in the raw data image.
1356 CodeViewEntryPointer
= NULL
;
1357 for (Index1
= 0; Index1
< Index
; Index1
++) {
1358 if ((DebugEntry
->RVA
>= SectionHeader
[Index1
].VirtualAddress
) &&
1359 (DebugEntry
->RVA
< (SectionHeader
[Index1
].VirtualAddress
+ SectionHeader
[Index1
].Misc
.VirtualSize
))) {
1360 CodeViewEntryPointer
= (VOID
*) (
1362 (UINTN
) DebugEntry
->RVA
-
1363 SectionHeader
[Index1
].VirtualAddress
+
1364 SectionHeader
[Index1
].PointerToRawData
+
1365 (UINTN
)TEImageAdjust
);
1369 if (Index1
>= Index
) {
1371 // Can't find CodeViewEntryPointer in raw PE/COFF image.
1375 switch (* (UINT32
*) CodeViewEntryPointer
) {
1376 case CODEVIEW_SIGNATURE_NB10
:
1377 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_NB10_ENTRY
));
1378 case CODEVIEW_SIGNATURE_RSDS
:
1379 return (VOID
*) ((CHAR8
*)CodeViewEntryPointer
+ sizeof (EFI_IMAGE_DEBUG_CODEVIEW_RSDS_ENTRY
));