//===- Object.h -------------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLVM_OBJCOPY_OBJECT_H #define LLVM_OBJCOPY_OBJECT_H #include "llvm/MC/StringTableBuilder.h" #include "llvm/Object/ELFObjectFile.h" #include "llvm/Support/FileOutputBuffer.h" #include #include class Segment; class SectionBase { public: llvm::StringRef Name; Segment *ParentSegment = nullptr; uint64_t HeaderOffset; uint64_t OriginalOffset; uint32_t Index; uint64_t Addr = 0; uint64_t Align = 1; uint32_t EntrySize = 0; uint64_t Flags = 0; uint64_t Info = 0; uint64_t Link = llvm::ELF::SHN_UNDEF; uint64_t NameIndex = 0; uint64_t Offset = 0; uint64_t Size = 0; uint64_t Type = llvm::ELF::SHT_NULL; virtual ~SectionBase() {} virtual void finalize(); template void writeHeader(llvm::FileOutputBuffer &Out) const; virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0; }; class Segment { private: struct SectionCompare { bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const { // Some sections might have the same address if one of them is empty. To // fix this we can use the lexicographic ordering on ->Addr and the // address of the actully stored section. if (Lhs->OriginalOffset == Rhs->OriginalOffset) return Lhs < Rhs; return Lhs->OriginalOffset < Rhs->OriginalOffset; } }; std::set Sections; llvm::ArrayRef Contents; public: uint64_t Align; uint64_t FileSize; uint32_t Flags; uint32_t Index; uint64_t MemSize; uint64_t Offset; uint64_t PAddr; uint64_t Type; uint64_t VAddr; uint64_t OriginalOffset; Segment(llvm::ArrayRef Data) : Contents(Data) {} void finalize(); const SectionBase *firstSection() const { if (!Sections.empty()) return *Sections.begin(); return nullptr; } void addSection(const SectionBase *sec) { Sections.insert(sec); } template void writeHeader(llvm::FileOutputBuffer &Out) const; void writeSegment(llvm::FileOutputBuffer &Out) const; }; class Section : public SectionBase { private: llvm::ArrayRef Contents; public: Section(llvm::ArrayRef Data) : Contents(Data) {} void writeSection(llvm::FileOutputBuffer &Out) const override; }; // This is just a wraper around a StringTableBuilder that implements SectionBase class StringTableSection : public SectionBase { private: llvm::StringTableBuilder StrTabBuilder; public: StringTableSection() : StrTabBuilder(llvm::StringTableBuilder::ELF) { Type = llvm::ELF::SHT_STRTAB; } void addString(llvm::StringRef Name); uint32_t findIndex(llvm::StringRef Name) const; void finalize() override; void writeSection(llvm::FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { return S->Type == llvm::ELF::SHT_STRTAB; } }; // Symbols have a st_shndx field that normally stores an index but occasionally // stores a different special value. This enum keeps track of what the st_shndx // field means. Most of the values are just copies of the special SHN_* values. // SYMBOL_SIMPLE_INDEX means that the st_shndx is just an index of a section. enum SymbolShndxType { SYMBOL_SIMPLE_INDEX = 0, SYMBOL_ABS = llvm::ELF::SHN_ABS, SYMBOL_COMMON = llvm::ELF::SHN_COMMON, SYMBOL_HEXAGON_SCOMMON = llvm::ELF::SHN_HEXAGON_SCOMMON, SYMBOL_HEXAGON_SCOMMON_2 = llvm::ELF::SHN_HEXAGON_SCOMMON_2, SYMBOL_HEXAGON_SCOMMON_4 = llvm::ELF::SHN_HEXAGON_SCOMMON_4, SYMBOL_HEXAGON_SCOMMON_8 = llvm::ELF::SHN_HEXAGON_SCOMMON_8, }; struct Symbol { uint8_t Binding; SectionBase *DefinedIn; SymbolShndxType ShndxType; uint32_t Index; llvm::StringRef Name; uint32_t NameIndex; uint64_t Size; uint8_t Type; uint64_t Value; uint16_t getShndx() const; }; class SymbolTableSection : public SectionBase { protected: std::vector> Symbols; StringTableSection *SymbolNames; public: void setStrTab(StringTableSection *StrTab) { SymbolNames = StrTab; } void addSymbol(llvm::StringRef Name, uint8_t Bind, uint8_t Type, SectionBase *DefinedIn, uint64_t Value, uint16_t Shndx, uint64_t Sz); void addSymbolNames(); const Symbol *getSymbolByIndex(uint32_t Index) const; void finalize() override; static bool classof(const SectionBase *S) { return S->Type == llvm::ELF::SHT_SYMTAB; } }; // Only writeSection depends on the ELF type so we implement it in a subclass. template class SymbolTableSectionImpl : public SymbolTableSection { void writeSection(llvm::FileOutputBuffer &Out) const override; }; struct Relocation { const Symbol *RelocSymbol; uint64_t Offset; uint64_t Addend; uint32_t Type; }; template class RelocationSection : public SectionBase { private: typedef typename ELFT::Rel Elf_Rel; typedef typename ELFT::Rela Elf_Rela; std::vector Relocations; SymbolTableSection *Symbols; SectionBase *SecToApplyRel; template void writeRel(T *Buf) const; public: void setSymTab(SymbolTableSection *StrTab) { Symbols = StrTab; } void setSection(SectionBase *Sec) { SecToApplyRel = Sec; } void addRelocation(Relocation Rel) { Relocations.push_back(Rel); } void finalize() override; void writeSection(llvm::FileOutputBuffer &Out) const override; static bool classof(const SectionBase *S) { return S->Type == llvm::ELF::SHT_REL || S->Type == llvm::ELF::SHT_RELA; } }; template class Object { private: typedef std::unique_ptr SecPtr; typedef std::unique_ptr SegPtr; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Ehdr Elf_Ehdr; typedef typename ELFT::Phdr Elf_Phdr; void initSymbolTable(const llvm::object::ELFFile &ElfFile, SymbolTableSection *SymTab); SecPtr makeSection(const llvm::object::ELFFile &ElfFile, const Elf_Shdr &Shdr); void readProgramHeaders(const llvm::object::ELFFile &ElfFile); void readSectionHeaders(const llvm::object::ELFFile &ElfFile); protected: StringTableSection *SectionNames; SymbolTableSection *SymbolTable; std::vector Sections; std::vector Segments; void writeHeader(llvm::FileOutputBuffer &Out) const; void writeProgramHeaders(llvm::FileOutputBuffer &Out) const; void writeSectionData(llvm::FileOutputBuffer &Out) const; void writeSectionHeaders(llvm::FileOutputBuffer &Out) const; public: uint8_t Ident[16]; uint64_t Entry; uint64_t SHOffset; uint32_t Type; uint32_t Machine; uint32_t Version; uint32_t Flags; Object(const llvm::object::ELFObjectFile &Obj); virtual size_t totalSize() const = 0; virtual void finalize() = 0; virtual void write(llvm::FileOutputBuffer &Out) const = 0; virtual ~Object() = default; }; template class ELFObject : public Object { private: typedef std::unique_ptr SecPtr; typedef std::unique_ptr SegPtr; typedef typename ELFT::Shdr Elf_Shdr; typedef typename ELFT::Ehdr Elf_Ehdr; typedef typename ELFT::Phdr Elf_Phdr; void sortSections(); void assignOffsets(); public: ELFObject(const llvm::object::ELFObjectFile &Obj) : Object(Obj) {} void finalize() override; size_t totalSize() const override; void write(llvm::FileOutputBuffer &Out) const override; }; template class BinaryObject : public Object { private: typedef std::unique_ptr SecPtr; typedef std::unique_ptr SegPtr; uint64_t TotalSize; public: BinaryObject(const llvm::object::ELFObjectFile &Obj) : Object(Obj) {} void finalize() override; size_t totalSize() const override; void write(llvm::FileOutputBuffer &Out) const override; }; #endif