Index: llvm/include/llvm/Object/ELFObjectFile.h =================================================================== --- llvm/include/llvm/Object/ELFObjectFile.h +++ llvm/include/llvm/Object/ELFObjectFile.h @@ -382,6 +382,10 @@ 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 +425,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; } @@ -494,7 +498,7 @@ 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) && ESym->getType() == ELF::STT_FUNC) @@ -515,7 +519,7 @@ 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(); @@ -543,11 +547,11 @@ template uint16_t ELFObjectFile::getEMachine() const { - return EF.getHeader()->e_machine; + return getHeader()->e_machine; } template uint16_t ELFObjectFile::getEType() const { - return EF.getHeader()->e_type; + return getHeader()->e_type; } template @@ -623,7 +627,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") || @@ -810,7 +814,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)); } @@ -837,7 +841,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); @@ -896,7 +900,7 @@ template StringRef ELFObjectFile::getRelocationTypeName(uint32_t Type) const { - return getELFRelocationTypeName(EF.getHeader()->e_machine, Type); + return getELFRelocationTypeName(getHeader()->e_machine, Type); } template @@ -1046,9 +1050,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: @@ -1080,7 +1084,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: @@ -1112,7 +1116,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; @@ -1129,7 +1133,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: @@ -1144,7 +1148,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: @@ -1165,7 +1169,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; @@ -1186,7 +1190,7 @@ template Expected ELFObjectFile::getStartAddress() const { - return EF.getHeader()->e_entry; + return getHeader()->e_entry; } template @@ -1196,7 +1200,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 @@ -213,14 +213,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,15 +253,18 @@ : DynSymbols; } + const Elf_Ehdr *getHeader() const override { return &FileHeader; } + static DataRefImpl toDataRef(uintptr_t Ptr); static DataRefImpl toDataRef(uint32_t A, uint32_t B); 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)), + this->base() + getHeader()->e_shoff), + getHeader()->e_shnum)), Symbols(findSymbolTable(ELF::SHT_SYMTAB)), DynSymbols(findSymbolTable(ELF::SHT_DYNSYM)) {} @@ -361,6 +361,9 @@ void removeSection(SectionRef Sec) { Sections.remove(Sec.getRawDataRefImpl().p); } + + const Elf_Ehdr &header() const { return FileHeader; } + Elf_Ehdr &header() { return FileHeader; } }; template Index: llvm/unittests/Object/MutableELFObjectTest.cpp =================================================================== --- llvm/unittests/Object/MutableELFObjectTest.cpp +++ llvm/unittests/Object/MutableELFObjectTest.cpp @@ -703,3 +703,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.header(); + EXPECT_EQ(Header.e_type, ELF::ET_REL); + Header.e_type = ELF::ET_EXEC; + EXPECT_EQ(MutableObject.header().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); +}