--- BaseTools/Source/C/GenFw/Elf64Convert.c.orig 2018-10-31 01:50:38 UTC +++ BaseTools/Source/C/GenFw/Elf64Convert.c @@ -219,7 +219,7 @@ IsTextShdr ( Elf_Shdr *Shdr ) { - return (BOOLEAN) ((Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == SHF_ALLOC); + return (BOOLEAN) ((Shdr->sh_flags & (SHF_EXECINSTR | SHF_WRITE | SHF_ALLOC)) == (SHF_EXECINSTR | SHF_ALLOC)); } STATIC @@ -242,7 +242,7 @@ IsDataShdr ( if (IsHiiRsrcShdr(Shdr)) { return FALSE; } - return (BOOLEAN) (Shdr->sh_flags & (SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); + return (BOOLEAN) (Shdr->sh_flags & (SHF_EXECINSTR | SHF_WRITE | SHF_ALLOC)) == (SHF_ALLOC | SHF_WRITE); } // @@ -565,7 +565,7 @@ WriteSections64 ( // // Ignore for unkown section type. // - VerboseMsg ("%s unknown section type %x. We directly copy this section into Coff file", mInImageName, (unsigned)Shdr->sh_type); + VerboseMsg ("%s unknown section type %x. We directly ignore this section and NOT copy into Coff file", mInImageName, (unsigned)Shdr->sh_type); break; } } @@ -691,6 +691,26 @@ WriteSections64 ( - (SecOffset - SecShdr->sh_addr)); VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); break; + case R_X86_64_PLT32: + // + // Relative relocation: L + A - P + // + VerboseMsg ("R_X86_64_PLT32"); + VerboseMsg ("Offset: 0x%08X, Addend: 0x%08X", + (UINT32)(SecOffset + (Rel->r_offset - SecShdr->sh_addr)), + *(UINT32 *)Targ); + *(UINT32 *)Targ = (UINT32) (*(UINT32 *)Targ + + (mCoffSectionsOffset[Sym->st_shndx] - SymShdr->sh_addr) + - (SecOffset - SecShdr->sh_addr)); + VerboseMsg ("Relocation: 0x%08X", *(UINT32 *)Targ); + break; + case R_X86_64_GOTPCREL: + case R_X86_64_REX_GOTPCRELX: + // + // Relative relocation: G + GOT + A - P + // + VerboseMsg ("R_X86_64_GOTPCREL"); + break; default: Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } @@ -770,7 +790,15 @@ WriteRelocations64 ( UINT32 Index; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; EFI_IMAGE_DATA_DIRECTORY *Dir; + UINT64 GoTPcRelPtrOffset = 0; + UINT64 *RipDisplacementPtr; + UINT64 *ElfFileGoTPcRelPtr; + UINT64 *CoffFileGoTPcRelPtr; + Elf_Shdr *shdr; + UINT32 i; + + for (Index = 0; Index < mEhdr->e_shnum; Index++) { Elf_Shdr *RelShdr = GetShdrByIndex(Index); if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { @@ -785,6 +813,51 @@ WriteRelocations64 ( switch (ELF_R_TYPE(Rel->r_info)) { case R_X86_64_NONE: case R_X86_64_PC32: + case R_X86_64_PLT32: + break; + case R_X86_64_GOTPCREL: + case R_X86_64_REX_GOTPCRELX: + // + // link script force .got and .got.* in .text section, so GoTPcRel pointer must be in .text section + // but its value might point to .text or .data section + // + RipDisplacementPtr = (UINT64 *)((UINT8*)mEhdr + SecShdr->sh_offset + Rel->r_offset - SecShdr->sh_addr); + GoTPcRelPtrOffset = Rel->r_offset + 4 + (INT32)(*RipDisplacementPtr) - SecShdr->sh_addr; + ElfFileGoTPcRelPtr = (UINT64 *)((UINT8*)mEhdr + SecShdr->sh_offset + GoTPcRelPtrOffset); + CoffFileGoTPcRelPtr = (UINT64 *)(mCoffFile + mCoffSectionsOffset[RelShdr->sh_info] + GoTPcRelPtrOffset); + // + // Check which section the GoTPcRel pointer point to, and calculate Elf to Coff sections displacement accordingly + // + shdr = NULL; + for (i = 0; i < mEhdr->e_shnum; i++) { + shdr = GetShdrByIndex(i); + if ((*ElfFileGoTPcRelPtr >= shdr->sh_addr) && + (*ElfFileGoTPcRelPtr < shdr->sh_addr + shdr->sh_size)) { + break; + } + } + // + // Fix the Elf to Coff sections displacement + // + if(IsDataShdr(shdr)) { + *CoffFileGoTPcRelPtr = *CoffFileGoTPcRelPtr + mDataOffset - shdr->sh_addr; + }else if (IsTextShdr(SecShdr)){ + *CoffFileGoTPcRelPtr = *CoffFileGoTPcRelPtr + mTextOffset - shdr->sh_addr; + }else { + // + // link script force to merge .rodata .rodata.*, .got and .got.* in .text section, + // not support GoTPcRel point to section other than .data or .text + // + Error (NULL, 0, 3000, "Invalid", "Not support relocate R_X86_64_GOTPCREL address in section other than .data or .text"); + assert (FALSE); + } + + VerboseMsg ("R_X86_64_GOTPCREL to EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", + mCoffSectionsOffset[RelShdr->sh_info] + GoTPcRelPtrOffset); + CoffAddFixup( + (UINT32)(UINTN)((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + GoTPcRelPtrOffset), + EFI_IMAGE_REL_BASED_DIR64); + VerboseMsg ("Relocation: 0x%08X", *(UINT64*)CoffFileGoTPcRelPtr); break; case R_X86_64_64: VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X",