yaml2elf.cpp revision 58495694c09540459e4eea50eef2dcffc705f3c3
15918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
25918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//
35918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//                     The LLVM Compiler Infrastructure
45918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//
55918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva// This file is distributed under the University of Illinois Open Source
65918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva// License. See LICENSE.TXT for details.
75918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//
85918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//===----------------------------------------------------------------------===//
95918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva///
105918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva/// \file
115918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva/// \brief The ELF component of yaml2obj.
125918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva///
135918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva//===----------------------------------------------------------------------===//
145918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva
155918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "yaml2obj.h"
165918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "llvm/Object/ELF.h"
175918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "llvm/Object/ELFYAML.h"
185918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "llvm/Support/ELF.h"
195918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "llvm/Support/MemoryBuffer.h"
205918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "llvm/Support/YAMLTraits.h"
215918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva#include "llvm/Support/raw_ostream.h"
225918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva
235918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silvausing namespace llvm;
245918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva
25274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// There is similar code in yaml2coff, but with some slight COFF-specific
26274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// variations like different initial state. Might be able to deduplicate
27274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// some day, but also want to make sure that the Mach-O use case is served.
28274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva//
29274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// This class has a deliberately small interface, since a lot of
30274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// implementation variation is possible.
31274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva//
32274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// TODO: Use an ordered container with a suffix-based comparison in order
33274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// to deduplicate suffixes. std::map<> with a custom comparator is likely
34274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// to be the simplest implementation, but a suffix trie could be more
35274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva// suitable for the job.
36f3f3523b9c714d9b98f6102ce79ed3d0c9050169Sean Silvanamespace {
37274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvaclass StringTableBuilder {
38274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  /// \brief Indices of strings currently present in `Buf`.
39274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  StringMap<unsigned> StringIndices;
40274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  /// \brief The contents of the string table as we build it.
41274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  std::string Buf;
42274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvapublic:
43274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  StringTableBuilder() {
44274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    Buf.push_back('\0');
45274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  }
46274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  /// \returns Index of string in string table.
47274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  unsigned addString(StringRef S) {
48274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    StringMapEntry<unsigned> &Entry = StringIndices.GetOrCreateValue(S);
49274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    unsigned &I = Entry.getValue();
50274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    if (I != 0)
51274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva      return I;
52274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    I = Buf.size();
53274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    Buf.append(S.begin(), S.end());
54274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    Buf.push_back('\0');
55274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    return I;
56274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  }
57274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  size_t size() const {
58274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    return Buf.size();
59274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  }
60274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  void writeToStream(raw_ostream &OS) {
61274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    OS.write(Buf.data(), Buf.size());
62274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  }
63274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva};
64f3f3523b9c714d9b98f6102ce79ed3d0c9050169Sean Silva} // end anonymous namespace
65274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
662a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva// This class is used to build up a contiguous binary blob while keeping
672a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva// track of an offset in the output (which notionally begins at
682a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva// `InitialOffset`).
69f3f3523b9c714d9b98f6102ce79ed3d0c9050169Sean Silvanamespace {
702a7e79a30f87be4103963e6049a2f1cf171f502cSean Silvaclass ContiguousBlobAccumulator {
712a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva  const uint64_t InitialOffset;
72b14f972ed6865a978402fb1c788ee7939b58680dSean Silva  SmallVector<char, 128> Buf;
732a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva  raw_svector_ostream OS;
742a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva
75e766884193afeb684fe1e14f74c316405e9d801fSean Silva  /// \returns The new offset.
76e766884193afeb684fe1e14f74c316405e9d801fSean Silva  uint64_t padToAlignment(unsigned Align) {
77e766884193afeb684fe1e14f74c316405e9d801fSean Silva    uint64_t CurrentOffset = InitialOffset + OS.tell();
78e766884193afeb684fe1e14f74c316405e9d801fSean Silva    uint64_t AlignedOffset = RoundUpToAlignment(CurrentOffset, Align);
79e766884193afeb684fe1e14f74c316405e9d801fSean Silva    for (; CurrentOffset != AlignedOffset; ++CurrentOffset)
80e766884193afeb684fe1e14f74c316405e9d801fSean Silva      OS.write('\0');
81e766884193afeb684fe1e14f74c316405e9d801fSean Silva    return AlignedOffset; // == CurrentOffset;
82e766884193afeb684fe1e14f74c316405e9d801fSean Silva  }
83e766884193afeb684fe1e14f74c316405e9d801fSean Silva
842a7e79a30f87be4103963e6049a2f1cf171f502cSean Silvapublic:
85b14f972ed6865a978402fb1c788ee7939b58680dSean Silva  ContiguousBlobAccumulator(uint64_t InitialOffset_)
86b14f972ed6865a978402fb1c788ee7939b58680dSean Silva      : InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
87e766884193afeb684fe1e14f74c316405e9d801fSean Silva  template <class Integer>
88e766884193afeb684fe1e14f74c316405e9d801fSean Silva  raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align = 16) {
89e766884193afeb684fe1e14f74c316405e9d801fSean Silva    Offset = padToAlignment(Align);
90e766884193afeb684fe1e14f74c316405e9d801fSean Silva    return OS;
91e766884193afeb684fe1e14f74c316405e9d801fSean Silva  }
922a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva  void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
932a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva};
94f3f3523b9c714d9b98f6102ce79ed3d0c9050169Sean Silva} // end anonymous namespace
952a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva
96fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva// Used to keep track of section names, so that in the YAML file sections
97fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva// can be referenced by name instead of by index.
98f3f3523b9c714d9b98f6102ce79ed3d0c9050169Sean Silvanamespace {
99fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silvaclass SectionNameToIdxMap {
100fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  StringMap<int> Map;
101fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silvapublic:
102fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  /// \returns true if name is already present in the map.
103fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  bool addName(StringRef SecName, unsigned i) {
104fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    StringMapEntry<int> &Entry = Map.GetOrCreateValue(SecName, -1);
105fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    if (Entry.getValue() != -1)
106fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      return true;
107fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    Entry.setValue((int)i);
108fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    return false;
109fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  }
110fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  /// \returns true if name is not present in the map
111fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  bool lookupSection(StringRef SecName, unsigned &Idx) const {
112fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    StringMap<int>::const_iterator I = Map.find(SecName);
113fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    if (I == Map.end())
114fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      return true;
115fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    Idx = I->getValue();
116fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    return false;
117fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  }
118fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva};
119f3f3523b9c714d9b98f6102ce79ed3d0c9050169Sean Silva} // end anonymous namespace
120fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva
121274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvatemplate <class T>
122274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvastatic size_t vectorDataSize(const std::vector<T> &Vec) {
123274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  return Vec.size() * sizeof(T);
124274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva}
125274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
126274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvatemplate <class T>
127274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvastatic void writeVectorData(raw_ostream &OS, const std::vector<T> &Vec) {
128274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  OS.write((const char *)Vec.data(), vectorDataSize(Vec));
129274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva}
130274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
131274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvatemplate <class T>
132274264ce2ba93d26702f7ebfe6aea121df44113fSean Silvastatic void zero(T &Obj) {
133274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  memset(&Obj, 0, sizeof(Obj));
134274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva}
135274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
136c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva/// \brief Create a string table in `SHeader`, which we assume is already
137c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva/// zero'd.
138c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silvatemplate <class Elf_Shdr>
139c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silvastatic void createStringTableSectionHeader(Elf_Shdr &SHeader,
140c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva                                           StringTableBuilder &STB,
141c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva                                           ContiguousBlobAccumulator &CBA) {
142c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva  SHeader.sh_type = ELF::SHT_STRTAB;
143e766884193afeb684fe1e14f74c316405e9d801fSean Silva  STB.writeToStream(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
144c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva  SHeader.sh_size = STB.size();
145c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva  SHeader.sh_addralign = 1;
146c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva}
147c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva
1480382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silvanamespace {
1490382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva/// \brief "Single point of truth" for the ELF file construction.
1500382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva/// TODO: This class still has a ways to go before it is truly a "single
1510382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva/// point of truth".
1520382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silvatemplate <class ELFT>
1530382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silvaclass ELFState {
1540382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  /// \brief The future ".strtab" section.
1550382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  StringTableBuilder DotStrtab;
1560382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  /// \brief The section number of the ".strtab" section.
1570382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  unsigned DotStrtabSecNo;
1580382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  /// \brief The accumulated contents of all sections so far.
1590382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  ContiguousBlobAccumulator &SectionContentAccum;
1600382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  typedef typename object::ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
1610382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  /// \brief The ELF file header.
1620382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  Elf_Ehdr &Header;
1630382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva
164c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva  SectionNameToIdxMap &SN2I;
165c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva
1660382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silvapublic:
1670382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva
1680382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  ELFState(Elf_Ehdr &Header_, ContiguousBlobAccumulator &Accum,
169c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva           unsigned DotStrtabSecNo_, SectionNameToIdxMap &SN2I_)
1700382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva      : DotStrtab(), DotStrtabSecNo(DotStrtabSecNo_),
171c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva        SectionContentAccum(Accum), Header(Header_), SN2I(SN2I_) {}
1720382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva
1730382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  unsigned getDotStrTabSecNo() const { return DotStrtabSecNo; }
1740382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  StringTableBuilder &getStringTable() { return DotStrtab; }
1750382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  ContiguousBlobAccumulator &getSectionContentAccum() {
1760382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva    return SectionContentAccum;
1770382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  }
178c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva  SectionNameToIdxMap &getSN2I() { return SN2I; }
1790382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva};
1800382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva} // end anonymous namespace
1810382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva
1824235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva// FIXME: At this point it is fairly clear that we need to refactor these
1834235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva// static functions into methods of a class sharing some typedefs. These
1844235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva// ELF type names are insane.
185552d7cd31a0f6eb0e1434981196f477ae741a184Sean Silvatemplate <class ELFT>
186552d7cd31a0f6eb0e1434981196f477ae741a184Sean Silvastatic void
187552d7cd31a0f6eb0e1434981196f477ae741a184Sean SilvaaddSymbols(const std::vector<ELFYAML::Symbol> &Symbols, ELFState<ELFT> &State,
188552d7cd31a0f6eb0e1434981196f477ae741a184Sean Silva           std::vector<typename object::ELFObjectFile<ELFT>::Elf_Sym> &Syms,
189552d7cd31a0f6eb0e1434981196f477ae741a184Sean Silva           unsigned SymbolBinding) {
190552d7cd31a0f6eb0e1434981196f477ae741a184Sean Silva  typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
1914235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  for (unsigned i = 0, e = Symbols.size(); i != e; ++i) {
1924235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    const ELFYAML::Symbol &Sym = Symbols[i];
1934235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    Elf_Sym Symbol;
1944235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    zero(Symbol);
1954235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    if (!Sym.Name.empty())
1964235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva      Symbol.st_name = State.getStringTable().addString(Sym.Name);
1974235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    Symbol.setBindingAndType(SymbolBinding, Sym.Type);
198326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva    if (!Sym.Section.empty()) {
199326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva      unsigned Index;
200326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva      if (State.getSN2I().lookupSection(Sym.Section, Index)) {
201326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva        errs() << "error: Unknown section referenced: '" << Sym.Section
202326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva               << "' by YAML symbol " << Sym.Name << ".\n";
203326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva        exit(1);
204326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva      }
205326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva      Symbol.st_shndx = Index;
206326c193e0aa221c7836adfa16a3ec85857d7d8b7Sean Silva    } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
2074235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    Symbol.st_value = Sym.Value;
2084235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    Symbol.st_size = Sym.Size;
2094235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva    Syms.push_back(Symbol);
2104235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  }
2114235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva}
2124235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva
213afcf60fe15999ea07193118f447a34f41171e433Sean Silvatemplate <class ELFT>
214afcf60fe15999ea07193118f447a34f41171e433Sean Silvastatic void handleSymtabSectionHeader(
2150382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva    const ELFYAML::Section &Sec, ELFState<ELFT> &State,
2160382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva    typename object::ELFObjectFile<ELFT>::Elf_Shdr &SHeader) {
217afcf60fe15999ea07193118f447a34f41171e433Sean Silva
218afcf60fe15999ea07193118f447a34f41171e433Sean Silva  typedef typename object::ELFObjectFile<ELFT>::Elf_Sym Elf_Sym;
219afcf60fe15999ea07193118f447a34f41171e433Sean Silva  // TODO: Ensure that a manually specified `Link` field is diagnosed as an
220afcf60fe15999ea07193118f447a34f41171e433Sean Silva  // error for SHT_SYMTAB.
2210382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  SHeader.sh_link = State.getDotStrTabSecNo();
2224235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  // One greater than symbol table index of the last local symbol.
2234235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  SHeader.sh_info = Sec.Symbols.Local.size() + 1;
224afcf60fe15999ea07193118f447a34f41171e433Sean Silva  SHeader.sh_entsize = sizeof(Elf_Sym);
225afcf60fe15999ea07193118f447a34f41171e433Sean Silva
226afcf60fe15999ea07193118f447a34f41171e433Sean Silva  std::vector<Elf_Sym> Syms;
227ca0170ffa1ba6d53f0008b345cb5ac777e81c3b1Sean Silva  {
228ca0170ffa1ba6d53f0008b345cb5ac777e81c3b1Sean Silva    // Ensure STN_UNDEF is present
229ca0170ffa1ba6d53f0008b345cb5ac777e81c3b1Sean Silva    Elf_Sym Sym;
230ca0170ffa1ba6d53f0008b345cb5ac777e81c3b1Sean Silva    zero(Sym);
231ca0170ffa1ba6d53f0008b345cb5ac777e81c3b1Sean Silva    Syms.push_back(Sym);
232ca0170ffa1ba6d53f0008b345cb5ac777e81c3b1Sean Silva  }
2334235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  addSymbols(Sec.Symbols.Local, State, Syms, ELF::STB_LOCAL);
2344235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  addSymbols(Sec.Symbols.Global, State, Syms, ELF::STB_GLOBAL);
2354235ba32f2610ee2ed1e0c4bfca5c67835e9f97dSean Silva  addSymbols(Sec.Symbols.Weak, State, Syms, ELF::STB_WEAK);
236afcf60fe15999ea07193118f447a34f41171e433Sean Silva
2370382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  ContiguousBlobAccumulator &CBA = State.getSectionContentAccum();
238e766884193afeb684fe1e14f74c316405e9d801fSean Silva  writeVectorData(CBA.getOSAndAlignedOffset(SHeader.sh_offset), Syms);
239afcf60fe15999ea07193118f447a34f41171e433Sean Silva  SHeader.sh_size = vectorDataSize(Syms);
240afcf60fe15999ea07193118f447a34f41171e433Sean Silva}
241afcf60fe15999ea07193118f447a34f41171e433Sean Silva
2425918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silvatemplate <class ELFT>
2434b548ecb012ce27feff9f58aad27775df679b159Sean Silvastatic int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
2445918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  using namespace llvm::ELF;
245e1e1bb1b362b81bd8ff2037efbeda11bf3f73787Sean Silva  typedef typename object::ELFObjectFile<ELFT>::Elf_Ehdr Elf_Ehdr;
246e1e1bb1b362b81bd8ff2037efbeda11bf3f73787Sean Silva  typedef typename object::ELFObjectFile<ELFT>::Elf_Shdr Elf_Shdr;
247274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
248274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  const ELFYAML::FileHeader &Hdr = Doc.Header;
249274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
250274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  Elf_Ehdr Header;
251274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  zero(Header);
2525918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_MAG0] = 0x7f;
2535918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_MAG1] = 'E';
2545918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_MAG2] = 'L';
2555918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_MAG3] = 'F';
2565918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
2575918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  bool IsLittleEndian = ELFT::TargetEndianness == support::little;
2585918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
2595918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_VERSION] = EV_CURRENT;
26083bc34561bcf9eaccd5fc1e25f6be7397d4ae4ecSean Silva  Header.e_ident[EI_OSABI] = Hdr.OSABI;
2615918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_ident[EI_ABIVERSION] = 0;
2625918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_type = Hdr.Type;
2635918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_machine = Hdr.Machine;
2645918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_version = EV_CURRENT;
2655918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  Header.e_entry = Hdr.Entry;
266274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  Header.e_ehsize = sizeof(Elf_Ehdr);
267274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
268274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  // TODO: Flesh out section header support.
269274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  // TODO: Program headers.
270274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
271274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  Header.e_shentsize = sizeof(Elf_Shdr);
272274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  // Immediately following the ELF header.
273274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  Header.e_shoff = sizeof(Header);
274c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  const std::vector<ELFYAML::Section> &Sections = Doc.Sections;
275c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  // "+ 3" for
276c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  // - SHT_NULL entry (placed first, i.e. 0'th entry)
277c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  // - string table (.strtab) (placed second to last)
278c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  // - section header string table. (placed last)
279c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  Header.e_shnum = Sections.size() + 3;
280274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  // Place section header string table last.
281c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  Header.e_shstrndx = Header.e_shnum - 1;
282c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  const unsigned DotStrtabSecNo = Header.e_shnum - 2;
283274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva
2840382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  // XXX: This offset is tightly coupled with the order that we write
2850382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  // things to `OS`.
2860382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  const size_t SectionContentBeginOffset =
2870382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva      Header.e_ehsize + Header.e_shentsize * Header.e_shnum;
2880382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  ContiguousBlobAccumulator CBA(SectionContentBeginOffset);
289fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  SectionNameToIdxMap SN2I;
290fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
291fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    StringRef Name = Sections[i].Name;
292fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    if (Name.empty())
293fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      continue;
294c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    // "+ 1" to take into account the SHT_NULL entry.
295c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    if (SN2I.addName(Name, i + 1)) {
296fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      errs() << "error: Repeated section name: '" << Name
297fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva             << "' at YAML section number " << i << ".\n";
2984b548ecb012ce27feff9f58aad27775df679b159Sean Silva      return 1;
299fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    }
300fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva  }
301fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva
302c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva  ELFState<ELFT> State(Header, CBA, DotStrtabSecNo, SN2I);
303c18f66e70dea8abc8c9d86d40088fc8fc8247b20Sean Silva
3047dc89c1f3ab870e5f517aa201d98befd6249ed5fSean Silva  StringTableBuilder SHStrTab;
305274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  std::vector<Elf_Shdr> SHeaders;
306c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  {
307c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    // Ensure SHN_UNDEF entry is present. An all-zero section header is a
308c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    // valid SHN_UNDEF entry since SHT_NULL == 0.
309c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    Elf_Shdr SHdr;
310c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    zero(SHdr);
311c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva    SHeaders.push_back(SHdr);
312c2b6adff3e94f8e299caa31947ad970096377e40Sean Silva  }
313274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  for (unsigned i = 0, e = Sections.size(); i != e; ++i) {
314274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    const ELFYAML::Section &Sec = Sections[i];
315274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    Elf_Shdr SHeader;
316274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    zero(SHeader);
3177dc89c1f3ab870e5f517aa201d98befd6249ed5fSean Silva    SHeader.sh_name = SHStrTab.addString(Sec.Name);
318274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    SHeader.sh_type = Sec.Type;
319274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    SHeader.sh_flags = Sec.Flags;
32045b812d1a79f3f8642821e65a25d92e3d741a095Sean Silva    SHeader.sh_addr = Sec.Address;
3212a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva
322e766884193afeb684fe1e14f74c316405e9d801fSean Silva    Sec.Content.writeAsBinary(CBA.getOSAndAlignedOffset(SHeader.sh_offset));
3232a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva    SHeader.sh_size = Sec.Content.binary_size();
3242a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva
325fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    if (!Sec.Link.empty()) {
326fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      unsigned Index;
327fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      if (SN2I.lookupSection(Sec.Link, Index)) {
328fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva        errs() << "error: Unknown section referenced: '" << Sec.Link
329fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva               << "' at YAML section number " << i << ".\n";
3304b548ecb012ce27feff9f58aad27775df679b159Sean Silva        return 1;
331fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      }
332fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva      SHeader.sh_link = Index;
333fe57e347a57d643bbbcc9c19c8267a3e8c06b5a6Sean Silva    }
334274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    SHeader.sh_info = 0;
33597d37e818153c6c5f844ddebaab26be324dbe41cSean Silva    SHeader.sh_addralign = Sec.AddressAlign;
336274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    SHeader.sh_entsize = 0;
3370382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva    // XXX: Really ugly right now. Should not be writing to `CBA` above
3380382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva    // (and setting sh_offset and sh_size) when going through this branch
3390382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva    // here.
340afcf60fe15999ea07193118f447a34f41171e433Sean Silva    if (Sec.Type == ELFYAML::ELF_SHT(SHT_SYMTAB))
3410382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva      handleSymtabSectionHeader<ELFT>(Sec, State, SHeader);
342274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva    SHeaders.push_back(SHeader);
343274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  }
3445918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva
345afcf60fe15999ea07193118f447a34f41171e433Sean Silva  // .strtab string table header.
346a7bd8549fdcb18c686bdadf46000452c927d3b5dSean Silva  Elf_Shdr DotStrTabSHeader;
347a7bd8549fdcb18c686bdadf46000452c927d3b5dSean Silva  zero(DotStrTabSHeader);
348a7bd8549fdcb18c686bdadf46000452c927d3b5dSean Silva  DotStrTabSHeader.sh_name = SHStrTab.addString(StringRef(".strtab"));
3490382b30eb5ecdde9749841a2f39960ab8e2de87cSean Silva  createStringTableSectionHeader(DotStrTabSHeader, State.getStringTable(), CBA);
35058495694c09540459e4eea50eef2dcffc705f3c3Sean Silva  SHeaders.push_back(DotStrTabSHeader);
351a7bd8549fdcb18c686bdadf46000452c927d3b5dSean Silva
3527dc89c1f3ab870e5f517aa201d98befd6249ed5fSean Silva  // Section header string table header.
3537dc89c1f3ab870e5f517aa201d98befd6249ed5fSean Silva  Elf_Shdr SHStrTabSHeader;
3547dc89c1f3ab870e5f517aa201d98befd6249ed5fSean Silva  zero(SHStrTabSHeader);
355c60c86dcaee929840ac5ad16d1adffa20ba46494Sean Silva  createStringTableSectionHeader(SHStrTabSHeader, SHStrTab, CBA);
35658495694c09540459e4eea50eef2dcffc705f3c3Sean Silva  SHeaders.push_back(SHStrTabSHeader);
3575918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva
3585918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  OS.write((const char *)&Header, sizeof(Header));
359274264ce2ba93d26702f7ebfe6aea121df44113fSean Silva  writeVectorData(OS, SHeaders);
3602a7e79a30f87be4103963e6049a2f1cf171f502cSean Silva  CBA.writeBlobToStream(OS);
3614b548ecb012ce27feff9f58aad27775df679b159Sean Silva  return 0;
3625918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva}
3635918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva
364efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silvastatic bool is64Bit(const ELFYAML::Object &Doc) {
365efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
366efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva}
367efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva
368efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silvastatic bool isLittleEndian(const ELFYAML::Object &Doc) {
369efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  return Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
370efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva}
371efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva
3725918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silvaint yaml2elf(llvm::raw_ostream &Out, llvm::MemoryBuffer *Buf) {
3735918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  yaml::Input YIn(Buf->getBuffer());
3745918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  ELFYAML::Object Doc;
3755918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  YIn >> Doc;
3765918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  if (YIn.error()) {
3775918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva    errs() << "yaml2obj: Failed to parse YAML file!\n";
3785918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva    return 1;
3795918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  }
380efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  using object::ELFType;
381efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  typedef ELFType<support::little, 8, true> LE64;
382efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  typedef ELFType<support::big, 8, true> BE64;
383efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  typedef ELFType<support::little, 4, false> LE32;
384efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  typedef ELFType<support::big, 4, false> BE32;
385efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva  if (is64Bit(Doc)) {
386efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva    if (isLittleEndian(Doc))
387efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva      return writeELF<LE64>(outs(), Doc);
3885918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva    else
389efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva      return writeELF<BE64>(outs(), Doc);
3905918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  } else {
391efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva    if (isLittleEndian(Doc))
392efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva      return writeELF<LE32>(outs(), Doc);
3935918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva    else
394efc78986b3bf51572e013bfdf8cbb9e06a47c788Sean Silva      return writeELF<BE32>(outs(), Doc);
3955918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva  }
3965918b7a03d4d6a52e18f7c102250c9cfd6ae52ddSean Silva}
397