OSDN Git Service

Reland "[llvm][llvm-objcopy] Added support for outputting to binary in llvm-objcopy"
[android-x86/external-llvm.git] / tools / llvm-objcopy / Object.h
1 //===- Object.h -------------------------------------------------*- C++ -*-===//
2 //
3 //                      The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #ifndef LLVM_OBJCOPY_OBJECT_H
11 #define LLVM_OBJCOPY_OBJECT_H
12
13 #include "llvm/MC/StringTableBuilder.h"
14 #include "llvm/Object/ELFObjectFile.h"
15 #include "llvm/Support/FileOutputBuffer.h"
16
17 #include <memory>
18 #include <set>
19
20 class Segment;
21
22 class SectionBase {
23 public:
24   llvm::StringRef Name;
25   Segment *ParentSegment = nullptr;
26   uint64_t HeaderOffset;
27   uint64_t OriginalOffset;
28   uint32_t Index;
29
30   uint64_t Addr = 0;
31   uint64_t Align = 1;
32   uint32_t EntrySize = 0;
33   uint64_t Flags = 0;
34   uint64_t Info = 0;
35   uint64_t Link = llvm::ELF::SHN_UNDEF;
36   uint64_t NameIndex = 0;
37   uint64_t Offset = 0;
38   uint64_t Size = 0;
39   uint64_t Type = llvm::ELF::SHT_NULL;
40
41   virtual ~SectionBase() {}
42   virtual void finalize();
43   template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
44   virtual void writeSection(llvm::FileOutputBuffer &Out) const = 0;
45 };
46
47 class Segment {
48 private:
49   struct SectionCompare {
50     bool operator()(const SectionBase *Lhs, const SectionBase *Rhs) const {
51       // Some sections might have the same address if one of them is empty. To
52       // fix this we can use the lexicographic ordering on ->Addr and the
53       // address of the actully stored section.
54       if (Lhs->OriginalOffset == Rhs->OriginalOffset)
55         return Lhs < Rhs;
56       return Lhs->OriginalOffset < Rhs->OriginalOffset;
57     }
58   };
59
60   std::set<const SectionBase *, SectionCompare> Sections;
61   llvm::ArrayRef<uint8_t> Contents;
62
63 public:
64   uint64_t Align;
65   uint64_t FileSize;
66   uint32_t Flags;
67   uint32_t Index;
68   uint64_t MemSize;
69   uint64_t Offset;
70   uint64_t PAddr;
71   uint64_t Type;
72   uint64_t VAddr;
73
74   Segment(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
75   void finalize();
76   const SectionBase *firstSection() const {
77     if (!Sections.empty())
78       return *Sections.begin();
79     return nullptr;
80   }
81   void addSection(const SectionBase *sec) { Sections.insert(sec); }
82   template <class ELFT> void writeHeader(llvm::FileOutputBuffer &Out) const;
83   void writeSegment(llvm::FileOutputBuffer &Out) const;
84 };
85
86 class Section : public SectionBase {
87 private:
88   llvm::ArrayRef<uint8_t> Contents;
89
90 public:
91   Section(llvm::ArrayRef<uint8_t> Data) : Contents(Data) {}
92   void writeSection(llvm::FileOutputBuffer &Out) const override;
93 };
94
95 // This is just a wraper around a StringTableBuilder that implements SectionBase
96 class StringTableSection : public SectionBase {
97 private:
98   llvm::StringTableBuilder StrTabBuilder;
99
100 public:
101   StringTableSection() : StrTabBuilder(llvm::StringTableBuilder::ELF) {
102     Type = llvm::ELF::SHT_STRTAB;
103   }
104
105   void addString(llvm::StringRef Name);
106   uint32_t findIndex(llvm::StringRef Name) const;
107   void finalize() override;
108   void writeSection(llvm::FileOutputBuffer &Out) const override;
109   static bool classof(const SectionBase *S) {
110     return S->Type == llvm::ELF::SHT_STRTAB;
111   }
112 };
113
114 template <class ELFT> class Object {
115 private:
116   typedef std::unique_ptr<SectionBase> SecPtr;
117   typedef std::unique_ptr<Segment> SegPtr;
118
119   typedef typename ELFT::Shdr Elf_Shdr;
120   typedef typename ELFT::Ehdr Elf_Ehdr;
121   typedef typename ELFT::Phdr Elf_Phdr;
122
123   SecPtr makeSection(const llvm::object::ELFFile<ELFT> &ElfFile,
124                      const Elf_Shdr &Shdr);
125   void readProgramHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
126   void readSectionHeaders(const llvm::object::ELFFile<ELFT> &ElfFile);
127
128 protected:
129   StringTableSection *SectionNames;
130   std::vector<SecPtr> Sections;
131   std::vector<SegPtr> Segments;
132
133   void writeHeader(llvm::FileOutputBuffer &Out) const;
134   void writeProgramHeaders(llvm::FileOutputBuffer &Out) const;
135   void writeSectionData(llvm::FileOutputBuffer &Out) const;
136   void writeSectionHeaders(llvm::FileOutputBuffer &Out) const;
137
138 public:
139   uint8_t Ident[16];
140   uint64_t Entry;
141   uint64_t SHOffset;
142   uint32_t Type;
143   uint32_t Machine;
144   uint32_t Version;
145   uint32_t Flags;
146
147   Object(const llvm::object::ELFObjectFile<ELFT> &Obj);
148   virtual size_t totalSize() const = 0;
149   virtual void finalize() = 0;
150   virtual void write(llvm::FileOutputBuffer &Out) const = 0;
151   virtual ~Object() = default;
152 };
153
154 template <class ELFT> class ELFObject : public Object<ELFT> {
155 private:
156   typedef std::unique_ptr<SectionBase> SecPtr;
157   typedef std::unique_ptr<Segment> SegPtr;
158
159   typedef typename ELFT::Shdr Elf_Shdr;
160   typedef typename ELFT::Ehdr Elf_Ehdr;
161   typedef typename ELFT::Phdr Elf_Phdr;
162
163   void sortSections();
164   void assignOffsets();
165
166 public:
167   ELFObject(const llvm::object::ELFObjectFile<ELFT> &Obj) : Object<ELFT>(Obj) {}
168   void finalize() override;
169   size_t totalSize() const override;
170   void write(llvm::FileOutputBuffer &Out) const override;
171 };
172
173 template <class ELFT> class BinaryObject : public Object<ELFT> {
174 private:
175   typedef std::unique_ptr<SectionBase> SecPtr;
176   typedef std::unique_ptr<Segment> SegPtr;
177
178   uint64_t TotalSize;
179
180 public:
181   BinaryObject(const llvm::object::ELFObjectFile<ELFT> &Obj)
182       : Object<ELFT>(Obj) {}
183   void finalize() override;
184   size_t totalSize() const override;
185   void write(llvm::FileOutputBuffer &Out) const override;
186 };
187 #endif