X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=BaseTools%2FSource%2FC%2FCommon%2FBasePeCoff.c;h=1d89a300de18786c41de1ac228ac0cf2da72ae4c;hb=0a563f3fecfd9baffe8dce51bb4411d6a748a936;hp=878c1c611b8d11b00cc0d6d7fbc5c28a397c0dd4;hpb=40d841f6a8f84e75409178e19e69b95e01bada0f;p=mirror_edk2.git
diff --git a/BaseTools/Source/C/Common/BasePeCoff.c b/BaseTools/Source/C/Common/BasePeCoff.c
index 878c1c611b..1d89a300de 100644
--- a/BaseTools/Source/C/Common/BasePeCoff.c
+++ b/BaseTools/Source/C/Common/BasePeCoff.c
@@ -2,14 +2,15 @@
Functions to get info and load PE/COFF image.
-Copyright (c) 2004 - 2008, Intel Corporation. All rights reserved.
-This program and the accompanying materials
-are licensed and made available under the terms and conditions of the BSD License
-which accompanies this distribution. The full text of the license may be found at
-http://opensource.org/licenses/bsd-license.php
-
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+Copyright (c) 2004 - 2018, Intel Corporation. All rights reserved.
+Portions Copyright (c) 2011 - 2013, ARM Ltd. All rights reserved.
+This program and the accompanying materials
+are licensed and made available under the terms and conditions of the BSD License
+which accompanies this distribution. The full text of the license may be found at
+http://opensource.org/licenses/bsd-license.php
+
+THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
@@ -19,7 +20,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
#include "PeCoffLib.h"
typedef union {
- VOID *Header;
+ VOID *Header;
EFI_IMAGE_OPTIONAL_HEADER32 *Optional32;
EFI_IMAGE_OPTIONAL_HEADER64 *Optional64;
} EFI_IMAGE_OPTIONAL_HEADER_POINTER;
@@ -55,14 +56,6 @@ PeCoffLoaderRelocateIa32Image (
IN UINT64 Adjust
);
-RETURN_STATUS
-PeCoffLoaderRelocateX64Image (
- IN UINT16 *Reloc,
- IN OUT CHAR8 *Fixup,
- IN OUT CHAR8 **FixupData,
- IN UINT64 Adjust
- );
-
RETURN_STATUS
PeCoffLoaderRelocateIpfImage (
IN UINT16 *Reloc,
@@ -97,12 +90,12 @@ Arguments:
ImageContext - The context of the image being loaded
PeHdr - The buffer in which to return the PE header
-
+
TeHdr - The buffer in which to return the TE header
Returns:
- RETURN_SUCCESS if the PE or TE Header is read,
+ RETURN_SUCCESS if the PE or TE Header is read,
Otherwise, the error status from reading the PE/COFF or TE image using the ImageRead function.
--*/
@@ -142,7 +135,7 @@ Returns:
//
// Check the PE/COFF Header Signature. If not, then try to get a TE header
//
- *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr;
+ *TeHdr = (EFI_TE_IMAGE_HEADER *)*PeHdr;
if ((*TeHdr)->Signature != EFI_TE_IMAGE_HEADER_SIGNATURE) {
return RETURN_UNSUPPORTED;
}
@@ -170,7 +163,7 @@ Arguments:
ImageContext - The context of the image being loaded
PeHdr - The buffer in which to return the PE header
-
+
TeHdr - The buffer in which to return the TE header
Returns:
@@ -181,7 +174,7 @@ Returns:
--*/
{
//
- // See if the machine type is supported.
+ // See if the machine type is supported.
// We support a native machine type (IA-32/Itanium-based)
//
if (ImageContext->IsTeImage == FALSE) {
@@ -189,15 +182,16 @@ Returns:
} else {
ImageContext->Machine = TeHdr->Machine;
}
-
+
if (ImageContext->Machine != EFI_IMAGE_MACHINE_IA32 && \
ImageContext->Machine != EFI_IMAGE_MACHINE_IA64 && \
ImageContext->Machine != EFI_IMAGE_MACHINE_X64 && \
ImageContext->Machine != EFI_IMAGE_MACHINE_ARMT && \
- ImageContext->Machine != EFI_IMAGE_MACHINE_EBC) {
+ ImageContext->Machine != EFI_IMAGE_MACHINE_EBC && \
+ ImageContext->Machine != EFI_IMAGE_MACHINE_AARCH64) {
if (ImageContext->Machine == IMAGE_FILE_MACHINE_ARM) {
//
- // There are two types of ARM images. Pure ARM and ARM/Thumb.
+ // There are two types of ARM images. Pure ARM and ARM/Thumb.
// If we see the ARM say it is the ARM/Thumb so there is only
// a single machine type we need to check for ARM.
//
@@ -210,8 +204,8 @@ Returns:
} else {
//
- // unsupported PeImage machine type
- //
+ // unsupported PeImage machine type
+ //
return RETURN_UNSUPPORTED;
}
}
@@ -231,8 +225,8 @@ Returns:
ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER && \
ImageContext->ImageType != EFI_IMAGE_SUBSYSTEM_SAL_RUNTIME_DRIVER) {
//
- // upsupported PeImage subsystem type
- //
+ // upsupported PeImage subsystem type
+ //
return RETURN_UNSUPPORTED;
}
@@ -342,7 +336,7 @@ Returns:
//
if ((!(ImageContext->IsTeImage)) && ((PeHdr->Pe32.FileHeader.Characteristics & EFI_IMAGE_FILE_RELOCS_STRIPPED) != 0)) {
ImageContext->RelocationsStripped = TRUE;
- } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0)) {
+ } else if ((ImageContext->IsTeImage) && (TeHdr->DataDirectory[0].Size == 0) && (TeHdr->DataDirectory[0].VirtualAddress == 0)) {
ImageContext->RelocationsStripped = TRUE;
} else {
ImageContext->RelocationsStripped = FALSE;
@@ -354,7 +348,7 @@ Returns:
ImageContext->ImageSize = (UINT64) OptionHeader.Optional32->SizeOfImage;
ImageContext->SectionAlignment = OptionHeader.Optional32->SectionAlignment;
ImageContext->SizeOfHeaders = OptionHeader.Optional32->SizeOfHeaders;
-
+
//
// Modify ImageSize to contain .PDB file name if required and initialize
// PdbRVA field...
@@ -367,7 +361,7 @@ Returns:
ImageContext->ImageSize = (UINT64) OptionHeader.Optional64->SizeOfImage;
ImageContext->SectionAlignment = OptionHeader.Optional64->SectionAlignment;
ImageContext->SizeOfHeaders = OptionHeader.Optional64->SizeOfHeaders;
-
+
//
// Modify ImageSize to contain .PDB file name if required and initialize
// PdbRVA field...
@@ -377,7 +371,7 @@ Returns:
DebugDirectoryEntryRva = DebugDirectoryEntry->VirtualAddress;
}
}
-
+
if (DebugDirectoryEntryRva != 0) {
//
// Determine the file offset of the debug directory... This means we walk
@@ -388,8 +382,8 @@ Returns:
SectionHeaderOffset = (UINTN)(
ImageContext->PeCoffHeaderOffset +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
PeHdr->Pe32.FileHeader.SizeOfOptionalHeader
);
@@ -419,12 +413,12 @@ Returns:
SectionHeaderOffset += sizeof (EFI_IMAGE_SECTION_HEADER);
}
- if (DebugDirectoryEntryFileOffset != 0) {
+ if (DebugDirectoryEntryFileOffset != 0) {
for (Index = 0; Index < DebugDirectoryEntry->Size; Index += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY)) {
//
// Read next debug directory entry
//
- Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
+ Size = sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY);
Status = ImageContext->ImageRead (
ImageContext->Handle,
DebugDirectoryEntryFileOffset + Index,
@@ -495,8 +489,8 @@ Returns:
//
// In Te image header there is not a field to describe the ImageSize.
- // Actually, the ImageSize equals the RVA plus the VirtualSize of
- // the last section mapped into memory (Must be rounded up to
+ // Actually, the ImageSize equals the RVA plus the VirtualSize of
+ // the last section mapped into memory (Must be rounded up to
// a mulitple of Section Alignment). Per the PE/COFF specification, the
// section headers in the Section Table must appear in order of the RVA
// values for the corresponding sections. So the ImageSize can be determined
@@ -609,6 +603,7 @@ Returns:
CHAR8 *FixupBase;
UINT16 *F16;
UINT32 *F32;
+ UINT64 *F64;
CHAR8 *FixupData;
PHYSICAL_ADDRESS BaseAddress;
UINT16 MachineType;
@@ -629,17 +624,12 @@ Returns:
}
//
- // If the destination address is not 0, use that rather than the
- // image address as the relocation target.
+ // Use DestinationAddress field of ImageContext as the relocation address even if it is 0.
//
- if (ImageContext->DestinationAddress) {
- BaseAddress = ImageContext->DestinationAddress;
- } else {
- BaseAddress = ImageContext->ImageAddress;
- }
+ BaseAddress = ImageContext->DestinationAddress;
if (!(ImageContext->IsTeImage)) {
- PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress +
+ PeHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)((UINTN)ImageContext->ImageAddress +
ImageContext->PeCoffHeaderOffset);
OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);
if (PeHdr->Pe32.OptionalHeader.Magic == EFI_IMAGE_NT_OPTIONAL_HDR32_MAGIC) {
@@ -655,11 +645,22 @@ Returns:
//
if (OptionHeader.Optional32->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
RelocDir = &OptionHeader.Optional32->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
- RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
- RelocBaseEnd = PeCoffLoaderImageAddress (
- ImageContext,
- RelocDir->VirtualAddress + RelocDir->Size - 1
- );
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
} else {
//
// Set base and end to bypass processing below.
@@ -679,11 +680,22 @@ Returns:
//
if (OptionHeader.Optional64->NumberOfRvaAndSizes > EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC) {
RelocDir = &OptionHeader.Optional64->DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC];
- RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
- RelocBaseEnd = PeCoffLoaderImageAddress (
- ImageContext,
- RelocDir->VirtualAddress + RelocDir->Size - 1
- );
+ if ((RelocDir != NULL) && (RelocDir->Size > 0)) {
+ RelocBase = PeCoffLoaderImageAddress (ImageContext, RelocDir->VirtualAddress);
+ RelocBaseEnd = PeCoffLoaderImageAddress (
+ ImageContext,
+ RelocDir->VirtualAddress + RelocDir->Size - 1
+ );
+ if (RelocBase == NULL || RelocBaseEnd == NULL || RelocBaseEnd < RelocBase) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
+ } else {
+ //
+ // Set base and end to bypass processing below.
+ //
+ RelocBase = RelocBaseEnd = 0;
+ }
} else {
//
// Set base and end to bypass processing below.
@@ -696,20 +708,20 @@ Returns:
Adjust = (UINT64) (BaseAddress - TeHdr->ImageBase);
TeHdr->ImageBase = (UINT64) (BaseAddress);
MachineType = TeHdr->Machine;
-
+
//
// Find the relocation block
//
RelocDir = &TeHdr->DataDirectory[0];
RelocBase = (EFI_IMAGE_BASE_RELOCATION *)(UINTN)(
- ImageContext->ImageAddress +
+ ImageContext->ImageAddress +
RelocDir->VirtualAddress +
- sizeof(EFI_TE_IMAGE_HEADER) -
+ sizeof(EFI_TE_IMAGE_HEADER) -
TeHdr->StrippedSize
);
RelocBaseEnd = (EFI_IMAGE_BASE_RELOCATION *) ((UINTN) RelocBase + (UINTN) RelocDir->Size - 1);
}
-
+
//
// Run the relocation information and apply the fixups
//
@@ -720,16 +732,20 @@ Returns:
RelocEnd = (UINT16 *) ((CHAR8 *) RelocBase + RelocBase->SizeOfBlock);
if (!(ImageContext->IsTeImage)) {
FixupBase = PeCoffLoaderImageAddress (ImageContext, RelocBase->VirtualAddress);
+ if (FixupBase == NULL) {
+ ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
+ return RETURN_LOAD_ERROR;
+ }
} else {
FixupBase = (CHAR8 *)(UINTN)(ImageContext->ImageAddress +
RelocBase->VirtualAddress +
- sizeof(EFI_TE_IMAGE_HEADER) -
+ sizeof(EFI_TE_IMAGE_HEADER) -
TeHdr->StrippedSize
);
}
if ((CHAR8 *) RelocEnd < (CHAR8 *) ((UINTN) ImageContext->ImageAddress) ||
- (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +
+ (CHAR8 *) RelocEnd > (CHAR8 *)((UINTN)ImageContext->ImageAddress +
(UINTN)ImageContext->ImageSize)) {
ImageContext->ImageError = IMAGE_ERROR_FAILED_RELOCATION;
return RETURN_LOAD_ERROR;
@@ -773,6 +789,16 @@ Returns:
}
break;
+ case EFI_IMAGE_REL_BASED_DIR64:
+ F64 = (UINT64 *) Fixup;
+ *F64 = *F64 + (UINT64) Adjust;
+ if (FixupData != NULL) {
+ FixupData = ALIGN_POINTER (FixupData, sizeof (UINT64));
+ *(UINT64 *) FixupData = *F64;
+ FixupData = FixupData + sizeof (UINT64);
+ }
+ break;
+
case EFI_IMAGE_REL_BASED_HIGHADJ:
//
// Return the same EFI_UNSUPPORTED return code as
@@ -790,9 +816,6 @@ Returns:
case EFI_IMAGE_MACHINE_ARMT:
Status = PeCoffLoaderRelocateArmImage (&Reloc, Fixup, &FixupData, Adjust);
break;
- case EFI_IMAGE_MACHINE_X64:
- Status = PeCoffLoaderRelocateX64Image (Reloc, Fixup, &FixupData, Adjust);
- break;
case EFI_IMAGE_MACHINE_IA64:
Status = PeCoffLoaderRelocateIpfImage (Reloc, Fixup, &FixupData, Adjust);
break;
@@ -938,12 +961,12 @@ Returns:
((UINTN)ImageContext->ImageAddress + ImageContext->PeCoffHeaderOffset);
OptionHeader.Header = (VOID *) &(PeHdr->Pe32.OptionalHeader);
-
+
FirstSection = (EFI_IMAGE_SECTION_HEADER *) (
(UINTN)ImageContext->ImageAddress +
ImageContext->PeCoffHeaderOffset +
- sizeof(UINT32) +
- sizeof(EFI_IMAGE_FILE_HEADER) +
+ sizeof(UINT32) +
+ sizeof(EFI_IMAGE_FILE_HEADER) +
PeHdr->Pe32.FileHeader.SizeOfOptionalHeader
);
NumberOfSections = (UINTN) (PeHdr->Pe32.FileHeader.NumberOfSections);
@@ -984,14 +1007,7 @@ Returns:
ImageContext,
Section->VirtualAddress + Section->Misc.VirtualSize - 1
);
- if (ImageContext->IsTeImage) {
- Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
- End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
- }
- if (End > MaxEnd) {
- MaxEnd = End;
- }
//
// If the base start or end address resolved to 0, then fail.
//
@@ -1000,6 +1016,16 @@ Returns:
return RETURN_LOAD_ERROR;
}
+
+ if (ImageContext->IsTeImage) {
+ Base = (CHAR8 *) ((UINTN) Base + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
+ End = (CHAR8 *) ((UINTN) End + sizeof (EFI_TE_IMAGE_HEADER) - (UINTN) TeHdr->StrippedSize);
+ }
+
+ if (End > MaxEnd) {
+ MaxEnd = End;
+ }
+
//
// Read the section
//
@@ -1054,12 +1080,10 @@ Returns:
PeHdr->Pe32.OptionalHeader.AddressOfEntryPoint
);
} else {
- ImageContext->EntryPoint = (PHYSICAL_ADDRESS) (
- (UINTN)ImageContext->ImageAddress +
- (UINTN)TeHdr->AddressOfEntryPoint +
- (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
- (UINTN) TeHdr->StrippedSize
- );
+ ImageContext->EntryPoint = (UINTN)ImageContext->ImageAddress +
+ (UINTN)TeHdr->AddressOfEntryPoint +
+ (UINTN)sizeof(EFI_TE_IMAGE_HEADER) -
+ (UINTN) TeHdr->StrippedSize;
}
//
@@ -1262,19 +1286,19 @@ PeCoffLoaderGetPdbPointer (
if (Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG].VirtualAddress != 0) {
DirectoryEntry = &Hdr.Te->DataDirectory[EFI_TE_IMAGE_DIRECTORY_ENTRY_DEBUG];
TEImageAdjust = sizeof (EFI_TE_IMAGE_HEADER) - Hdr.Te->StrippedSize;
-
+
//
// Get the DebugEntry offset in the raw data image.
//
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (Hdr.Te + 1);
Index = Hdr.Te->NumberOfSections;
for (Index1 = 0; Index1 < Index; Index1 ++) {
- if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&
+ if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&
(DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *)((UINTN) Hdr.Te +
- DirectoryEntry->VirtualAddress -
- SectionHeader [Index1].VirtualAddress +
- SectionHeader [Index1].PointerToRawData +
+ DirectoryEntry->VirtualAddress -
+ SectionHeader [Index1].VirtualAddress +
+ SectionHeader [Index1].PointerToRawData +
TEImageAdjust);
break;
}
@@ -1310,8 +1334,8 @@ PeCoffLoaderGetPdbPointer (
SectionHeader = (EFI_IMAGE_SECTION_HEADER *) (
(UINT8 *) Hdr.Pe32 +
- sizeof (UINT32) +
- sizeof (EFI_IMAGE_FILE_HEADER) +
+ sizeof (UINT32) +
+ sizeof (EFI_IMAGE_FILE_HEADER) +
Hdr.Pe32->FileHeader.SizeOfOptionalHeader
);
Index = Hdr.Pe32->FileHeader.NumberOfSections;
@@ -1338,12 +1362,12 @@ PeCoffLoaderGetPdbPointer (
// Get the DebugEntry offset in the raw data image.
//
for (Index1 = 0; Index1 < Index; Index1 ++) {
- if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&
+ if ((DirectoryEntry->VirtualAddress >= SectionHeader[Index1].VirtualAddress) &&
(DirectoryEntry->VirtualAddress < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {
DebugEntry = (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY *) (
- (UINTN) Pe32Data +
- DirectoryEntry->VirtualAddress -
- SectionHeader[Index1].VirtualAddress +
+ (UINTN) Pe32Data +
+ DirectoryEntry->VirtualAddress -
+ SectionHeader[Index1].VirtualAddress +
SectionHeader[Index1].PointerToRawData);
break;
}
@@ -1359,7 +1383,7 @@ PeCoffLoaderGetPdbPointer (
//
// Scan the directory to find the debug entry.
- //
+ //
for (DirCount = 0; DirCount < DirectoryEntry->Size; DirCount += sizeof (EFI_IMAGE_DEBUG_DIRECTORY_ENTRY), DebugEntry++) {
if (EFI_IMAGE_DEBUG_TYPE_CODEVIEW == DebugEntry->Type) {
if (DebugEntry->SizeOfData > 0) {
@@ -1368,13 +1392,13 @@ PeCoffLoaderGetPdbPointer (
//
CodeViewEntryPointer = NULL;
for (Index1 = 0; Index1 < Index; Index1 ++) {
- if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) &&
+ if ((DebugEntry->RVA >= SectionHeader[Index1].VirtualAddress) &&
(DebugEntry->RVA < (SectionHeader[Index1].VirtualAddress + SectionHeader[Index1].Misc.VirtualSize))) {
CodeViewEntryPointer = (VOID *) (
- ((UINTN)Pe32Data) +
- (UINTN) DebugEntry->RVA -
- SectionHeader[Index1].VirtualAddress +
- SectionHeader[Index1].PointerToRawData +
+ ((UINTN)Pe32Data) +
+ (UINTN) DebugEntry->RVA -
+ SectionHeader[Index1].VirtualAddress +
+ SectionHeader[Index1].PointerToRawData +
(UINTN)TEImageAdjust);
break;
}