blob: 1d28a1abffcf3a605f39dc4061add8ca59a94595 [file] [log] [blame]
Sean Silvaf99309c2013-06-10 23:44:15 +00001//===- 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"
Will Dietz0b48c732013-10-12 21:29:16 +000016#include "llvm/ADT/ArrayRef.h"
Zachary Turner264b5d92017-06-07 03:48:56 +000017#include "llvm/BinaryFormat/ELF.h"
Rafael Espindola97de4742014-07-03 02:01:39 +000018#include "llvm/MC/StringTableBuilder.h"
Michael J. Spencer126973b2013-08-08 22:27:13 +000019#include "llvm/Object/ELFObjectFile.h"
Rafael Espindolaebd91932016-03-01 19:15:06 +000020#include "llvm/ObjectYAML/ELFYAML.h"
Sean Silvaf99309c2013-06-10 23:44:15 +000021#include "llvm/Support/MemoryBuffer.h"
22#include "llvm/Support/YAMLTraits.h"
23#include "llvm/Support/raw_ostream.h"
24
25using namespace llvm;
26
Sean Silva46dffff2013-06-13 22:20:01 +000027// 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`).
Sean Silva2a74f702013-06-15 00:31:46 +000030namespace {
Sean Silva46dffff2013-06-13 22:20:01 +000031class ContiguousBlobAccumulator {
32 const uint64_t InitialOffset;
Sean Silvabd3bc692013-06-20 19:11:41 +000033 SmallVector<char, 128> Buf;
Sean Silva46dffff2013-06-13 22:20:01 +000034 raw_svector_ostream OS;
35
Sean Silvad93323f2013-06-22 00:47:43 +000036 /// \returns The new offset.
37 uint64_t padToAlignment(unsigned Align) {
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +000038 if (Align == 0)
39 Align = 1;
Sean Silvad93323f2013-06-22 00:47:43 +000040 uint64_t CurrentOffset = InitialOffset + OS.tell();
Rui Ueyamada00f2f2016-01-14 21:06:47 +000041 uint64_t AlignedOffset = alignTo(CurrentOffset, Align);
Sean Silvad93323f2013-06-22 00:47:43 +000042 for (; CurrentOffset != AlignedOffset; ++CurrentOffset)
43 OS.write('\0');
44 return AlignedOffset; // == CurrentOffset;
45 }
46
Sean Silva46dffff2013-06-13 22:20:01 +000047public:
Sean Silvabd3bc692013-06-20 19:11:41 +000048 ContiguousBlobAccumulator(uint64_t InitialOffset_)
49 : InitialOffset(InitialOffset_), Buf(), OS(Buf) {}
Sean Silvad93323f2013-06-22 00:47:43 +000050 template <class Integer>
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +000051 raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) {
Sean Silvad93323f2013-06-22 00:47:43 +000052 Offset = padToAlignment(Align);
53 return OS;
54 }
Sean Silva46dffff2013-06-13 22:20:01 +000055 void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); }
56};
Sean Silva2a74f702013-06-15 00:31:46 +000057} // end anonymous namespace
Sean Silva46dffff2013-06-13 22:20:01 +000058
Simon Atanasyan35babf92014-04-06 09:02:55 +000059// Used to keep track of section and symbol names, so that in the YAML file
60// sections and symbols can be referenced by name instead of by index.
Sean Silva2a74f702013-06-15 00:31:46 +000061namespace {
Simon Atanasyan35babf92014-04-06 09:02:55 +000062class NameToIdxMap {
Sean Silvaa6423eb2013-06-15 00:25:26 +000063 StringMap<int> Map;
64public:
65 /// \returns true if name is already present in the map.
Simon Atanasyan35babf92014-04-06 09:02:55 +000066 bool addName(StringRef Name, unsigned i) {
David Blaikie5106ce72014-11-19 05:49:42 +000067 return !Map.insert(std::make_pair(Name, (int)i)).second;
Sean Silvaa6423eb2013-06-15 00:25:26 +000068 }
69 /// \returns true if name is not present in the map
Simon Atanasyan35babf92014-04-06 09:02:55 +000070 bool lookup(StringRef Name, unsigned &Idx) const {
71 StringMap<int>::const_iterator I = Map.find(Name);
Sean Silvaa6423eb2013-06-15 00:25:26 +000072 if (I == Map.end())
73 return true;
74 Idx = I->getValue();
75 return false;
76 }
77};
Sean Silva2a74f702013-06-15 00:31:46 +000078} // end anonymous namespace
Sean Silvaa6423eb2013-06-15 00:25:26 +000079
Sean Silva38205932013-06-13 22:19:48 +000080template <class T>
Will Dietz0b48c732013-10-12 21:29:16 +000081static size_t arrayDataSize(ArrayRef<T> A) {
82 return A.size() * sizeof(T);
Sean Silva38205932013-06-13 22:19:48 +000083}
84
85template <class T>
Will Dietz0b48c732013-10-12 21:29:16 +000086static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) {
87 OS.write((const char *)A.data(), arrayDataSize(A));
Sean Silva38205932013-06-13 22:19:48 +000088}
89
90template <class T>
91static void zero(T &Obj) {
92 memset(&Obj, 0, sizeof(Obj));
93}
94
Sean Silva08a75ae2013-06-20 19:11:44 +000095namespace {
96/// \brief "Single point of truth" for the ELF file construction.
97/// TODO: This class still has a ways to go before it is truly a "single
98/// point of truth".
99template <class ELFT>
100class ELFState {
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000101 typedef typename object::ELFFile<ELFT>::Elf_Ehdr Elf_Ehdr;
Petr Hosekeb04da32017-07-19 20:38:46 +0000102 typedef typename object::ELFFile<ELFT>::Elf_Phdr Elf_Phdr;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000103 typedef typename object::ELFFile<ELFT>::Elf_Shdr Elf_Shdr;
104 typedef typename object::ELFFile<ELFT>::Elf_Sym Elf_Sym;
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000105 typedef typename object::ELFFile<ELFT>::Elf_Rel Elf_Rel;
106 typedef typename object::ELFFile<ELFT>::Elf_Rela Elf_Rela;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000107
Sean Silva08a75ae2013-06-20 19:11:44 +0000108 /// \brief The future ".strtab" section.
Rafael Espindola21956e42015-10-23 21:48:05 +0000109 StringTableBuilder DotStrtab{StringTableBuilder::ELF};
Sean Silva08a75ae2013-06-20 19:11:44 +0000110
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000111 /// \brief The future ".shstrtab" section.
Rafael Espindola21956e42015-10-23 21:48:05 +0000112 StringTableBuilder DotShStrtab{StringTableBuilder::ELF};
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000113
Simon Atanasyan35babf92014-04-06 09:02:55 +0000114 NameToIdxMap SN2I;
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000115 NameToIdxMap SymN2I;
Simon Atanasyan220c54a2014-04-02 16:34:40 +0000116 const ELFYAML::Object &Doc;
Sean Silvac1c290b2013-06-20 20:59:34 +0000117
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000118 bool buildSectionIndex();
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000119 bool buildSymbolIndex(std::size_t &StartIndex,
120 const std::vector<ELFYAML::Symbol> &Symbols);
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000121 void initELFHeader(Elf_Ehdr &Header);
Petr Hosekeb04da32017-07-19 20:38:46 +0000122 void initProgramHeaders(std::vector<Elf_Phdr> &PHeaders);
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000123 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);
Petr Hosekeb04da32017-07-19 20:38:46 +0000130 void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
131 std::vector<Elf_Shdr> &SHeaders);
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000132 void addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
133 std::vector<Elf_Sym> &Syms, unsigned SymbolBinding);
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000134 void writeSectionContent(Elf_Shdr &SHeader,
135 const ELFYAML::RawContentSection &Section,
136 ContiguousBlobAccumulator &CBA);
137 bool writeSectionContent(Elf_Shdr &SHeader,
138 const ELFYAML::RelocationSection &Section,
139 ContiguousBlobAccumulator &CBA);
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000140 bool writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group,
141 ContiguousBlobAccumulator &CBA);
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000142 bool writeSectionContent(Elf_Shdr &SHeader,
143 const ELFYAML::MipsABIFlags &Section,
144 ContiguousBlobAccumulator &CBA);
Sean Silva08a75ae2013-06-20 19:11:44 +0000145
Simon Atanasyan220c54a2014-04-02 16:34:40 +0000146 // - SHT_NULL entry (placed first, i.e. 0'th entry)
147 // - symbol table (.symtab) (placed third to last)
148 // - string table (.strtab) (placed second to last)
149 // - section header string table (.shstrtab) (placed last)
150 unsigned getDotSymTabSecNo() const { return Doc.Sections.size() + 1; }
151 unsigned getDotStrTabSecNo() const { return Doc.Sections.size() + 2; }
152 unsigned getDotShStrTabSecNo() const { return Doc.Sections.size() + 3; }
153 unsigned getSectionCount() const { return Doc.Sections.size() + 4; }
154
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000155 ELFState(const ELFYAML::Object &D) : Doc(D) {}
Simon Atanasyan220c54a2014-04-02 16:34:40 +0000156
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000157public:
158 static int writeELF(raw_ostream &OS, const ELFYAML::Object &Doc);
Sean Silva08a75ae2013-06-20 19:11:44 +0000159};
160} // end anonymous namespace
161
Sean Silva37e817c2013-06-21 00:33:01 +0000162template <class ELFT>
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000163void ELFState<ELFT>::initELFHeader(Elf_Ehdr &Header) {
164 using namespace llvm::ELF;
165 zero(Header);
166 Header.e_ident[EI_MAG0] = 0x7f;
167 Header.e_ident[EI_MAG1] = 'E';
168 Header.e_ident[EI_MAG2] = 'L';
169 Header.e_ident[EI_MAG3] = 'F';
170 Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32;
171 bool IsLittleEndian = ELFT::TargetEndianness == support::little;
172 Header.e_ident[EI_DATA] = IsLittleEndian ? ELFDATA2LSB : ELFDATA2MSB;
173 Header.e_ident[EI_VERSION] = EV_CURRENT;
174 Header.e_ident[EI_OSABI] = Doc.Header.OSABI;
175 Header.e_ident[EI_ABIVERSION] = 0;
176 Header.e_type = Doc.Header.Type;
177 Header.e_machine = Doc.Header.Machine;
178 Header.e_version = EV_CURRENT;
179 Header.e_entry = Doc.Header.Entry;
Petr Hosekeb04da32017-07-19 20:38:46 +0000180 Header.e_phoff = sizeof(Header);
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000181 Header.e_flags = Doc.Header.Flags;
182 Header.e_ehsize = sizeof(Elf_Ehdr);
Petr Hosekeb04da32017-07-19 20:38:46 +0000183 Header.e_phentsize = sizeof(Elf_Phdr);
184 Header.e_phnum = Doc.ProgramHeaders.size();
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000185 Header.e_shentsize = sizeof(Elf_Shdr);
Petr Hosekeb04da32017-07-19 20:38:46 +0000186 // Immediately following the ELF header and program headers.
187 Header.e_shoff =
188 sizeof(Header) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size();
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000189 Header.e_shnum = getSectionCount();
190 Header.e_shstrndx = getDotShStrTabSecNo();
191}
192
193template <class ELFT>
Petr Hosekeb04da32017-07-19 20:38:46 +0000194void ELFState<ELFT>::initProgramHeaders(std::vector<Elf_Phdr> &PHeaders) {
195 for (const auto &YamlPhdr : Doc.ProgramHeaders) {
196 Elf_Phdr Phdr;
197 Phdr.p_type = YamlPhdr.Type;
198 Phdr.p_flags = YamlPhdr.Flags;
199 Phdr.p_vaddr = YamlPhdr.VAddr;
200 Phdr.p_paddr = YamlPhdr.PAddr;
201 PHeaders.push_back(Phdr);
202 }
203}
204
205template <class ELFT>
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000206bool ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders,
207 ContiguousBlobAccumulator &CBA) {
208 // Ensure SHN_UNDEF entry is present. An all-zero section header is a
209 // valid SHN_UNDEF entry since SHT_NULL == 0.
210 Elf_Shdr SHeader;
211 zero(SHeader);
212 SHeaders.push_back(SHeader);
213
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000214 for (const auto &Sec : Doc.Sections)
215 DotShStrtab.add(Sec->Name);
Rafael Espindola21956e42015-10-23 21:48:05 +0000216 DotShStrtab.finalize();
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000217
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000218 for (const auto &Sec : Doc.Sections) {
219 zero(SHeader);
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000220 SHeader.sh_name = DotShStrtab.getOffset(Sec->Name);
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000221 SHeader.sh_type = Sec->Type;
222 SHeader.sh_flags = Sec->Flags;
223 SHeader.sh_addr = Sec->Address;
224 SHeader.sh_addralign = Sec->AddressAlign;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000225
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000226 if (!Sec->Link.empty()) {
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000227 unsigned Index;
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000228 if (SN2I.lookup(Sec->Link, Index)) {
229 errs() << "error: Unknown section referenced: '" << Sec->Link
230 << "' at YAML section '" << Sec->Name << "'.\n";
231 return false;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000232 }
233 SHeader.sh_link = Index;
234 }
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000235
236 if (auto S = dyn_cast<ELFYAML::RawContentSection>(Sec.get()))
237 writeSectionContent(SHeader, *S, CBA);
238 else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec.get())) {
239 if (S->Link.empty())
240 // For relocation section set link to .symtab by default.
241 SHeader.sh_link = getDotSymTabSecNo();
242
243 unsigned Index;
244 if (SN2I.lookup(S->Info, Index)) {
Michael J. Spencer572d7422015-08-27 23:11:20 +0000245 if (S->Info.getAsInteger(0, Index)) {
246 errs() << "error: Unknown section referenced: '" << S->Info
247 << "' at YAML section '" << S->Name << "'.\n";
248 return false;
249 }
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000250 }
251 SHeader.sh_info = Index;
252
253 if (!writeSectionContent(SHeader, *S, CBA))
254 return false;
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000255 } else if (auto S = dyn_cast<ELFYAML::Group>(Sec.get())) {
256 unsigned SymIdx;
257 if (SymN2I.lookup(S->Info, SymIdx)) {
258 errs() << "error: Unknown symbol referenced: '" << S->Info
259 << "' at YAML section '" << S->Name << "'.\n";
260 return false;
261 }
262 SHeader.sh_info = SymIdx;
263 if (!writeSectionContent(SHeader, *S, CBA))
264 return false;
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000265 } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec.get())) {
266 if (!writeSectionContent(SHeader, *S, CBA))
267 return false;
Simon Atanasyan5db02762015-07-03 23:00:54 +0000268 } else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Sec.get())) {
269 SHeader.sh_entsize = 0;
270 SHeader.sh_size = S->Size;
271 // SHT_NOBITS section does not have content
272 // so just to setup the section offset.
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +0000273 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000274 } else
275 llvm_unreachable("Unknown section type");
276
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000277 SHeaders.push_back(SHeader);
278 }
279 return true;
280}
281
282template <class ELFT>
283void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader,
284 ContiguousBlobAccumulator &CBA) {
285 zero(SHeader);
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000286 SHeader.sh_name = DotShStrtab.getOffset(".symtab");
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000287 SHeader.sh_type = ELF::SHT_SYMTAB;
288 SHeader.sh_link = getDotStrTabSecNo();
289 // One greater than symbol table index of the last local symbol.
290 SHeader.sh_info = Doc.Symbols.Local.size() + 1;
291 SHeader.sh_entsize = sizeof(Elf_Sym);
Simon Atanasyan3a120922015-07-09 18:23:02 +0000292 SHeader.sh_addralign = 8;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000293
294 std::vector<Elf_Sym> Syms;
295 {
296 // Ensure STN_UNDEF is present
297 Elf_Sym Sym;
298 zero(Sym);
299 Syms.push_back(Sym);
300 }
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000301
302 // Add symbol names to .strtab.
303 for (const auto &Sym : Doc.Symbols.Local)
304 DotStrtab.add(Sym.Name);
305 for (const auto &Sym : Doc.Symbols.Global)
306 DotStrtab.add(Sym.Name);
307 for (const auto &Sym : Doc.Symbols.Weak)
308 DotStrtab.add(Sym.Name);
Rafael Espindola21956e42015-10-23 21:48:05 +0000309 DotStrtab.finalize();
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000310
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000311 addSymbols(Doc.Symbols.Local, Syms, ELF::STB_LOCAL);
312 addSymbols(Doc.Symbols.Global, Syms, ELF::STB_GLOBAL);
313 addSymbols(Doc.Symbols.Weak, Syms, ELF::STB_WEAK);
314
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +0000315 writeArrayData(
316 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign),
317 makeArrayRef(Syms));
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000318 SHeader.sh_size = arrayDataSize(makeArrayRef(Syms));
319}
320
321template <class ELFT>
322void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name,
323 StringTableBuilder &STB,
324 ContiguousBlobAccumulator &CBA) {
325 zero(SHeader);
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000326 SHeader.sh_name = DotShStrtab.getOffset(Name);
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000327 SHeader.sh_type = ELF::SHT_STRTAB;
Rafael Espindola39751af2016-10-04 22:43:25 +0000328 STB.write(CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign));
329 SHeader.sh_size = STB.getSize();
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000330 SHeader.sh_addralign = 1;
331}
332
333template <class ELFT>
Petr Hosekeb04da32017-07-19 20:38:46 +0000334void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders,
335 std::vector<Elf_Shdr> &SHeaders) {
336 uint32_t PhdrIdx = 0;
337 for (auto &YamlPhdr : Doc.ProgramHeaders) {
338 auto &PHeader = PHeaders[PhdrIdx++];
339
340 if (YamlPhdr.Sections.size())
341 PHeader.p_offset = UINT32_MAX;
342 else
343 PHeader.p_offset = 0;
344
345 // Find the minimum offset for the program header.
346 for (auto SecName : YamlPhdr.Sections) {
347 uint32_t Index = 0;
348 SN2I.lookup(SecName.Section, Index);
349 const auto &SHeader = SHeaders[Index];
350 PHeader.p_offset = std::min(PHeader.p_offset, SHeader.sh_offset);
351 }
352
353 // Find the maximum offset of the end of a section in order to set p_filesz.
354 PHeader.p_filesz = 0;
355 for (auto SecName : YamlPhdr.Sections) {
356 uint32_t Index = 0;
357 SN2I.lookup(SecName.Section, Index);
358 const auto &SHeader = SHeaders[Index];
359 uint64_t EndOfSection;
360 if (SHeader.sh_type == llvm::ELF::SHT_NOBITS)
361 EndOfSection = SHeader.sh_offset;
362 else
363 EndOfSection = SHeader.sh_offset + SHeader.sh_size;
364 uint64_t EndOfSegment = PHeader.p_offset + PHeader.p_filesz;
365 EndOfSegment = std::max(EndOfSegment, EndOfSection);
366 PHeader.p_filesz = EndOfSegment - PHeader.p_offset;
367 }
368
369 // Find the memory size by adding the size of sections at the end of the
370 // segment. These should be empty (size of zero) and NOBITS sections.
371 PHeader.p_memsz = PHeader.p_filesz;
372 for (auto SecName : YamlPhdr.Sections) {
373 uint32_t Index = 0;
374 SN2I.lookup(SecName.Section, Index);
375 const auto &SHeader = SHeaders[Index];
376 if (SHeader.sh_offset == PHeader.p_offset + PHeader.p_filesz)
377 PHeader.p_memsz += SHeader.sh_size;
378 }
379
380 // Set the alignment of the segment to be the same as the maximum alignment
381 // of the the sections with the same offset so that by default the segment
382 // has a valid and sensible alignment.
383 PHeader.p_align = 1;
384 for (auto SecName : YamlPhdr.Sections) {
385 uint32_t Index = 0;
386 SN2I.lookup(SecName.Section, Index);
387 const auto &SHeader = SHeaders[Index];
388 if (SHeader.sh_offset == PHeader.p_offset)
389 PHeader.p_align = std::max(PHeader.p_align, SHeader.sh_addralign);
390 }
391 }
392}
393
394template <class ELFT>
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000395void ELFState<ELFT>::addSymbols(const std::vector<ELFYAML::Symbol> &Symbols,
396 std::vector<Elf_Sym> &Syms,
397 unsigned SymbolBinding) {
Simon Atanasyan048baca2014-03-14 06:53:30 +0000398 for (const auto &Sym : Symbols) {
Sean Silva6b083882013-06-18 23:14:03 +0000399 Elf_Sym Symbol;
400 zero(Symbol);
401 if (!Sym.Name.empty())
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000402 Symbol.st_name = DotStrtab.getOffset(Sym.Name);
Sean Silvaaff51252013-06-21 00:27:50 +0000403 Symbol.setBindingAndType(SymbolBinding, Sym.Type);
Sean Silvac4afa6d2013-06-21 01:11:48 +0000404 if (!Sym.Section.empty()) {
405 unsigned Index;
Simon Atanasyan35babf92014-04-06 09:02:55 +0000406 if (SN2I.lookup(Sym.Section, Index)) {
Sean Silvac4afa6d2013-06-21 01:11:48 +0000407 errs() << "error: Unknown section referenced: '" << Sym.Section
408 << "' by YAML symbol " << Sym.Name << ".\n";
409 exit(1);
410 }
411 Symbol.st_shndx = Index;
412 } // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
Sean Silva05001b92013-06-20 20:59:47 +0000413 Symbol.st_value = Sym.Value;
Simon Atanasyan60e1a792014-11-06 22:46:24 +0000414 Symbol.st_other = Sym.Other;
Sean Silva05001b92013-06-20 20:59:47 +0000415 Symbol.st_size = Sym.Size;
Sean Silva6b083882013-06-18 23:14:03 +0000416 Syms.push_back(Symbol);
417 }
Sean Silvaaff51252013-06-21 00:27:50 +0000418}
419
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000420template <class ELFT>
421void
422ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
423 const ELFYAML::RawContentSection &Section,
424 ContiguousBlobAccumulator &CBA) {
Simon Atanasyanb83f3802014-05-16 16:01:00 +0000425 assert(Section.Size >= Section.Content.binary_size() &&
426 "Section size and section content are inconsistent");
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +0000427 raw_ostream &OS =
428 CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Simon Atanasyanb83f3802014-05-16 16:01:00 +0000429 Section.Content.writeAsBinary(OS);
430 for (auto i = Section.Content.binary_size(); i < Section.Size; ++i)
431 OS.write(0);
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000432 SHeader.sh_entsize = 0;
Simon Atanasyanb83f3802014-05-16 16:01:00 +0000433 SHeader.sh_size = Section.Size;
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000434}
435
Simon Atanasyan5d19c672015-01-25 13:29:25 +0000436static bool isMips64EL(const ELFYAML::Object &Doc) {
437 return Doc.Header.Machine == ELFYAML::ELF_EM(llvm::ELF::EM_MIPS) &&
438 Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) &&
439 Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
440}
441
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000442template <class ELFT>
443bool
444ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
445 const ELFYAML::RelocationSection &Section,
446 ContiguousBlobAccumulator &CBA) {
Simon Atanasyan8eb9d1b2015-05-08 07:05:04 +0000447 assert((Section.Type == llvm::ELF::SHT_REL ||
448 Section.Type == llvm::ELF::SHT_RELA) &&
449 "Section type is not SHT_REL nor SHT_RELA");
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000450
451 bool IsRela = Section.Type == llvm::ELF::SHT_RELA;
452 SHeader.sh_entsize = IsRela ? sizeof(Elf_Rela) : sizeof(Elf_Rel);
453 SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size();
454
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +0000455 auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000456
457 for (const auto &Rel : Section.Relocations) {
Adhemerval Zanella9f3dbff2015-04-22 15:26:43 +0000458 unsigned SymIdx = 0;
459 // Some special relocation, R_ARM_v4BX for instance, does not have
460 // an external reference. So it ignores the return value of lookup()
461 // here.
462 SymN2I.lookup(Rel.Symbol, SymIdx);
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000463
464 if (IsRela) {
465 Elf_Rela REntry;
466 zero(REntry);
467 REntry.r_offset = Rel.Offset;
468 REntry.r_addend = Rel.Addend;
Simon Atanasyan5d19c672015-01-25 13:29:25 +0000469 REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000470 OS.write((const char *)&REntry, sizeof(REntry));
471 } else {
472 Elf_Rel REntry;
473 zero(REntry);
474 REntry.r_offset = Rel.Offset;
Simon Atanasyan5d19c672015-01-25 13:29:25 +0000475 REntry.setSymbolAndType(SymIdx, Rel.Type, isMips64EL(Doc));
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000476 OS.write((const char *)&REntry, sizeof(REntry));
477 }
478 }
479 return true;
480}
481
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000482template <class ELFT>
483bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
484 const ELFYAML::Group &Section,
485 ContiguousBlobAccumulator &CBA) {
486 typedef typename object::ELFFile<ELFT>::Elf_Word Elf_Word;
Simon Atanasyan8eb9d1b2015-05-08 07:05:04 +0000487 assert(Section.Type == llvm::ELF::SHT_GROUP &&
488 "Section type is not SHT_GROUP");
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000489
490 SHeader.sh_entsize = sizeof(Elf_Word);
491 SHeader.sh_size = SHeader.sh_entsize * Section.Members.size();
492
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +0000493 auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Shankar Easwaran6fbbe202015-02-21 04:28:26 +0000494
495 for (auto member : Section.Members) {
496 Elf_Word SIdx;
497 unsigned int sectionIndex = 0;
498 if (member.sectionNameOrType == "GRP_COMDAT")
499 sectionIndex = llvm::ELF::GRP_COMDAT;
500 else if (SN2I.lookup(member.sectionNameOrType, sectionIndex)) {
501 errs() << "error: Unknown section referenced: '"
502 << member.sectionNameOrType << "' at YAML section' "
503 << Section.Name << "\n";
504 return false;
505 }
506 SIdx = sectionIndex;
507 OS.write((const char *)&SIdx, sizeof(SIdx));
508 }
509 return true;
510}
511
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000512template <class ELFT>
513bool ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader,
514 const ELFYAML::MipsABIFlags &Section,
515 ContiguousBlobAccumulator &CBA) {
Simon Atanasyan8eb9d1b2015-05-08 07:05:04 +0000516 assert(Section.Type == llvm::ELF::SHT_MIPS_ABIFLAGS &&
517 "Section type is not SHT_MIPS_ABIFLAGS");
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000518
519 object::Elf_Mips_ABIFlags<ELFT> Flags;
520 zero(Flags);
521 SHeader.sh_entsize = sizeof(Flags);
522 SHeader.sh_size = SHeader.sh_entsize;
523
Simon Atanasyan22c4c9e2015-07-08 10:12:40 +0000524 auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign);
Simon Atanasyan04d9e652015-05-07 15:40:48 +0000525 Flags.version = Section.Version;
526 Flags.isa_level = Section.ISALevel;
527 Flags.isa_rev = Section.ISARevision;
528 Flags.gpr_size = Section.GPRSize;
529 Flags.cpr1_size = Section.CPR1Size;
530 Flags.cpr2_size = Section.CPR2Size;
531 Flags.fp_abi = Section.FpABI;
532 Flags.isa_ext = Section.ISAExtension;
533 Flags.ases = Section.ASEs;
534 Flags.flags1 = Section.Flags1;
535 Flags.flags2 = Section.Flags2;
536 OS.write((const char *)&Flags, sizeof(Flags));
537
538 return true;
539}
540
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000541template <class ELFT> bool ELFState<ELFT>::buildSectionIndex() {
542 SN2I.addName(".symtab", getDotSymTabSecNo());
543 SN2I.addName(".strtab", getDotStrTabSecNo());
544 SN2I.addName(".shstrtab", getDotShStrTabSecNo());
Sean Silvaaff51252013-06-21 00:27:50 +0000545
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000546 for (unsigned i = 0, e = Doc.Sections.size(); i != e; ++i) {
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000547 StringRef Name = Doc.Sections[i]->Name;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000548 if (Name.empty())
549 continue;
550 // "+ 1" to take into account the SHT_NULL entry.
551 if (SN2I.addName(Name, i + 1)) {
552 errs() << "error: Repeated section name: '" << Name
553 << "' at YAML section number " << i << ".\n";
554 return false;
555 }
Sean Silvaaff51252013-06-21 00:27:50 +0000556 }
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000557 return true;
Sean Silva6b083882013-06-18 23:14:03 +0000558}
559
Sean Silvaf99309c2013-06-10 23:44:15 +0000560template <class ELFT>
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000561bool
562ELFState<ELFT>::buildSymbolIndex(std::size_t &StartIndex,
563 const std::vector<ELFYAML::Symbol> &Symbols) {
564 for (const auto &Sym : Symbols) {
565 ++StartIndex;
566 if (Sym.Name.empty())
567 continue;
568 if (SymN2I.addName(Sym.Name, StartIndex)) {
569 errs() << "error: Repeated symbol name: '" << Sym.Name << "'.\n";
570 return false;
571 }
572 }
573 return true;
574}
575
576template <class ELFT>
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000577int ELFState<ELFT>::writeELF(raw_ostream &OS, const ELFYAML::Object &Doc) {
Simon Atanasyan220c54a2014-04-02 16:34:40 +0000578 ELFState<ELFT> State(Doc);
579 if (!State.buildSectionIndex())
580 return 1;
581
Simon Atanasyan42ac0dd2014-04-11 04:13:39 +0000582 std::size_t StartSymIndex = 0;
583 if (!State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Local) ||
584 !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Global) ||
585 !State.buildSymbolIndex(StartSymIndex, Doc.Symbols.Weak))
586 return 1;
587
Sean Silva38205932013-06-13 22:19:48 +0000588 Elf_Ehdr Header;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000589 State.initELFHeader(Header);
Sean Silvaf99309c2013-06-10 23:44:15 +0000590
Sean Silva38205932013-06-13 22:19:48 +0000591 // TODO: Flesh out section header support.
Petr Hosekeb04da32017-07-19 20:38:46 +0000592
593 std::vector<Elf_Phdr> PHeaders;
594 State.initProgramHeaders(PHeaders);
Sean Silva38205932013-06-13 22:19:48 +0000595
Sean Silva08a75ae2013-06-20 19:11:44 +0000596 // XXX: This offset is tightly coupled with the order that we write
597 // things to `OS`.
Petr Hosekeb04da32017-07-19 20:38:46 +0000598 const size_t SectionContentBeginOffset = Header.e_ehsize +
599 Header.e_phentsize * Header.e_phnum +
600 Header.e_shentsize * Header.e_shnum;
Sean Silva08a75ae2013-06-20 19:11:44 +0000601 ContiguousBlobAccumulator CBA(SectionContentBeginOffset);
Sean Silvac1c290b2013-06-20 20:59:34 +0000602
Hans Wennborg59f0cba2014-04-30 19:38:09 +0000603 // Doc might not contain .symtab, .strtab and .shstrtab sections,
604 // but we will emit them, so make sure to add them to ShStrTabSHeader.
605 State.DotShStrtab.add(".symtab");
606 State.DotShStrtab.add(".strtab");
607 State.DotShStrtab.add(".shstrtab");
608
Sean Silva38205932013-06-13 22:19:48 +0000609 std::vector<Elf_Shdr> SHeaders;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000610 if(!State.initSectionHeaders(SHeaders, CBA))
611 return 1;
Sean Silva38205932013-06-13 22:19:48 +0000612
Sean Silva82177572013-06-22 01:38:00 +0000613 // .symtab section.
614 Elf_Shdr SymtabSHeader;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000615 State.initSymtabSectionHeader(SymtabSHeader, CBA);
Sean Silva82177572013-06-22 01:38:00 +0000616 SHeaders.push_back(SymtabSHeader);
617
Sean Silva6b083882013-06-18 23:14:03 +0000618 // .strtab string table header.
Sean Silvac3131922013-06-18 21:37:50 +0000619 Elf_Shdr DotStrTabSHeader;
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000620 State.initStrtabSectionHeader(DotStrTabSHeader, ".strtab", State.DotStrtab,
621 CBA);
Sean Silva7d617222013-06-22 01:06:12 +0000622 SHeaders.push_back(DotStrTabSHeader);
Sean Silvac3131922013-06-18 21:37:50 +0000623
Simon Atanasyan3ee21b02014-04-02 16:34:54 +0000624 // .shstrtab string table header.
625 Elf_Shdr ShStrTabSHeader;
626 State.initStrtabSectionHeader(ShStrTabSHeader, ".shstrtab", State.DotShStrtab,
627 CBA);
628 SHeaders.push_back(ShStrTabSHeader);
Sean Silvaf99309c2013-06-10 23:44:15 +0000629
Petr Hosekeb04da32017-07-19 20:38:46 +0000630 // Now we can decide segment offsets
631 State.setProgramHeaderLayout(PHeaders, SHeaders);
632
Sean Silvaf99309c2013-06-10 23:44:15 +0000633 OS.write((const char *)&Header, sizeof(Header));
Petr Hosekeb04da32017-07-19 20:38:46 +0000634 writeArrayData(OS, makeArrayRef(PHeaders));
Will Dietz0b48c732013-10-12 21:29:16 +0000635 writeArrayData(OS, makeArrayRef(SHeaders));
Sean Silva46dffff2013-06-13 22:20:01 +0000636 CBA.writeBlobToStream(OS);
Sean Silva415d93f2013-06-17 20:14:59 +0000637 return 0;
Sean Silvaf99309c2013-06-10 23:44:15 +0000638}
639
Sean Silva11caeba2013-06-22 01:03:35 +0000640static bool is64Bit(const ELFYAML::Object &Doc) {
641 return Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64);
642}
643
644static bool isLittleEndian(const ELFYAML::Object &Doc) {
645 return Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB);
646}
647
Chris Bieneman8ff0c112016-06-27 19:53:53 +0000648int yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out) {
Sean Silva11caeba2013-06-22 01:03:35 +0000649 using object::ELFType;
Rafael Espindolaac729b42015-06-02 12:05:27 +0000650 typedef ELFType<support::little, true> LE64;
651 typedef ELFType<support::big, true> BE64;
652 typedef ELFType<support::little, false> LE32;
653 typedef ELFType<support::big, false> BE32;
Sean Silva11caeba2013-06-22 01:03:35 +0000654 if (is64Bit(Doc)) {
655 if (isLittleEndian(Doc))
Simon Atanasyan73e047e2014-05-15 16:14:02 +0000656 return ELFState<LE64>::writeELF(Out, Doc);
Sean Silvaf99309c2013-06-10 23:44:15 +0000657 else
Simon Atanasyan73e047e2014-05-15 16:14:02 +0000658 return ELFState<BE64>::writeELF(Out, Doc);
Sean Silvaf99309c2013-06-10 23:44:15 +0000659 } else {
Sean Silva11caeba2013-06-22 01:03:35 +0000660 if (isLittleEndian(Doc))
Simon Atanasyan73e047e2014-05-15 16:14:02 +0000661 return ELFState<LE32>::writeELF(Out, Doc);
Sean Silvaf99309c2013-06-10 23:44:15 +0000662 else
Simon Atanasyan73e047e2014-05-15 16:14:02 +0000663 return ELFState<BE32>::writeELF(Out, Doc);
Sean Silvaf99309c2013-06-10 23:44:15 +0000664 }
Sean Silvaf99309c2013-06-10 23:44:15 +0000665}