Index: llvm/include/llvm/Object/MutableELFObject.h =================================================================== --- llvm/include/llvm/Object/MutableELFObject.h +++ llvm/include/llvm/Object/MutableELFObject.h @@ -34,6 +34,12 @@ Header.sh_size); } + MutableELFSection(const Elf_Shdr &Header, StringRef Name, + OwningArrayRef &&Data) + : Header(Header), Name(Name), Data(std::move(Data)) {} + + MutableELFSection(MutableELFSection &&Other) = default; + void setData(ArrayRef Ref) { Data = OwningArrayRef(Ref); Header.sh_size = Data.size(); @@ -163,6 +169,13 @@ Mappings[Index].Type = MappingType::Removed; } + /// Add's \param Value to the end of the table. + NewType &add(NewType &&Value) { + NewValues.emplace_back(std::move(Value)); + Mappings.emplace_back(NewValues.size() - 1, MappingType::New); + return NewValues.back(); + } + /// If the entry at index Index has already been made mutable, this returns /// a reference to that. Otherwise, this replaces the current entry at the /// specified index with a NewType constructued with Arguments. @@ -229,6 +242,7 @@ getSectionContents(DataRefImpl Sec) const override; void moveSymbolNext(DataRefImpl &Sym) const override; + const Elf_Sym *getSymbol(DataRefImpl Sym) const override; Expected getSymbolName(DataRefImpl Sym) const override; ArrayRef findSymbolTable(uint64_t ShType) const; uint32_t findSectionOfType(uint64_t ShType) const; @@ -334,6 +348,16 @@ return getMutableSection(*Sec); } + /// Add symbol \param Sym. + MutableELFSymbol &addSymbol(MutableELFSymbol &&Sym) { + return Symbols.add(std::move(Sym)); + } + + /// Add section \param Sec. + MutableELFSection &addSection(MutableELFSection &&Sec) { + return Sections.add(std::move(Sec)); + } + /// Removes a symbol. void removeSymbol(SymbolRef Sym) { assert(Sections.getOriginal(Sym.getRawDataRefImpl().d.a).sh_type == @@ -385,6 +409,15 @@ Sym.d.b = Symbols.getNextIndex(Sym.d.b); } +template +const Elf_Sym_Impl * +MutableELFObject::getSymbol(DataRefImpl Sym) const { + const MutableSymbolTable &Table = getWhichTable(Sym); + if (const MutableELFSymbol *SymOrNull = Table.getConstIfNew(Sym.d.b)) + return &SymOrNull->Header; + return ELFObjectFile::getSymbol(Sym); +} + template Expected MutableELFObject::getSymbolName(DataRefImpl Sym) const { Index: llvm/unittests/Object/MutableELFObjectTest.cpp =================================================================== --- llvm/unittests/Object/MutableELFObjectTest.cpp +++ llvm/unittests/Object/MutableELFObjectTest.cpp @@ -504,3 +504,62 @@ EXPECT_NE(Name, ".remove_me"); EXPECT_NE(Name, ".remove_me_too"); } + +TEST(MutableELFObject, AddSectionAndSymbols) { + 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)); + + EXPECT_EQ( + std::distance(MutableObject.section_begin(), MutableObject.section_end()), + 4); + + Elf_Shdr_Impl Header; + Header.sh_size = 64; + + MutableObject.addSection({Header, ".newsec", OwningArrayRef(64)}); + + EXPECT_EQ( + std::distance(MutableObject.section_begin(), MutableObject.section_end()), + 5); + + auto Iter = MutableObject.section_begin(); + std::advance(Iter, 4); + + EXPECT_EQ(Iter->getSize(), 64u); + StringRef Name; + EXPECT_FALSE(Iter->getName(Name)); + EXPECT_EQ(Name, ".newsec"); + + EXPECT_EQ( + std::distance(MutableObject.symbol_begin(), MutableObject.symbol_end()), + 1); + + Elf_Sym_Impl SymHeader; + SymHeader.st_shndx = ELF::SHN_ABS; + SymHeader.st_value = 1234; + SymHeader.st_size = 2; + auto ReturnedSym = MutableObject.addSymbol({SymHeader, "newsym"}); + EXPECT_EQ(ReturnedSym.Header.st_value, 1234u); + + EXPECT_EQ( + std::distance(MutableObject.symbol_begin(), MutableObject.symbol_end()), + 2); + + ELFSymbolRef NewSym = *symbol_iterator(++MutableObject.symbol_begin()); + EXPECT_EQ(NewSym.getValue(), 1234u); + EXPECT_EQ(NewSym.getSize(), 2u); + Expected NameOrErr = NewSym.getName(); + ASSERT_THAT_EXPECTED(NameOrErr, Succeeded()); + EXPECT_EQ(*NameOrErr, "newsym"); +}