Index: llvm/include/llvm/Object/ELFObjectFile.h =================================================================== --- llvm/include/llvm/Object/ELFObjectFile.h +++ llvm/include/llvm/Object/ELFObjectFile.h @@ -382,6 +382,8 @@ return Error::success(); } + virtual const Elf_Ehdr &getHeader() const { return *EF.getHeader(); } + // This flag is used for classof, to distinguish ELFObjectFile from // its subclass. If more subclasses will be created, this flag will // have to become an enum. @@ -421,7 +423,7 @@ Triple::ArchType getArch() const override; Expected getStartAddress() const override; - unsigned getPlatformFlags() const override { return EF.getHeader()->e_flags; } + unsigned getPlatformFlags() const override { return getHeader().e_flags; } const ELFFile *getELFFile() const { return &EF; } @@ -496,9 +498,9 @@ if (ESym->st_shndx == ELF::SHN_ABS) return Ret; - const Elf_Ehdr *Header = EF.getHeader(); + const Elf_Ehdr &Header = getHeader(); // Clear the ARM/Thumb or microMIPS indicator flag. - if ((Header->e_machine == ELF::EM_ARM || Header->e_machine == ELF::EM_MIPS) && + if ((Header.e_machine == ELF::EM_ARM || Header.e_machine == ELF::EM_MIPS) && ESym->getType() == ELF::STT_FUNC) Ret &= ~1; @@ -517,13 +519,13 @@ return Result; } - const Elf_Ehdr *Header = EF.getHeader(); + const Elf_Ehdr &Header = getHeader(); auto SymTabOrErr = EF.getSection(Symb.d.a); if (!SymTabOrErr) return SymTabOrErr.takeError(); const Elf_Shdr *SymTab = *SymTabOrErr; - if (Header->e_type == ELF::ET_REL) { + if (Header.e_type == ELF::ET_REL) { auto SectionOrErr = EF.getSection(ESym, SymTab, ShndxTable); if (!SectionOrErr) return SectionOrErr.takeError(); @@ -543,13 +545,12 @@ return 0; } -template -uint16_t ELFObjectFile::getEMachine() const { - return EF.getHeader()->e_machine; +template uint16_t ELFObjectFile::getEMachine() const { + return getHeader().e_machine; } template uint16_t ELFObjectFile::getEType() const { - return EF.getHeader()->e_type; + return getHeader().e_type; } template @@ -625,7 +626,7 @@ if (DotDynSymSecSyms && ESym == (*DotDynSymSecSyms).begin()) Result |= SymbolRef::SF_FormatSpecific; - if (EF.getHeader()->e_machine == ELF::EM_ARM) { + if (getHeader().e_machine == ELF::EM_ARM) { if (Expected NameOrErr = getSymbolName(Sym)) { StringRef Name = *NameOrErr; if (Name.startswith("$d") || Name.startswith("$t") || @@ -812,7 +813,7 @@ if (!SectionsOrErr) return relocation_iterator(RelocationRef()); uintptr_t SHT = reinterpret_cast((*SectionsOrErr).begin()); - RelData.d.a = (Sec.p - SHT) / EF.getHeader()->e_shentsize; + RelData.d.a = (Sec.p - SHT) / getHeader().e_shentsize; RelData.d.b = 0; return relocation_iterator(RelocationRef(RelData, this)); } @@ -839,7 +840,7 @@ template section_iterator ELFObjectFile::getRelocatedSection(DataRefImpl Sec) const { - if (EF.getHeader()->e_type != ELF::ET_REL) + if (getHeader().e_type != ELF::ET_REL) return section_end(); const Elf_Shdr *EShdr = getSection(Sec); @@ -898,7 +899,7 @@ template StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { - return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); + return getELFRelocationTypeName(getHeader().e_machine, Type); } template @@ -1048,9 +1049,9 @@ template StringRef ELFObjectFile::getFileFormatName() const { bool IsLittleEndian = ELFT::TargetEndianness == support::little; - switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + switch (getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: - switch (EF.getHeader()->e_machine) { + switch (getHeader().e_machine) { case ELF::EM_386: return "ELF32-i386"; case ELF::EM_IAMCU: @@ -1082,7 +1083,7 @@ return "ELF32-unknown"; } case ELF::ELFCLASS64: - switch (EF.getHeader()->e_machine) { + switch (getHeader().e_machine) { case ELF::EM_386: return "ELF64-i386"; case ELF::EM_X86_64: @@ -1114,7 +1115,7 @@ template Triple::ArchType ELFObjectFile::getArch() const { bool IsLittleEndian = ELFT::TargetEndianness == support::little; - switch (EF.getHeader()->e_machine) { + switch (getHeader().e_machine) { case ELF::EM_386: case ELF::EM_IAMCU: return Triple::x86; @@ -1131,7 +1132,7 @@ case ELF::EM_LANAI: return Triple::lanai; case ELF::EM_MIPS: - switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + switch (getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: return IsLittleEndian ? Triple::mipsel : Triple::mips; case ELF::ELFCLASS64: @@ -1146,7 +1147,7 @@ case ELF::EM_PPC64: return IsLittleEndian ? Triple::ppc64le : Triple::ppc64; case ELF::EM_RISCV: - switch (EF.getHeader()->e_ident[ELF::EI_CLASS]) { + switch (getHeader().e_ident[ELF::EI_CLASS]) { case ELF::ELFCLASS32: return Triple::riscv32; case ELF::ELFCLASS64: @@ -1167,7 +1168,7 @@ if (!IsLittleEndian) return Triple::UnknownArch; - unsigned MACH = EF.getHeader()->e_flags & ELF::EF_AMDGPU_MACH; + unsigned MACH = getHeader().e_flags & ELF::EF_AMDGPU_MACH; if (MACH >= ELF::EF_AMDGPU_MACH_R600_FIRST && MACH <= ELF::EF_AMDGPU_MACH_R600_LAST) return Triple::r600; @@ -1188,7 +1189,7 @@ template Expected ELFObjectFile::getStartAddress() const { - return EF.getHeader()->e_entry; + return getHeader().e_entry; } template @@ -1198,7 +1199,7 @@ } template bool ELFObjectFile::isRelocatableObject() const { - return EF.getHeader()->e_type == ELF::ET_REL; + return getHeader().e_type == ELF::ET_REL; } } // end namespace object Index: llvm/include/llvm/Object/MutableELFObject.h =================================================================== --- llvm/include/llvm/Object/MutableELFObject.h +++ llvm/include/llvm/Object/MutableELFObject.h @@ -207,14 +207,11 @@ using MutableSymbolTable = MutableTable>; + Elf_Ehdr FileHeader; MutableTable> Sections; MutableSymbolTable Symbols; MutableSymbolTable DynSymbols; - const Elf_Ehdr &getHeader() const { - return *reinterpret_cast(this->base()); - } - /// Many getSection* methods in ELFObjectFile use getSection to get the /// the header associated with that section. This override returns a valid /// section header whether the section has been modified or not. @@ -256,6 +253,7 @@ public: explicit MutableELFObject(ELFObjectFile &&B) : ELFObjectFile(std::move(B)), + FileHeader(*reinterpret_cast(this->base())), Sections(ArrayRef(reinterpret_cast( this->base() + getHeader().e_shoff), getHeader().e_shnum)), @@ -354,6 +352,9 @@ assert(Sec.getRawDataRefImpl().p && "Cannot remove index 0 section"); Sections.remove(Sec.getRawDataRefImpl().p); } + + const Elf_Ehdr &getHeader() const override { return FileHeader; } + Elf_Ehdr &getMutableHeader() { return FileHeader; } }; template Index: llvm/unittests/Object/MutableELFObjectTest.cpp =================================================================== --- llvm/unittests/Object/MutableELFObjectTest.cpp +++ llvm/unittests/Object/MutableELFObjectTest.cpp @@ -726,3 +726,36 @@ EXPECT_EQ(Distance(), 8); EXPECT_EQ(IterAtIndex(7)->getSize(), 100u); } + +TEST(MutableELFObject, UpdateHeader) { + SmallString<0> Storage; + Expected> ErrOrObj = yaml2ObjectFile(Storage, R"( +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64)"); + + ASSERT_THAT_EXPECTED(ErrOrObj, Succeeded()); + auto *ELFObjFile = dyn_cast>(ErrOrObj->get()); + ASSERT_TRUE(ELFObjFile); + MutableELFObject MutableObject(std::move(*ELFObjFile)); + + Elf_Ehdr_Impl &Header = MutableObject.getMutableHeader(); + EXPECT_EQ(Header.e_type, ELF::ET_REL); + Header.e_type = ELF::ET_EXEC; + EXPECT_EQ(MutableObject.getHeader().e_type, ELF::ET_EXEC); + EXPECT_FALSE(MutableObject.isRelocatableObject()); + + Header.e_type = ELF::ET_REL; + EXPECT_TRUE(MutableObject.isRelocatableObject()); + + Header.e_flags = 100; + EXPECT_EQ(MutableObject.getPlatformFlags(), 100u); + + Header.e_entry = 5; + Expected StartAddr = MutableObject.getStartAddress(); + ASSERT_THAT_EXPECTED(StartAddr, Succeeded()); + EXPECT_EQ(*StartAddr, 5u); +}