\r
Functions to get info and load PE/COFF image.\r
\r
-Copyright (c) 2004 - 2010, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.<BR>\r
Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.<BR>\r
-This program and the accompanying materials \r
-are licensed and made available under the terms and conditions of the BSD License \r
-which accompanies this distribution. The full text of the license may be found at \r
-http://opensource.org/licenses/bsd-license.php \r
- \r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "PeCoffLib.h"\r
\r
typedef union {\r
- VOID *Header; \r
+ VOID *Header;\r
EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;\r
EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;\r
} EFI_IMAGE_OPTIONAL_HEADER_POINTER;\r
IN UINT64 Adjust\r
);\r
\r
-RETURN_STATUS\r
-PeCoffLoaderRelocateIpfImage (\r
- IN UINT16 *Reloc,\r
- IN OUT CHAR8 *Fixup,\r
- IN OUT CHAR8 **FixupData,\r
- IN UINT64 Adjust\r
- );\r
\r
RETURN_STATUS\r
PeCoffLoaderRelocateArmImage (\r
ImageContext - The context of the image being loaded\r
\r
PeHdr - The buffer in which to return the PE header\r
- \r
+\r
TeHdr - The buffer in which to return the TE header\r
\r
Returns:\r
\r
- RETURN_SUCCESS if the PE or TE Header is read, \r
+ RETURN_SUCCESS if the PE or TE Header is read,\r
Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.\r
\r
--*/\r
//\r
// Check the PE/COFF Header Signature. If not, then try to get a TE header\r
//\r
- *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr; \r
+ *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr;\r
if ((*TeHdr)->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {\r
return RETURN_UNSUPPORTED;\r
}\r
ImageContext - The context of the image being loaded\r
\r
PeHdr - The buffer in which to return the PE header\r
- \r
+\r
TeHdr - The buffer in which to return the TE header\r
\r
Returns:\r
--*/\r
{\r
//\r
- // See if the machine type is supported. \r
+ // See if the machine type is supported.\r
// We support a native machine type (IA-32/Itanium-based)\r
//\r
if (ImageContext->IsTeImage == FALSE) {\r
} else {\r
ImageContext->Machine = TeHdr->Machine;\r
}\r
- \r
+\r
if (ImageContext->Machine != EFI_IMAGE_MACHINE_IA32 && \\r
- ImageContext->Machine != EFI_IMAGE_MACHINE_IA64 && \\r
ImageContext->Machine != EFI_IMAGE_MACHINE_X64 && \\r
ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \\r
ImageContext->Machine != EFI_IMAGE_MACHINE_EBC && \\r
ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64) {\r
if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) {\r
//\r
- // There are two types of ARM images. Pure ARM and ARM/Thumb. \r
+ // There are two types of ARM images. Pure ARM and ARM/Thumb.\r
// If we see the ARM say it is the ARM/Thumb so there is only\r
// a single machine type we need to check for ARM.\r
//\r
\r
} else {\r
//\r
- // unsupported PeImage machine type \r
- // \r
+ // unsupported PeImage machine type\r
+ //\r
return RETURN_UNSUPPORTED;\r
}\r
}\r
ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && \\r
ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) {\r
//\r
- // upsupported PeImage subsystem type \r
- // \r
+ // unsupported PeImage subsystem type\r
+ //\r
return RETURN_UNSUPPORTED;\r
}\r
\r
//\r
if ((!(ImageContext->IsTeImage)) && ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {\r
ImageContext->RelocationsStripped = TRUE;\r
- } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0)) {\r
+ } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0) && (TeHdr->DataDirectory[0].VirtualAddress == 0)) {\r
ImageContext->RelocationsStripped = TRUE;\r
} else {\r
ImageContext->RelocationsStripped = FALSE;\r
ImageContext->ImageSize = (UINT64) OptionHeader.Optional32->SizeOfImage;\r
ImageContext->SectionAlignment = OptionHeader.Optional32->SectionAlignment;\r
ImageContext->SizeOfHeaders = OptionHeader.Optional32->SizeOfHeaders;\r
- \r
+\r
//\r
// Modify ImageSize to contain .PDB file name if required and initialize\r
// PdbRVA field...\r
ImageContext->ImageSize = (UINT64) OptionHeader.Optional64->SizeOfImage;\r
ImageContext->SectionAlignment = OptionHeader.Optional64->SectionAlignment;\r
ImageContext->SizeOfHeaders = OptionHeader.Optional64->SizeOfHeaders;\r
- \r
+\r
//\r
// Modify ImageSize to contain .PDB file name if required and initialize\r
// PdbRVA field...\r
DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;\r
}\r
}\r
- \r
+\r
if (DebugDirectoryEntryRva != 0) {\r
//\r
// Determine the file offset of the debug directory... This means we walk\r
\r
SectionHeaderOffset = (UINTN)(\r
ImageContext->PeCoffHeaderOffset +\r
- sizeof (UINT32) + \r
- sizeof (EFI_IMAGE_FILE_HEADER) + \r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
PeHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
);\r
\r
SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);\r
}\r
\r
- if (DebugDirectoryEntryFileOffset != 0) { \r
+ if (DebugDirectoryEntryFileOffset != 0) {\r
for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {\r
//\r
// Read next debug directory entry\r
//\r
- Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY); \r
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);\r
Status = ImageContext->ImageRead (\r
ImageContext->Handle,\r
DebugDirectoryEntryFileOffset + Index,\r
\r
//\r
// In Te image header there is not a field to describe the ImageSize.\r
- // Actually, the ImageSize equals the RVA plus the VirtualSize of \r
- // the last section mapped into memory (Must be rounded up to \r
- // a mulitple of Section Alignment). Per the PE/COFF specification, the\r
+ // Actually, the ImageSize equals the RVA plus the VirtualSize of\r
+ // the last section mapped into memory (Must be rounded up to\r
+ // a multiple of Section Alignment). Per the PE/COFF specification, the\r
// section headers in the Section Table must appear in order of the RVA\r
// values for the corresponding sections. So the ImageSize can be determined\r
// by the RVA and the VirtualSize of the last section header in the\r
// Use DestinationAddress field of ImageContext as the relocation address even if it is 0.\r
//\r
BaseAddress = ImageContext->DestinationAddress;\r
- \r
+\r
if (!(ImageContext->IsTeImage)) {\r
- PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress + \r
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress +\r
ImageContext->PeCoffHeaderOffset);\r
OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);\r
if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {\r
//\r
if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
RelocDir = &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
- RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
- RelocBaseEnd = PeCoffLoaderImageAddress (\r
- ImageContext,\r
- RelocDir->VirtualAddress + RelocDir->Size - 1\r
- );\r
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {\r
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
+ RelocBaseEnd = PeCoffLoaderImageAddress (\r
+ ImageContext,\r
+ RelocDir->VirtualAddress + RelocDir->Size - 1\r
+ );\r
+ if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {\r
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+ return RETURN_LOAD_ERROR;\r
+ }\r
+ } else {\r
+ //\r
+ // Set base and end to bypass processing below.\r
+ //\r
+ RelocBase = RelocBaseEnd = 0;\r
+ }\r
} else {\r
//\r
// Set base and end to bypass processing below.\r
//\r
if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {\r
RelocDir = &OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];\r
- RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
- RelocBaseEnd = PeCoffLoaderImageAddress (\r
- ImageContext,\r
- RelocDir->VirtualAddress + RelocDir->Size - 1\r
- );\r
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {\r
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);\r
+ RelocBaseEnd = PeCoffLoaderImageAddress (\r
+ ImageContext,\r
+ RelocDir->VirtualAddress + RelocDir->Size - 1\r
+ );\r
+ if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {\r
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+ return RETURN_LOAD_ERROR;\r
+ }\r
+ } else {\r
+ //\r
+ // Set base and end to bypass processing below.\r
+ //\r
+ RelocBase = RelocBaseEnd = 0;\r
+ }\r
} else {\r
//\r
// Set base and end to bypass processing below.\r
Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase);\r
TeHdr->ImageBase = (UINT64) (BaseAddress);\r
MachineType = TeHdr->Machine;\r
- \r
+\r
//\r
// Find the relocation block\r
//\r
RelocDir = &TeHdr->DataDirectory[0];\r
RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(\r
- ImageContext->ImageAddress + \r
+ ImageContext->ImageAddress +\r
RelocDir->VirtualAddress +\r
- sizeof(EFI_TE_IMAGE_HEADER) - \r
+ sizeof(EFI_TE_IMAGE_HEADER) -\r
TeHdr->StrippedSize\r
);\r
RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);\r
}\r
- \r
+\r
//\r
// Run the relocation information and apply the fixups\r
//\r
RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);\r
if (!(ImageContext->IsTeImage)) {\r
FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);\r
+ if (FixupBase == NULL) {\r
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
+ return RETURN_LOAD_ERROR;\r
+ }\r
} else {\r
FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +\r
RelocBase->VirtualAddress +\r
- sizeof(EFI_TE_IMAGE_HEADER) - \r
+ sizeof(EFI_TE_IMAGE_HEADER) -\r
TeHdr->StrippedSize\r
);\r
}\r
\r
if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||\r
- (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress + \r
+ (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +\r
(UINTN)ImageContext->ImageSize)) {\r
ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;\r
return RETURN_LOAD_ERROR;\r
case EFI_IMAGE_MACHINE_ARMT:\r
Status = PeCoffLoaderRelocateArmImage (&Reloc, Fixup, &FixupData, Adjust);\r
break;\r
- case EFI_IMAGE_MACHINE_IA64:\r
- Status = PeCoffLoaderRelocateIpfImage (Reloc, Fixup, &FixupData, Adjust);\r
- break;\r
default:\r
Status = RETURN_UNSUPPORTED;\r
break;\r
((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);\r
\r
OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);\r
- \r
+\r
FirstSection = (EFI_IMAGE_SECTION_HEADER *) (\r
(UINTN)ImageContext->ImageAddress +\r
ImageContext->PeCoffHeaderOffset +\r
- sizeof(UINT32) + \r
- sizeof(EFI_IMAGE_FILE_HEADER) + \r
+ sizeof(UINT32) +\r
+ sizeof(EFI_IMAGE_FILE_HEADER) +\r
PeHdr->Pe32.FileHeader.SizeOfOptionalHeader\r
);\r
NumberOfSections = (UINTN) (PeHdr->Pe32.FileHeader.NumberOfSections);\r
return RETURN_LOAD_ERROR;\r
}\r
\r
- \r
+\r
if (ImageContext->IsTeImage) {\r
Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);\r
PeHdr->Pe32.OptionalHeader.AddressOfEntryPoint\r
);\r
} else {\r
- ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (\r
- (UINTN)ImageContext->ImageAddress +\r
- (UINTN)TeHdr->AddressOfEntryPoint +\r
- (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
- (UINTN) TeHdr->StrippedSize\r
- );\r
+ ImageContext->EntryPoint = (UINTN)ImageContext->ImageAddress +\r
+ (UINTN)TeHdr->AddressOfEntryPoint +\r
+ (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -\r
+ (UINTN) TeHdr->StrippedSize;\r
}\r
\r
//\r
if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {\r
DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];\r
TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;\r
- \r
+\r
//\r
// Get the DebugEntry offset in the raw data image.\r
//\r
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (Hdr.Te + 1);\r
Index = Hdr.Te->NumberOfSections;\r
for (Index1 = 0; Index1 < Index; Index1 ++) {\r
- if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) && \r
+ if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&\r
(DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {\r
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +\r
- DirectoryEntry->VirtualAddress - \r
- SectionHeader [Index1].VirtualAddress + \r
- SectionHeader [Index1].PointerToRawData + \r
+ DirectoryEntry->VirtualAddress -\r
+ SectionHeader [Index1].VirtualAddress +\r
+ SectionHeader [Index1].PointerToRawData +\r
TEImageAdjust);\r
break;\r
}\r
Magic = EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC;\r
break;\r
case EFI_IMAGE_MACHINE_X64:\r
- case EFI_IMAGE_MACHINE_IPF:\r
//\r
- // Assume PE32+ image with X64 or IPF Machine field\r
+ // Assume PE32+ image with X64 Machine field\r
//\r
Magic = EFI_IMAGE_NT_OPTIONAL_HDR64_MAGIC;\r
break;\r
default:\r
//\r
- // For unknow Machine field, use Magic in optional Header\r
+ // For unknown Machine field, use Magic in optional Header\r
//\r
Magic = Hdr.Pe32->OptionalHeader.Magic;\r
}\r
\r
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (\r
(UINT8 *) Hdr.Pe32 +\r
- sizeof (UINT32) + \r
- sizeof (EFI_IMAGE_FILE_HEADER) + \r
+ sizeof (UINT32) +\r
+ sizeof (EFI_IMAGE_FILE_HEADER) +\r
Hdr.Pe32->FileHeader.SizeOfOptionalHeader\r
);\r
Index = Hdr.Pe32->FileHeader.NumberOfSections;\r
// Get the DebugEntry offset in the raw data image.\r
//\r
for (Index1 = 0; Index1 < Index; Index1 ++) {\r
- if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) && \r
+ if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&\r
(DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {\r
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (\r
- (UINTN) Pe32Data + \r
- DirectoryEntry->VirtualAddress - \r
- SectionHeader[Index1].VirtualAddress + \r
+ (UINTN) Pe32Data +\r
+ DirectoryEntry->VirtualAddress -\r
+ SectionHeader[Index1].VirtualAddress +\r
SectionHeader[Index1].PointerToRawData);\r
break;\r
}\r
\r
//\r
// Scan the directory to find the debug entry.\r
- // \r
+ //\r
for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {\r
if (EFI_IMAGE_DEBUG_TYPE_CODEVIEW == DebugEntry->Type) {\r
if (DebugEntry->SizeOfData > 0) {\r
//\r
CodeViewEntryPointer = NULL;\r
for (Index1 = 0; Index1 < Index; Index1 ++) {\r
- if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) && \r
+ if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) &&\r
(DebugEntry->RVA < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {\r
CodeViewEntryPointer = (VOID *) (\r
- ((UINTN)Pe32Data) + \r
- (UINTN) DebugEntry->RVA - \r
- SectionHeader[Index1].VirtualAddress + \r
- SectionHeader[Index1].PointerToRawData + \r
+ ((UINTN)Pe32Data) +\r
+ (UINTN) DebugEntry->RVA -\r
+ SectionHeader[Index1].VirtualAddress +\r
+ SectionHeader[Index1].PointerToRawData +\r
(UINTN)TEImageAdjust);\r
break;\r
}\r