VOID CoffAddFixup( UINT32 Offset, UINT8 Type ) { if (mCoffBaseRel == NULL || mCoffBaseRel->VirtualAddress != (Offset & ~0xfff)) { if (mCoffBaseRel != NULL) { // // Add a null entry (is it required ?) // CoffAddFixupEntry (0); // // Pad for alignment. // if (mCoffOffset % 4 != 0) CoffAddFixupEntry (0); } mCoffFile = realloc ( mCoffFile, mCoffOffset + sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT ); memset ( mCoffFile + mCoffOffset, 0, sizeof(EFI_IMAGE_BASE_RELOCATION) + 2 * MAX_COFF_ALIGNMENT ); mCoffBaseRel = (EFI_IMAGE_BASE_RELOCATION*)(mCoffFile + mCoffOffset); mCoffBaseRel->VirtualAddress = Offset & ~0xfff; mCoffBaseRel->SizeOfBlock = sizeof(EFI_IMAGE_BASE_RELOCATION); mCoffEntryRel = (UINT16 *)(mCoffBaseRel + 1); mCoffOffset += sizeof(EFI_IMAGE_BASE_RELOCATION); } // // Fill the entry. // CoffAddFixupEntry((UINT16) ((Type << 12) | (Offset & 0xfff))); }
STATIC VOID WriteRelocations64 ( VOID ) { UINT32 Index; EFI_IMAGE_OPTIONAL_HEADER_UNION *NtHdr; EFI_IMAGE_DATA_DIRECTORY *Dir; for (Index = 0; Index < mEhdr->e_shnum; Index++) { Elf_Shdr *RelShdr = GetShdrByIndex(Index); if ((RelShdr->sh_type == SHT_REL) || (RelShdr->sh_type == SHT_RELA)) { Elf_Shdr *SecShdr = GetShdrByIndex (RelShdr->sh_info); if (IsTextShdr(SecShdr) || IsDataShdr(SecShdr)) { UINT64 RelIdx; for (RelIdx = 0; RelIdx < RelShdr->sh_size; RelIdx += RelShdr->sh_entsize) { Elf_Rela *Rel = (Elf_Rela *)((UINT8*)mEhdr + RelShdr->sh_offset + RelIdx); if (mEhdr->e_machine == EM_X86_64) { switch (ELF_R_TYPE(Rel->r_info)) { case R_X86_64_NONE: case R_X86_64_PC32: break; case R_X86_64_64: VerboseMsg ("EFI_IMAGE_REL_BASED_DIR64 Offset: 0x%08X", mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); CoffAddFixup( (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)), EFI_IMAGE_REL_BASED_DIR64); break; case R_X86_64_32S: case R_X86_64_32: VerboseMsg ("EFI_IMAGE_REL_BASED_HIGHLOW Offset: 0x%08X", mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)); CoffAddFixup( (UINT32) ((UINT64) mCoffSectionsOffset[RelShdr->sh_info] + (Rel->r_offset - SecShdr->sh_addr)), EFI_IMAGE_REL_BASED_HIGHLOW); break; default: Error (NULL, 0, 3000, "Invalid", "%s unsupported ELF EM_X86_64 relocation 0x%x.", mInImageName, (unsigned) ELF_R_TYPE(Rel->r_info)); } } else { Error (NULL, 0, 3000, "Not Supported", "This tool does not support relocations for ELF with e_machine %u (processor type).", (unsigned) mEhdr->e_machine); } } } } } // // Pad by adding empty entries. // while (mCoffOffset & (mCoffAlignment - 1)) { CoffAddFixupEntry(0); } NtHdr = (EFI_IMAGE_OPTIONAL_HEADER_UNION *)(mCoffFile + mNtHdrOffset); Dir = &NtHdr->Pe32Plus.OptionalHeader.DataDirectory[EFI_IMAGE_DIRECTORY_ENTRY_BASERELOC]; Dir->Size = mCoffOffset - mRelocOffset; if (Dir->Size == 0) { // If no relocations, null out the directory entry and don't add the .reloc section Dir->VirtualAddress = 0; NtHdr->Pe32Plus.FileHeader.NumberOfSections--; } else { Dir->VirtualAddress = mRelocOffset; CreateSectionHeader (".reloc", mRelocOffset, mCoffOffset - mRelocOffset, EFI_IMAGE_SCN_CNT_INITIALIZED_DATA | EFI_IMAGE_SCN_MEM_DISCARDABLE | EFI_IMAGE_SCN_MEM_READ); } }