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