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; }