[ELF][yaml2obj] Handle additional MIPS specific st_other field flags
[oota-llvm.git] / tools / yaml2obj / yaml2elf.cpp
1 //===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
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 /// \file
11 /// \brief The ELF component of yaml2obj.
12 ///
13 //===----------------------------------------------------------------------===//
14
15 #include "yaml2obj.h"
16 #include "llvm/ADT/ArrayRef.h"
17 #include "llvm/MC/StringTableBuilder.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/Object/ELFYAML.h"
20 #include "llvm/Support/ELF.h"
21 #include "llvm/Support/MemoryBuffer.h"
22 #include "llvm/Support/YAMLTraits.h"
23 #include "llvm/Support/raw_ostream.h"
24
25 using namespace llvm;
26
27 // This class is used to build up a contiguous binary blob while keeping
28 // track of an offset in the output (which notionally begins at
29 // `InitialOffset`).
30 namespace {
31 class ContiguousBlobAccumulator {
32   const uint64_t InitialOffset;
33   SmallVector<char, 128> Buf;
34   raw_svector_ostream OS;
35
36   /// \returns The new offset.
37   uint64_t padToAlignment(unsigned Align) {
38     uint64_t CurrentOffset = InitialOffset + OS.tell();
39     uint64_t AlignedOffset = RoundUpToAlignment(CurrentOffset, Align);
40     for (; CurrentOffset != AlignedOffset; ++CurrentOffset)
41       OS.write('\0');
42     return AlignedOffset; // == CurrentOffset;
43   }
44
45 public:
46   ContiguousBlobAccumulator(uint64_t InitialOffset_)
47       : InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
48   template <class Integer>
49   raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align = 16) {
50     Offset = padToAlignment(Align);
51     return OS;
52   }
53   void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
54 };
55 } // end anonymous namespace
56
57 // Used to keep track of section and symbol names, so that in the YAML file
58 // sections and symbols can be referenced by name instead of by index.
59 namespace {
60 class NameToIdxMap {
61   StringMap<int> Map;
62 public:
63   /// \returns true if name is already present in the map.
64   bool addName(StringRef Name, unsigned i) {
65     StringMapEntry<int> &Entry = Map.GetOrCreateValue(Name, -1);
66     if (Entry.getValue() != -1)
67       return true;
68     Entry.setValue((int)i);
69     return false;
70   }
71   /// \returns true if name is not present in the map
72   bool lookup(StringRef Name, unsigned &Idx) const {
73     StringMap<int>::const_iterator I = Map.find(Name);
74     if (I == Map.end())
75       return true;
76     Idx = I->getValue();
77     return false;
78   }
79 };
80 } // end anonymous namespace
81
82 template <class T>
83 static size_t arrayDataSize(ArrayRef<T> A) {
84   return A.size() * sizeof(T);
85 }
86
87 template <class T>
88 static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
89   OS.write((const char *)A.data(), arrayDataSize(A));
90 }
91
92 template <class T>
93 static void zero(T &Obj) {
94   memset(&Obj, 0, sizeof(Obj));
95 }
96
97 namespace {
98 /// \brief "Single point of truth" for the ELF file construction.
99 /// TODO: This class still has a ways to go before it is truly a "single
100 /// point of truth".
101 template <class ELFT>
102 class ELFState {
103   typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
104   typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
105   typedef typename object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
106   typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
107   typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
108
109   /// \brief The future ".strtab" section.
110   StringTableBuilder DotStrtab;
111
112   /// \brief The future ".shstrtab" section.
113   StringTableBuilder DotShStrtab;
114
115   NameToIdxMap SN2I;
116   NameToIdxMap SymN2I;
117   const ELFYAML::Object &Doc;
118
119   bool buildSectionIndex();
120   bool buildSymbolIndex(std::size_t &StartIndex,
121                         const std::vector<ELFYAML::Symbol> &Symbols);
122   void initELFHeader(Elf_Ehdr &Header);
123   bool initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
124                           ContiguousBlobAccumulator &CBA);
125   void initSymtabSectionHeader(Elf_Shdr &SHeader,
126                                ContiguousBlobAccumulator &CBA);
127   void initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
128                                StringTableBuilder &STB,
129                                ContiguousBlobAccumulator &CBA);
130   void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
131                   std::vector<Elf_Sym> &Syms, unsigned SymbolBinding);
132   void writeSectionContent(Elf_Shdr &SHeader,
133                            const ELFYAML::RawContentSection &Section,
134                            ContiguousBlobAccumulator &CBA);
135   bool writeSectionContent(Elf_Shdr &SHeader,
136                            const ELFYAML::RelocationSection &Section,
137                            ContiguousBlobAccumulator &CBA);
138
139   // - SHT_NULL entry (placed first, i.e. 0'th entry)
140   // - symbol table (.symtab) (placed third to last)
141   // - string table (.strtab) (placed second to last)
142   // - section header string table (.shstrtab) (placed last)
143   unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; }
144   unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; }
145   unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; }
146   unsigned getSectionCount() const { return Doc.Sections.size() + 4; }
147
148   ELFState(const ELFYAML::Object &D) : Doc(D) {}
149
150 public:
151   static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
152 };
153 } // end anonymous namespace
154
155 template <class ELFT>
156 void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
157   using namespace llvm::ELF;
158   zero(Header);
159   Header.e_ident[EI_MAG0] = 0x7f;
160   Header.e_ident[EI_MAG1] = 'E';
161   Header.e_ident[EI_MAG2] = 'L';
162   Header.e_ident[EI_MAG3] = 'F';
163   Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
164   bool IsLittleEndian = ELFT::TargetEndianness == support::little;
165   Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
166   Header.e_ident[EI_VERSION] = EV_CURRENT;
167   Header.e_ident[EI_OSABI] = Doc.Header.OSABI;
168   Header.e_ident[EI_ABIVERSION] = 0;
169   Header.e_type = Doc.Header.Type;
170   Header.e_machine = Doc.Header.Machine;
171   Header.e_version = EV_CURRENT;
172   Header.e_entry = Doc.Header.Entry;
173   Header.e_flags = Doc.Header.Flags;
174   Header.e_ehsize = sizeof(Elf_Ehdr);
175   Header.e_shentsize = sizeof(Elf_Shdr);
176   // Immediately following the ELF header.
177   Header.e_shoff = sizeof(Header);
178   Header.e_shnum = getSectionCount();
179   Header.e_shstrndx = getDotShStrTabSecNo();
180 }
181
182 template <class ELFT>
183 bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
184                                         ContiguousBlobAccumulator &CBA) {
185   // Ensure SHN_UNDEF entry is present. An all-zero section header is a
186   // valid SHN_UNDEF entry since SHT_NULL == 0.
187   Elf_Shdr SHeader;
188   zero(SHeader);
189   SHeaders.push_back(SHeader);
190
191   for (const auto &Sec : Doc.Sections)
192     DotShStrtab.add(Sec->Name);
193   DotShStrtab.finalize(StringTableBuilder::ELF);
194
195   for (const auto &Sec : Doc.Sections) {
196     zero(SHeader);
197     SHeader.sh_name = DotShStrtab.getOffset(Sec->Name);
198     SHeader.sh_type = Sec->Type;
199     SHeader.sh_flags = Sec->Flags;
200     SHeader.sh_addr = Sec->Address;
201     SHeader.sh_addralign = Sec->AddressAlign;
202
203     if (!Sec->Link.empty()) {
204       unsigned Index;
205       if (SN2I.lookup(Sec->Link, Index)) {
206         errs() << "error: Unknown section referenced: '" << Sec->Link
207                << "' at YAML section '" << Sec->Name << "'.\n";
208         return false;
209       }
210       SHeader.sh_link = Index;
211     }
212
213     if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec.get()))
214       writeSectionContent(SHeader, *S, CBA);
215     else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec.get())) {
216       if (S->Link.empty())
217         // For relocation section set link to .symtab by default.
218         SHeader.sh_link = getDotSymTabSecNo();
219
220       unsigned Index;
221       if (SN2I.lookup(S->Info, Index)) {
222         errs() << "error: Unknown section referenced: '" << S->Info
223                << "' at YAML section '" << S->Name << "'.\n";
224         return false;
225       }
226       SHeader.sh_info = Index;
227
228       if (!writeSectionContent(SHeader, *S, CBA))
229         return false;
230     } else
231       llvm_unreachable("Unknown section type");
232
233     SHeaders.push_back(SHeader);
234   }
235   return true;
236 }
237
238 template <class ELFT>
239 void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
240                                              ContiguousBlobAccumulator &CBA) {
241   zero(SHeader);
242   SHeader.sh_name = DotShStrtab.getOffset(".symtab");
243   SHeader.sh_type = ELF::SHT_SYMTAB;
244   SHeader.sh_link = getDotStrTabSecNo();
245   // One greater than symbol table index of the last local symbol.
246   SHeader.sh_info = Doc.Symbols.Local.size() + 1;
247   SHeader.sh_entsize = sizeof(Elf_Sym);
248
249   std::vector<Elf_Sym> Syms;
250   {
251     // Ensure STN_UNDEF is present
252     Elf_Sym Sym;
253     zero(Sym);
254     Syms.push_back(Sym);
255   }
256
257   // Add symbol names to .strtab.
258   for (const auto &Sym : Doc.Symbols.Local)
259     DotStrtab.add(Sym.Name);
260   for (const auto &Sym : Doc.Symbols.Global)
261     DotStrtab.add(Sym.Name);
262   for (const auto &Sym : Doc.Symbols.Weak)
263     DotStrtab.add(Sym.Name);
264   DotStrtab.finalize(StringTableBuilder::ELF);
265
266   addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
267   addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
268   addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
269
270   writeArrayData(CBA.getOSAndAlignedOffset(SHeader.sh_offset),
271                  makeArrayRef(Syms));
272   SHeader.sh_size = arrayDataSize(makeArrayRef(Syms));
273 }
274
275 template <class ELFT>
276 void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
277                                              StringTableBuilder &STB,
278                                              ContiguousBlobAccumulator &CBA) {
279   zero(SHeader);
280   SHeader.sh_name = DotShStrtab.getOffset(Name);
281   SHeader.sh_type = ELF::SHT_STRTAB;
282   CBA.getOSAndAlignedOffset(SHeader.sh_offset) << STB.data();
283   SHeader.sh_size = STB.data().size();
284   SHeader.sh_addralign = 1;
285 }
286
287 template <class ELFT>
288 void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
289                                 std::vector<Elf_Sym> &Syms,
290                                 unsigned SymbolBinding) {
291   for (const auto &Sym : Symbols) {
292     Elf_Sym Symbol;
293     zero(Symbol);
294     if (!Sym.Name.empty())
295       Symbol.st_name = DotStrtab.getOffset(Sym.Name);
296     Symbol.setBindingAndType(SymbolBinding, Sym.Type);
297     if (!Sym.Section.empty()) {
298       unsigned Index;
299       if (SN2I.lookup(Sym.Section, Index)) {
300         errs() << "error: Unknown section referenced: '" << Sym.Section
301                << "' by YAML symbol " << Sym.Name << ".\n";
302         exit(1);
303       }
304       Symbol.st_shndx = Index;
305     } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
306     Symbol.st_value = Sym.Value;
307     Symbol.st_other = Sym.Other;
308     Symbol.st_size = Sym.Size;
309     Syms.push_back(Symbol);
310   }
311 }
312
313 template <class ELFT>
314 void
315 ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
316                                     const ELFYAML::RawContentSection &Section,
317                                     ContiguousBlobAccumulator &CBA) {
318   assert(Section.Size >= Section.Content.binary_size() &&
319          "Section size and section content are inconsistent");
320   raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
321   Section.Content.writeAsBinary(OS);
322   for (auto i = Section.Content.binary_size(); i < Section.Size; ++i)
323     OS.write(0);
324   SHeader.sh_entsize = 0;
325   SHeader.sh_size = Section.Size;
326 }
327
328 template <class ELFT>
329 bool
330 ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
331                                     const ELFYAML::RelocationSection &Section,
332                                     ContiguousBlobAccumulator &CBA) {
333   if (Section.Type != llvm::ELF::SHT_REL &&
334       Section.Type != llvm::ELF::SHT_RELA) {
335     errs() << "error: Invalid relocation section type.\n";
336     return false;
337   }
338
339   bool IsRela = Section.Type == llvm::ELF::SHT_RELA;
340   SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
341   SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size();
342
343   auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset);
344
345   for (const auto &Rel : Section.Relocations) {
346     unsigned SymIdx;
347     if (SymN2I.lookup(Rel.Symbol, SymIdx)) {
348       errs() << "error: Unknown symbol referenced: '" << Rel.Symbol
349              << "' at YAML relocation.\n";
350       return false;
351     }
352
353     if (IsRela) {
354       Elf_Rela REntry;
355       zero(REntry);
356       REntry.r_offset = Rel.Offset;
357       REntry.r_addend = Rel.Addend;
358       REntry.setSymbolAndType(SymIdx, Rel.Type);
359       OS.write((const char *)&REntry, sizeof(REntry));
360     } else {
361       Elf_Rel REntry;
362       zero(REntry);
363       REntry.r_offset = Rel.Offset;
364       REntry.setSymbolAndType(SymIdx, Rel.Type);
365       OS.write((const char *)&REntry, sizeof(REntry));
366     }
367   }
368   return true;
369 }
370
371 template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
372   SN2I.addName(".symtab", getDotSymTabSecNo());
373   SN2I.addName(".strtab", getDotStrTabSecNo());
374   SN2I.addName(".shstrtab", getDotShStrTabSecNo());
375
376   for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
377     StringRef Name = Doc.Sections[i]->Name;
378     if (Name.empty())
379       continue;
380     // "+ 1" to take into account the SHT_NULL entry.
381     if (SN2I.addName(Name, i + 1)) {
382       errs() << "error: Repeated section name: '" << Name
383              << "' at YAML section number " << i << ".\n";
384       return false;
385     }
386   }
387   return true;
388 }
389
390 template <class ELFT>
391 bool
392 ELFState<ELFT>::buildSymbolIndex(std::size_t &StartIndex,
393                                  const std::vector<ELFYAML::Symbol> &Symbols) {
394   for (const auto &Sym : Symbols) {
395     ++StartIndex;
396     if (Sym.Name.empty())
397       continue;
398     if (SymN2I.addName(Sym.Name, StartIndex)) {
399       errs() << "error: Repeated symbol name: '" << Sym.Name << "'.\n";
400       return false;
401     }
402   }
403   return true;
404 }
405
406 template <class ELFT>
407 int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
408   ELFState<ELFT> State(Doc);
409   if (!State.buildSectionIndex())
410     return 1;
411
412   std::size_t StartSymIndex = 0;
413   if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) ||
414       !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) ||
415       !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak))
416     return 1;
417
418   Elf_Ehdr Header;
419   State.initELFHeader(Header);
420
421   // TODO: Flesh out section header support.
422   // TODO: Program headers.
423
424   // XXX: This offset is tightly coupled with the order that we write
425   // things to `OS`.
426   const size_t SectionContentBeginOffset =
427       Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
428   ContiguousBlobAccumulator CBA(SectionContentBeginOffset);
429
430   // Doc might not contain .symtab, .strtab and .shstrtab sections,
431   // but we will emit them, so make sure to add them to ShStrTabSHeader.
432   State.DotShStrtab.add(".symtab");
433   State.DotShStrtab.add(".strtab");
434   State.DotShStrtab.add(".shstrtab");
435
436   std::vector<Elf_Shdr> SHeaders;
437   if(!State.initSectionHeaders(SHeaders, CBA))
438     return 1;
439
440   // .symtab section.
441   Elf_Shdr SymtabSHeader;
442   State.initSymtabSectionHeader(SymtabSHeader, CBA);
443   SHeaders.push_back(SymtabSHeader);
444
445   // .strtab string table header.
446   Elf_Shdr DotStrTabSHeader;
447   State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab,
448                                 CBA);
449   SHeaders.push_back(DotStrTabSHeader);
450
451   // .shstrtab string table header.
452   Elf_Shdr ShStrTabSHeader;
453   State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab,
454                                 CBA);
455   SHeaders.push_back(ShStrTabSHeader);
456
457   OS.write((const char *)&Header, sizeof(Header));
458   writeArrayData(OS, makeArrayRef(SHeaders));
459   CBA.writeBlobToStream(OS);
460   return 0;
461 }
462
463 static bool is64Bit(const ELFYAML::Object &Doc) {
464   return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
465 }
466
467 static bool isLittleEndian(const ELFYAML::Object &Doc) {
468   return Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
469 }
470
471 int yaml2elf(yaml::Input &YIn, raw_ostream &Out) {
472   ELFYAML::Object Doc;
473   YIn >> Doc;
474   if (YIn.error()) {
475     errs() << "yaml2obj: Failed to parse YAML file!\n";
476     return 1;
477   }
478   using object::ELFType;
479   typedef ELFType<support::little, 8, true> LE64;
480   typedef ELFType<support::big, 8, true> BE64;
481   typedef ELFType<support::little, 4, false> LE32;
482   typedef ELFType<support::big, 4, false> BE32;
483   if (is64Bit(Doc)) {
484     if (isLittleEndian(Doc))
485       return ELFState<LE64>::writeELF(Out, Doc);
486     else
487       return ELFState<BE64>::writeELF(Out, Doc);
488   } else {
489     if (isLittleEndian(Doc))
490       return ELFState<LE32>::writeELF(Out, Doc);
491     else
492       return ELFState<BE32>::writeELF(Out, Doc);
493   }
494 }