Index: llvm/include/llvm/Object/MutableELFObject.h =================================================================== --- /dev/null +++ llvm/include/llvm/Object/MutableELFObject.h @@ -0,0 +1,298 @@ +//===-- MutableELFObject.h --------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// This file declares the MutableELFObject template class. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MUTABLEELFOBJECT_H +#define LLVM_OBJECT_MUTABLEELFOBJECT_H + +#include "ELFObjectFile.h" +#include "ELFTypes.h" +#include "MutableObject.h" +#include "llvm/MC/StringTableBuilder.h" + +namespace llvm { +namespace object { +namespace elf { + +template class MutableELFObject; +template class MutableSection; +template class MutableStrTabSection; +template class MutableSectionIndexSection; +template class MutableSymbolTableSection; +template class MutableRelocationSection; +template class MutableDynRelocationSection; +template class MutableGroupSection; + +template +class MutableSection : public MutableSectionBase, public Elf_Shdr_Impl { + +public: + MutableSection(const MutableSection &) = default; + MutableSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSectionBase(Name, Data), Elf_Shdr_Impl(SecHeader) {} + ~MutableSection() override {} + + static bool classof(const MutableSectionBase *Sec) { + return isa>(Sec->OwningObject); + } + + virtual std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template +class MutableStrTabSection : public MutableSection { + +public: + MutableStrTabSection(const MutableStrTabSection &) = default; + MutableStrTabSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSection(Name, Data, SecHeader) { + assert(SecHeader.sh_type == ELF::SHT_STRTAB && "Expected .strtab section"); + } + ~MutableStrTabSection() override {} + + StringRef getName(uint64_t Index) const { return this->Data.data() + Index; } + + uint64_t findIndex(StringRef Name) const; + + static bool classof(const MutableSection *S) { + return S->sh_type == ELF::SHT_STRTAB; + } + + std::unique_ptr clone() const override { + // return std::unique_ptr(new + // MutableStrTabSection(*this)); + return make_unique>(*this); + } +}; + +template +class MutableSectionIndexSection : public MutableSection { + +public: + MutableSectionIndexSection(const MutableSectionIndexSection &) = default; + MutableSectionIndexSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSection(Name, Data, SecHeader) { + assert(SecHeader.sh_type == ELF::SHT_SYMTAB_SHNDX && "Incorrect sh_type"); + } + ~MutableSectionIndexSection() override {} + + static bool classof(const MutableSection *S) { + return S->sh_type == ELF::SHT_SYMTAB_SHNDX; + } + + std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template +class MutableSymbolTableSection : public MutableSection { + +public: + MutableSymbolTableSection(const MutableSymbolTableSection &) = default; + MutableSymbolTableSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSection(Name, Data, SecHeader) {} + ~MutableSymbolTableSection() override {} + + static bool classof(const MutableSection *S) { + return S->sh_type == ELF::SHT_SYMTAB; + } + + std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template +class MutableRelocationSection : public MutableSection { + +public: + MutableRelocationSection(const MutableRelocationSection &) = default; + MutableRelocationSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSection(Name, Data, SecHeader) { + assert(!(SecHeader.sh_flags & ELF::SHF_ALLOC) && + "Relocation section shouldn't be allocated"); + assert(SecHeader.sh_type == ELF::SHT_REL || + SecHeader.sh_type == ELF::SHT_RELA && "Incorrect sh_type"); + } + ~MutableRelocationSection() override {} + + static bool classof(const MutableSection *S) { + if (S->Flags & ELF::SHF_ALLOC) + return false; + return S->sh_type == ELF::SHT_REL || S->sh_type == ELF::SHT_RELA; + } + + std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template +class MutableDynRelocationSection : public MutableSection { + +public: + MutableDynRelocationSection(const MutableDynRelocationSection &) = default; + MutableDynRelocationSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSection(Name, Data, SecHeader) { + assert(SecHeader.sh_flags & ELF::SHF_ALLOC && + "Dynamic relocation section should be allocated"); + assert(SecHeader.sh_type == ELF::SHT_REL || + SecHeader.sh_type == ELF::SHT_RELA && "Incorrect sh_type"); + } + ~MutableDynRelocationSection() override {} + + static bool classof(const MutableSection *S) { + if (!(S->Flags & ELF::SHF_ALLOC)) + return false; + return S->sh_type == ELF::SHT_REL || S->sh_type == ELF::SHT_RELA; + } + + std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template +class MutableGroupSection : public MutableSection { + +public: + MutableGroupSection(const MutableGroupSection &) = default; + MutableGroupSection(std::string Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) + : MutableSection(Name, Data, SecHeader) { + assert(SecHeader.sh_type == ELF::SHT_GROUP && "Incorrect sh_type"); + } + ~MutableGroupSection() override {} + + static bool classof(const MutableSection *S) { + return S->sh_type == ELF::SHT_GROUP; + } + + std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template +class MutableSegment : public MutableSegmentBase, public Elf_Phdr_Impl { + +public: + MutableSegment(const MutableSegment &) = default; + MutableSegment(ArrayRef Data, Elf_Phdr_Impl ProgHeader) + : MutableSectionBase(Data), Elf_Phdr_Impl(ProgHeader) {} + ~MutableSegment() override {} + + static bool classof(const MutableSectionBase *Sec) { + return isa>(Sec->OwningObject); + } + + std::unique_ptr clone() const override { + return make_unique>(*this); + } +}; + +template class MutableELFObject : public MutableObject { + Elf_Ehdr_Impl Header; + +public: + MutableELFObject(const ObjectFile &ObjFile, + SectionList::VecType OriginalSections, + SegmentList::VecType OriginalSegments, + SymbolList::VecType OriginalSymbols, + Elf_Ehdr_Impl Header) + : MutableObject(ObjFile, std::move(OriginalSections), + std::move(OriginalSegments), std::move(OriginalSymbols)), + Header(Header) {} + +public: + static Expected> + createMutableObject(const ELFObjectFile &ObjFile); + + const ELFObjectFile *getObjectFile() const { return &ObjFile; } +}; + +template +static std::unique_ptr> +makeSection(StringRef Name, ArrayRef Data, + Elf_Shdr_Impl SecHeader) { + switch (SecHeader.sh_type) { + case ELF::SHT_STRTAB: + return make_unique>(Name, Data, SecHeader); + case ELF::SHT_SYMTAB_SHNDX: + return make_unique>(Name, Data, SecHeader); + case ELF::SHT_SYMTAB: + return make_unique>(Name, Data, SecHeader); + case ELF::SHT_REL: + case ELF::SHT_RELA: + if (SecHeader.sh_flags & ELF::SHF_ALLOC) + return make_unique>(Name, Data, + SecHeader); + else + return make_unique>(Name, Data, SecHeader); + case ELF::SHT_GROUP: + return make_unique>(Name, Data, SecHeader); + } + return make_unique>(Name, Data, SecHeader); +} + +template +Expected> +MutableELFObject::createMutableObject( + const ELFObjectFile &ObjFile) { + auto &Header = *ObjFile.getELFFile()->getHeader(); + const uint8_t *Base = reinterpret_cast( + ObjFile.getMemoryBufferRef().getBufferStart()); + + ArrayRef> SectionHeaders( + reinterpret_cast *>(Base + Header.e_shoff), + Header.e_shnum); + + const uint8_t *Shstrndx = nullptr; + if (Header.e_shstrndx) { + size_t Index = Header.e_shstrndx == ELF::SHN_XINDEX + ? SectionHeaders[0].sh_size + : Header.e_shstrndx; + Shstrndx = Base + SectionHeaders[Index].sh_offset; + } + auto SectionName = [Shstrndx](size_t StrOffset) -> StringRef { + if (!Shstrndx) + return StringRef(); + return StringRef(reinterpret_cast(Shstrndx) + StrOffset); + }; + + SectionList::VecType OriginalSections; + for (const auto &SecHeader : SectionHeaders) + OriginalSections.push_back(makeSection( + SectionName(SecHeader.sh_name), + ArrayRef(Base + SecHeader.sh_offset, SecHeader.sh_size), + SecHeader)); + + SegmentList::VecType OriginalSegments; + + return std::unique_ptr(new MutableELFObject( + ObjFile, std::move(OriginalSections), SegmentList::VecType(), + SymbolList::VecType(), Header)); +} + +} // namespace elf +} // namespace object +} // namespace llvm + +#endif // LLVM_OBJECT_MUTABLEELFOBJECT_H Index: llvm/include/llvm/Object/MutableObject.h =================================================================== --- /dev/null +++ llvm/include/llvm/Object/MutableObject.h @@ -0,0 +1,119 @@ +//===-- MutableObject.h -----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// +// +// Class for doing mutations on object files. +// +//===----------------------------------------------------------------------===// + +#ifndef LLVM_OBJECT_MUTABLEOBJECT_H +#define LLVM_OBJECT_MUTABLEOBJECT_H + +#include "ObjectFile.h" +#include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/MutableRange.h" +#include + +namespace llvm { +namespace object { + +struct MutableSectionBase; +struct MutableSegmentBase; +struct MutableSymbolBase; +class MutableObject; + +struct MutableSectionBase { + const MutableObject *OwningObject = nullptr; + MutableSegmentBase *OwnedSegment = nullptr; + + // Name is mutable because the original name can be recovered using + // sh_name or similar. This makes it more effecient add a prefix to + // all sections for example. + mutable std::string Name; + ArrayRef Data; + + MutableSectionBase(std::string Name, ArrayRef Data) + : Name(Name), Data(Data) {} + virtual ~MutableSectionBase() {} + + virtual std::unique_ptr clone() const { + return make_unique(*this); + } +}; + +struct MutableSegmentBase { + const MutableObject *OwningObject = nullptr; + MutableSegmentBase *OwnedSegment = nullptr; + ArrayRef Data; + + MutableSegmentBase(ArrayRef Data) : Data(Data) {} + virtual ~MutableSegmentBase() {} + virtual std::unique_ptr clone() const; +}; + +struct MutableSymbolBase { + const MutableObject *OwningObject = nullptr; + MutableSegmentBase *OwnedSegment = nullptr; + mutable std::string Name; + + MutableSymbolBase(const MutableObject &OwningObject, std::string Name) + : Name(Name) {} + virtual ~MutableSymbolBase() {} + virtual std::unique_ptr clone() const; +}; + +// Custom cloner for MutableRange because MutableXXXBase classes +// are non trivially copyable. +template struct MutableEntryCloner { + T operator()(const T *Other) { return (*Other)->clone(); } +}; + +// MutableRange doesn't take ownership of the underlying container +// this is a small wrapper that does. +template +struct OwningMutableRange + : public MutableRange, MutableEntryCloner> { + using VecType = std::vector; + using Base = MutableRange>; + + OwningMutableRange(VecType Vec) : Base(Vec), OwnedVec(std::move(Vec)) {} + +private: + const VecType OwnedVec; +}; + +class MutableObject { +protected: + const ObjectFile &ObjFile; + + using SectionList = OwningMutableRange>; + using SegmentList = OwningMutableRange>; + using SymbolList = OwningMutableRange>; + SectionList Sections; + SegmentList Segments; + SymbolList Symbols; + + MutableObject(const ObjectFile &ObjFile, + SectionList::VecType OriginalSections, + SegmentList::VecType OriginalSegments, + SymbolList::VecType OriginalSymbols); + +public: + static Expected> + createMutableObject(const ObjectFile &ObjFile); + + const ObjectFile *getObjectFile() const { return &ObjFile; } + + SectionList §ions() { return Sections; } + SegmentList &segments() { return Segments; } + SymbolList &symbols() { return Symbols; } +}; + +} // namespace object +} // namespace llvm + +#endif // LLVM_OBJECT_MUTABLEOBJECT_H Index: llvm/lib/Object/CMakeLists.txt =================================================================== --- llvm/lib/Object/CMakeLists.txt +++ llvm/lib/Object/CMakeLists.txt @@ -15,6 +15,7 @@ MachOUniversal.cpp Minidump.cpp ModuleSymbolTable.cpp + MutableObject.cpp Object.cpp ObjectFile.cpp RecordStreamer.cpp Index: llvm/lib/Object/MutableObject.cpp =================================================================== --- /dev/null +++ llvm/lib/Object/MutableObject.cpp @@ -0,0 +1,35 @@ +//===- MutableObject.cpp - An object file which can be mutated ------------===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "llvm/Object/MutableObject.h" + +using namespace llvm; +using namespace object; + +MutableObject::MutableObject(const ObjectFile &ObjFile, + SectionList::VecType OriginalSections, + SegmentList::VecType OriginalSegments, + SymbolList::VecType OriginalSymbols) + : ObjFile(ObjFile), Sections(std::move(OriginalSections)), + Segments(std::move(OriginalSegments)), + Symbols(std::move(OriginalSymbols)) {} + +Expected> +MutableObject::createMutableObject(const ObjectFile &ObjFile) { + // Hacky way to expose the constructor publicly for make_unique. + struct PublicCtor : public MutableObject { + PublicCtor(const ObjectFile &ObjFile, SectionList::VecType Secs, + SegmentList::VecType Segs, SymbolList::VecType Syms) + : MutableObject(ObjFile, std::move(Secs), std::move(Segs), + std::move(Syms)) {} + }; + + return llvm::make_unique(ObjFile, SectionList::VecType(), + SegmentList::VecType(), + SymbolList::VecType()); +}