1 //===- yaml2elf - Convert YAML to a ELF object file -----------------------===//
3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4 // See https://llvm.org/LICENSE.txt for license information.
5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 //===----------------------------------------------------------------------===//
10 /// The ELF component of yaml2obj.
12 //===----------------------------------------------------------------------===//
15 #include "llvm/ADT/ArrayRef.h"
16 #include "llvm/BinaryFormat/ELF.h"
17 #include "llvm/MC/StringTableBuilder.h"
18 #include "llvm/Object/ELFObjectFile.h"
19 #include "llvm/ObjectYAML/ELFYAML.h"
20 #include "llvm/Support/MemoryBuffer.h"
21 #include "llvm/Support/WithColor.h"
22 #include "llvm/Support/YAMLTraits.h"
23 #include "llvm/Support/raw_ostream.h"
27 // This class is used to build up a contiguous binary blob while keeping
28 // track of an offset in the output (which notionally begins at
31 class ContiguousBlobAccumulator
{
32 const uint64_t InitialOffset
;
33 SmallVector
<char, 128> Buf
;
34 raw_svector_ostream OS
;
36 /// \returns The new offset.
37 uint64_t padToAlignment(unsigned Align
) {
40 uint64_t CurrentOffset
= InitialOffset
+ OS
.tell();
41 uint64_t AlignedOffset
= alignTo(CurrentOffset
, Align
);
42 for (; CurrentOffset
!= AlignedOffset
; ++CurrentOffset
)
44 return AlignedOffset
; // == CurrentOffset;
48 ContiguousBlobAccumulator(uint64_t InitialOffset_
)
49 : InitialOffset(InitialOffset_
), Buf(), OS(Buf
) {}
50 template <class Integer
>
51 raw_ostream
&getOSAndAlignedOffset(Integer
&Offset
, unsigned Align
) {
52 Offset
= padToAlignment(Align
);
55 void writeBlobToStream(raw_ostream
&Out
) { Out
<< OS
.str(); }
57 } // end anonymous namespace
59 // 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.
65 /// \returns true if name is already present in the map.
66 bool addName(StringRef Name
, unsigned i
) {
67 return !Map
.insert(std::make_pair(Name
, (int)i
)).second
;
69 /// \returns true if name is not present in the map
70 bool lookup(StringRef Name
, unsigned &Idx
) const {
71 StringMap
<int>::const_iterator I
= Map
.find(Name
);
77 /// asserts if name is not present in the map
78 unsigned get(StringRef Name
) const {
80 auto missing
= lookup(Name
, Idx
);
82 assert(!missing
&& "Expected section not found in index");
85 unsigned size() const { return Map
.size(); }
87 } // end anonymous namespace
90 static size_t arrayDataSize(ArrayRef
<T
> A
) {
91 return A
.size() * sizeof(T
);
95 static void writeArrayData(raw_ostream
&OS
, ArrayRef
<T
> A
) {
96 OS
.write((const char *)A
.data(), arrayDataSize(A
));
100 static void zero(T
&Obj
) {
101 memset(&Obj
, 0, sizeof(Obj
));
105 /// "Single point of truth" for the ELF file construction.
106 /// TODO: This class still has a ways to go before it is truly a "single
108 template <class ELFT
>
110 typedef typename
ELFT::Ehdr Elf_Ehdr
;
111 typedef typename
ELFT::Phdr Elf_Phdr
;
112 typedef typename
ELFT::Shdr Elf_Shdr
;
113 typedef typename
ELFT::Sym Elf_Sym
;
114 typedef typename
ELFT::Rel Elf_Rel
;
115 typedef typename
ELFT::Rela Elf_Rela
;
116 typedef typename
ELFT::Relr Elf_Relr
;
117 typedef typename
ELFT::Dyn Elf_Dyn
;
119 enum class SymtabType
{ Static
, Dynamic
};
121 /// The future ".strtab" section.
122 StringTableBuilder DotStrtab
{StringTableBuilder::ELF
};
124 /// The future ".shstrtab" section.
125 StringTableBuilder DotShStrtab
{StringTableBuilder::ELF
};
127 /// The future ".dynstr" section.
128 StringTableBuilder DotDynstr
{StringTableBuilder::ELF
};
132 const ELFYAML::Object
&Doc
;
134 bool buildSectionIndex();
135 bool buildSymbolIndex(std::size_t &StartIndex
,
136 const std::vector
<ELFYAML::Symbol
> &Symbols
);
137 void initELFHeader(Elf_Ehdr
&Header
);
138 void initProgramHeaders(std::vector
<Elf_Phdr
> &PHeaders
);
139 bool initSectionHeaders(std::vector
<Elf_Shdr
> &SHeaders
,
140 ContiguousBlobAccumulator
&CBA
);
141 void initSymtabSectionHeader(Elf_Shdr
&SHeader
, SymtabType STType
,
142 ContiguousBlobAccumulator
&CBA
);
143 void initStrtabSectionHeader(Elf_Shdr
&SHeader
, StringRef Name
,
144 StringTableBuilder
&STB
,
145 ContiguousBlobAccumulator
&CBA
);
146 void setProgramHeaderLayout(std::vector
<Elf_Phdr
> &PHeaders
,
147 std::vector
<Elf_Shdr
> &SHeaders
);
148 void addSymbols(const std::vector
<ELFYAML::Symbol
> &Symbols
,
149 std::vector
<Elf_Sym
> &Syms
, unsigned SymbolBinding
,
150 const StringTableBuilder
&Strtab
);
151 void writeSectionContent(Elf_Shdr
&SHeader
,
152 const ELFYAML::RawContentSection
&Section
,
153 ContiguousBlobAccumulator
&CBA
);
154 bool writeSectionContent(Elf_Shdr
&SHeader
,
155 const ELFYAML::RelocationSection
&Section
,
156 ContiguousBlobAccumulator
&CBA
);
157 bool writeSectionContent(Elf_Shdr
&SHeader
, const ELFYAML::Group
&Group
,
158 ContiguousBlobAccumulator
&CBA
);
159 bool writeSectionContent(Elf_Shdr
&SHeader
,
160 const ELFYAML::MipsABIFlags
&Section
,
161 ContiguousBlobAccumulator
&CBA
);
162 bool hasDynamicSymbols() const;
163 SmallVector
<const char *, 5> implicitSectionNames() const;
165 // - SHT_NULL entry (placed first, i.e. 0'th entry)
166 // - symbol table (.symtab) (defaults to after last yaml section)
167 // - string table (.strtab) (defaults to after .symtab)
168 // - section header string table (.shstrtab) (defaults to after .strtab)
169 // - dynamic symbol table (.dynsym) (defaults to after .shstrtab)
170 // - dynamic string table (.dynstr) (defaults to after .dynsym)
171 unsigned getDotSymTabSecNo() const { return SN2I
.get(".symtab"); }
172 unsigned getDotStrTabSecNo() const { return SN2I
.get(".strtab"); }
173 unsigned getDotShStrTabSecNo() const { return SN2I
.get(".shstrtab"); }
174 unsigned getDotDynSymSecNo() const { return SN2I
.get(".dynsym"); }
175 unsigned getDotDynStrSecNo() const { return SN2I
.get(".dynstr"); }
176 unsigned getSectionCount() const { return SN2I
.size() + 1; }
178 ELFState(const ELFYAML::Object
&D
) : Doc(D
) {}
181 static int writeELF(raw_ostream
&OS
, const ELFYAML::Object
&Doc
);
183 } // end anonymous namespace
185 template <class ELFT
>
186 void ELFState
<ELFT
>::initELFHeader(Elf_Ehdr
&Header
) {
187 using namespace llvm::ELF
;
189 Header
.e_ident
[EI_MAG0
] = 0x7f;
190 Header
.e_ident
[EI_MAG1
] = 'E';
191 Header
.e_ident
[EI_MAG2
] = 'L';
192 Header
.e_ident
[EI_MAG3
] = 'F';
193 Header
.e_ident
[EI_CLASS
] = ELFT::Is64Bits
? ELFCLASS64
: ELFCLASS32
;
194 bool IsLittleEndian
= ELFT::TargetEndianness
== support::little
;
195 Header
.e_ident
[EI_DATA
] = IsLittleEndian
? ELFDATA2LSB
: ELFDATA2MSB
;
196 Header
.e_ident
[EI_VERSION
] = EV_CURRENT
;
197 Header
.e_ident
[EI_OSABI
] = Doc
.Header
.OSABI
;
198 Header
.e_ident
[EI_ABIVERSION
] = Doc
.Header
.ABIVersion
;
199 Header
.e_type
= Doc
.Header
.Type
;
200 Header
.e_machine
= Doc
.Header
.Machine
;
201 Header
.e_version
= EV_CURRENT
;
202 Header
.e_entry
= Doc
.Header
.Entry
;
203 Header
.e_phoff
= sizeof(Header
);
204 Header
.e_flags
= Doc
.Header
.Flags
;
205 Header
.e_ehsize
= sizeof(Elf_Ehdr
);
206 Header
.e_phentsize
= sizeof(Elf_Phdr
);
207 Header
.e_phnum
= Doc
.ProgramHeaders
.size();
208 Header
.e_shentsize
= sizeof(Elf_Shdr
);
209 // Immediately following the ELF header and program headers.
211 sizeof(Header
) + sizeof(Elf_Phdr
) * Doc
.ProgramHeaders
.size();
212 Header
.e_shnum
= getSectionCount();
213 Header
.e_shstrndx
= getDotShStrTabSecNo();
216 template <class ELFT
>
217 void ELFState
<ELFT
>::initProgramHeaders(std::vector
<Elf_Phdr
> &PHeaders
) {
218 for (const auto &YamlPhdr
: Doc
.ProgramHeaders
) {
220 Phdr
.p_type
= YamlPhdr
.Type
;
221 Phdr
.p_flags
= YamlPhdr
.Flags
;
222 Phdr
.p_vaddr
= YamlPhdr
.VAddr
;
223 Phdr
.p_paddr
= YamlPhdr
.PAddr
;
224 PHeaders
.push_back(Phdr
);
228 static bool convertSectionIndex(NameToIdxMap
&SN2I
, StringRef SecName
,
229 StringRef IndexSrc
, unsigned &IndexDest
) {
230 if (SN2I
.lookup(IndexSrc
, IndexDest
) && !to_integer(IndexSrc
, IndexDest
)) {
231 WithColor::error() << "Unknown section referenced: '" << IndexSrc
232 << "' at YAML section '" << SecName
<< "'.\n";
238 template <class ELFT
>
239 bool ELFState
<ELFT
>::initSectionHeaders(std::vector
<Elf_Shdr
> &SHeaders
,
240 ContiguousBlobAccumulator
&CBA
) {
241 // Ensure SHN_UNDEF entry is present. An all-zero section header is a
242 // valid SHN_UNDEF entry since SHT_NULL == 0.
245 SHeaders
.push_back(SHeader
);
247 for (const auto &Sec
: Doc
.Sections
) {
249 SHeader
.sh_name
= DotShStrtab
.getOffset(Sec
->Name
);
250 SHeader
.sh_type
= Sec
->Type
;
251 SHeader
.sh_flags
= Sec
->Flags
;
252 SHeader
.sh_addr
= Sec
->Address
;
253 SHeader
.sh_addralign
= Sec
->AddressAlign
;
255 if (!Sec
->Link
.empty()) {
257 if (!convertSectionIndex(SN2I
, Sec
->Name
, Sec
->Link
, Index
))
259 SHeader
.sh_link
= Index
;
262 if (auto S
= dyn_cast
<ELFYAML::RawContentSection
>(Sec
.get()))
263 writeSectionContent(SHeader
, *S
, CBA
);
264 else if (auto S
= dyn_cast
<ELFYAML::RelocationSection
>(Sec
.get())) {
266 // For relocation section set link to .symtab by default.
267 SHeader
.sh_link
= getDotSymTabSecNo();
270 if (!convertSectionIndex(SN2I
, S
->Name
, S
->Info
, Index
))
272 SHeader
.sh_info
= Index
;
273 if (!writeSectionContent(SHeader
, *S
, CBA
))
275 } else if (auto S
= dyn_cast
<ELFYAML::Group
>(Sec
.get())) {
277 if (SymN2I
.lookup(S
->Info
, SymIdx
) && !to_integer(S
->Info
, SymIdx
)) {
278 WithColor::error() << "Unknown symbol referenced: '" << S
->Info
279 << "' at YAML section '" << S
->Name
<< "'.\n";
282 SHeader
.sh_info
= SymIdx
;
283 if (!writeSectionContent(SHeader
, *S
, CBA
))
285 } else if (auto S
= dyn_cast
<ELFYAML::MipsABIFlags
>(Sec
.get())) {
286 if (!writeSectionContent(SHeader
, *S
, CBA
))
288 } else if (auto S
= dyn_cast
<ELFYAML::NoBitsSection
>(Sec
.get())) {
289 SHeader
.sh_entsize
= 0;
290 SHeader
.sh_size
= S
->Size
;
291 // SHT_NOBITS section does not have content
292 // so just to setup the section offset.
293 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
295 llvm_unreachable("Unknown section type");
297 SHeaders
.push_back(SHeader
);
302 template <class ELFT
>
303 void ELFState
<ELFT
>::initSymtabSectionHeader(Elf_Shdr
&SHeader
,
305 ContiguousBlobAccumulator
&CBA
) {
307 bool IsStatic
= STType
== SymtabType::Static
;
308 SHeader
.sh_name
= DotShStrtab
.getOffset(IsStatic
? ".symtab" : ".dynsym");
309 SHeader
.sh_type
= IsStatic
? ELF::SHT_SYMTAB
: ELF::SHT_DYNSYM
;
310 SHeader
.sh_link
= IsStatic
? getDotStrTabSecNo() : getDotDynStrSecNo();
311 const auto &Symbols
= IsStatic
? Doc
.Symbols
: Doc
.DynamicSymbols
;
312 auto &Strtab
= IsStatic
? DotStrtab
: DotDynstr
;
313 // One greater than symbol table index of the last local symbol.
314 SHeader
.sh_info
= Symbols
.Local
.size() + 1;
315 SHeader
.sh_entsize
= sizeof(Elf_Sym
);
316 SHeader
.sh_addralign
= 8;
318 std::vector
<Elf_Sym
> Syms
;
320 // Ensure STN_UNDEF is present
326 // Add symbol names to .strtab or .dynstr.
327 for (const auto &Sym
: Symbols
.Local
)
328 Strtab
.add(Sym
.Name
);
329 for (const auto &Sym
: Symbols
.Global
)
330 Strtab
.add(Sym
.Name
);
331 for (const auto &Sym
: Symbols
.Weak
)
332 Strtab
.add(Sym
.Name
);
335 addSymbols(Symbols
.Local
, Syms
, ELF::STB_LOCAL
, Strtab
);
336 addSymbols(Symbols
.Global
, Syms
, ELF::STB_GLOBAL
, Strtab
);
337 addSymbols(Symbols
.Weak
, Syms
, ELF::STB_WEAK
, Strtab
);
340 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
),
342 SHeader
.sh_size
= arrayDataSize(makeArrayRef(Syms
));
345 template <class ELFT
>
346 void ELFState
<ELFT
>::initStrtabSectionHeader(Elf_Shdr
&SHeader
, StringRef Name
,
347 StringTableBuilder
&STB
,
348 ContiguousBlobAccumulator
&CBA
) {
350 SHeader
.sh_name
= DotShStrtab
.getOffset(Name
);
351 SHeader
.sh_type
= ELF::SHT_STRTAB
;
352 STB
.write(CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
));
353 SHeader
.sh_size
= STB
.getSize();
354 SHeader
.sh_addralign
= 1;
357 template <class ELFT
>
358 void ELFState
<ELFT
>::setProgramHeaderLayout(std::vector
<Elf_Phdr
> &PHeaders
,
359 std::vector
<Elf_Shdr
> &SHeaders
) {
360 uint32_t PhdrIdx
= 0;
361 for (auto &YamlPhdr
: Doc
.ProgramHeaders
) {
362 auto &PHeader
= PHeaders
[PhdrIdx
++];
364 if (YamlPhdr
.Sections
.size())
365 PHeader
.p_offset
= UINT32_MAX
;
367 PHeader
.p_offset
= 0;
369 // Find the minimum offset for the program header.
370 for (auto SecName
: YamlPhdr
.Sections
) {
372 SN2I
.lookup(SecName
.Section
, Index
);
373 const auto &SHeader
= SHeaders
[Index
];
374 PHeader
.p_offset
= std::min(PHeader
.p_offset
, SHeader
.sh_offset
);
377 // Find the maximum offset of the end of a section in order to set p_filesz.
378 PHeader
.p_filesz
= 0;
379 for (auto SecName
: YamlPhdr
.Sections
) {
381 SN2I
.lookup(SecName
.Section
, Index
);
382 const auto &SHeader
= SHeaders
[Index
];
383 uint64_t EndOfSection
;
384 if (SHeader
.sh_type
== llvm::ELF::SHT_NOBITS
)
385 EndOfSection
= SHeader
.sh_offset
;
387 EndOfSection
= SHeader
.sh_offset
+ SHeader
.sh_size
;
388 uint64_t EndOfSegment
= PHeader
.p_offset
+ PHeader
.p_filesz
;
389 EndOfSegment
= std::max(EndOfSegment
, EndOfSection
);
390 PHeader
.p_filesz
= EndOfSegment
- PHeader
.p_offset
;
393 // Find the memory size by adding the size of sections at the end of the
394 // segment. These should be empty (size of zero) and NOBITS sections.
395 PHeader
.p_memsz
= PHeader
.p_filesz
;
396 for (auto SecName
: YamlPhdr
.Sections
) {
398 SN2I
.lookup(SecName
.Section
, Index
);
399 const auto &SHeader
= SHeaders
[Index
];
400 if (SHeader
.sh_offset
== PHeader
.p_offset
+ PHeader
.p_filesz
)
401 PHeader
.p_memsz
+= SHeader
.sh_size
;
404 // Set the alignment of the segment to be the same as the maximum alignment
405 // of the sections with the same offset so that by default the segment
406 // has a valid and sensible alignment.
407 if (YamlPhdr
.Align
) {
408 PHeader
.p_align
= *YamlPhdr
.Align
;
411 for (auto SecName
: YamlPhdr
.Sections
) {
413 SN2I
.lookup(SecName
.Section
, Index
);
414 const auto &SHeader
= SHeaders
[Index
];
415 if (SHeader
.sh_offset
== PHeader
.p_offset
)
416 PHeader
.p_align
= std::max(PHeader
.p_align
, SHeader
.sh_addralign
);
422 template <class ELFT
>
423 void ELFState
<ELFT
>::addSymbols(const std::vector
<ELFYAML::Symbol
> &Symbols
,
424 std::vector
<Elf_Sym
> &Syms
,
425 unsigned SymbolBinding
,
426 const StringTableBuilder
&Strtab
) {
427 for (const auto &Sym
: Symbols
) {
430 if (!Sym
.Name
.empty())
431 Symbol
.st_name
= Strtab
.getOffset(Sym
.Name
);
432 Symbol
.setBindingAndType(SymbolBinding
, Sym
.Type
);
433 if (!Sym
.Section
.empty()) {
435 if (SN2I
.lookup(Sym
.Section
, Index
)) {
436 WithColor::error() << "Unknown section referenced: '" << Sym
.Section
437 << "' by YAML symbol " << Sym
.Name
<< ".\n";
440 Symbol
.st_shndx
= Index
;
441 } else if (Sym
.Index
) {
442 Symbol
.st_shndx
= *Sym
.Index
;
444 // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
445 Symbol
.st_value
= Sym
.Value
;
446 Symbol
.st_other
= Sym
.Other
;
447 Symbol
.st_size
= Sym
.Size
;
448 Syms
.push_back(Symbol
);
452 template <class ELFT
>
454 ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
455 const ELFYAML::RawContentSection
&Section
,
456 ContiguousBlobAccumulator
&CBA
) {
457 assert(Section
.Size
>= Section
.Content
.binary_size() &&
458 "Section size and section content are inconsistent");
460 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
461 Section
.Content
.writeAsBinary(OS
);
462 for (auto i
= Section
.Content
.binary_size(); i
< Section
.Size
; ++i
)
465 SHeader
.sh_entsize
= *Section
.EntSize
;
466 else if (Section
.Type
== llvm::ELF::SHT_RELR
)
467 SHeader
.sh_entsize
= sizeof(Elf_Relr
);
468 else if (Section
.Type
== llvm::ELF::SHT_DYNAMIC
)
469 SHeader
.sh_entsize
= sizeof(Elf_Dyn
);
471 SHeader
.sh_entsize
= 0;
472 SHeader
.sh_size
= Section
.Size
;
475 static bool isMips64EL(const ELFYAML::Object
&Doc
) {
476 return Doc
.Header
.Machine
== ELFYAML::ELF_EM(llvm::ELF::EM_MIPS
) &&
477 Doc
.Header
.Class
== ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64
) &&
478 Doc
.Header
.Data
== ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB
);
481 template <class ELFT
>
483 ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
484 const ELFYAML::RelocationSection
&Section
,
485 ContiguousBlobAccumulator
&CBA
) {
486 assert((Section
.Type
== llvm::ELF::SHT_REL
||
487 Section
.Type
== llvm::ELF::SHT_RELA
) &&
488 "Section type is not SHT_REL nor SHT_RELA");
490 bool IsRela
= Section
.Type
== llvm::ELF::SHT_RELA
;
491 SHeader
.sh_entsize
= IsRela
? sizeof(Elf_Rela
) : sizeof(Elf_Rel
);
492 SHeader
.sh_size
= SHeader
.sh_entsize
* Section
.Relocations
.size();
494 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
496 for (const auto &Rel
: Section
.Relocations
) {
498 // Some special relocation, R_ARM_v4BX for instance, does not have
499 // an external reference. So it ignores the return value of lookup()
502 SymN2I
.lookup(*Rel
.Symbol
, SymIdx
);
507 REntry
.r_offset
= Rel
.Offset
;
508 REntry
.r_addend
= Rel
.Addend
;
509 REntry
.setSymbolAndType(SymIdx
, Rel
.Type
, isMips64EL(Doc
));
510 OS
.write((const char *)&REntry
, sizeof(REntry
));
514 REntry
.r_offset
= Rel
.Offset
;
515 REntry
.setSymbolAndType(SymIdx
, Rel
.Type
, isMips64EL(Doc
));
516 OS
.write((const char *)&REntry
, sizeof(REntry
));
522 template <class ELFT
>
523 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
524 const ELFYAML::Group
&Section
,
525 ContiguousBlobAccumulator
&CBA
) {
526 typedef typename
ELFT::Word Elf_Word
;
527 assert(Section
.Type
== llvm::ELF::SHT_GROUP
&&
528 "Section type is not SHT_GROUP");
530 SHeader
.sh_entsize
= sizeof(Elf_Word
);
531 SHeader
.sh_size
= SHeader
.sh_entsize
* Section
.Members
.size();
533 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
535 for (auto member
: Section
.Members
) {
537 unsigned int sectionIndex
= 0;
538 if (member
.sectionNameOrType
== "GRP_COMDAT")
539 sectionIndex
= llvm::ELF::GRP_COMDAT
;
540 else if (!convertSectionIndex(SN2I
, Section
.Name
, member
.sectionNameOrType
,
544 OS
.write((const char *)&SIdx
, sizeof(SIdx
));
549 template <class ELFT
>
550 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
551 const ELFYAML::MipsABIFlags
&Section
,
552 ContiguousBlobAccumulator
&CBA
) {
553 assert(Section
.Type
== llvm::ELF::SHT_MIPS_ABIFLAGS
&&
554 "Section type is not SHT_MIPS_ABIFLAGS");
556 object::Elf_Mips_ABIFlags
<ELFT
> Flags
;
558 SHeader
.sh_entsize
= sizeof(Flags
);
559 SHeader
.sh_size
= SHeader
.sh_entsize
;
561 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
562 Flags
.version
= Section
.Version
;
563 Flags
.isa_level
= Section
.ISALevel
;
564 Flags
.isa_rev
= Section
.ISARevision
;
565 Flags
.gpr_size
= Section
.GPRSize
;
566 Flags
.cpr1_size
= Section
.CPR1Size
;
567 Flags
.cpr2_size
= Section
.CPR2Size
;
568 Flags
.fp_abi
= Section
.FpABI
;
569 Flags
.isa_ext
= Section
.ISAExtension
;
570 Flags
.ases
= Section
.ASEs
;
571 Flags
.flags1
= Section
.Flags1
;
572 Flags
.flags2
= Section
.Flags2
;
573 OS
.write((const char *)&Flags
, sizeof(Flags
));
578 template <class ELFT
> bool ELFState
<ELFT
>::buildSectionIndex() {
579 for (unsigned i
= 0, e
= Doc
.Sections
.size(); i
!= e
; ++i
) {
580 StringRef Name
= Doc
.Sections
[i
]->Name
;
581 DotShStrtab
.add(Name
);
582 // "+ 1" to take into account the SHT_NULL entry.
583 if (SN2I
.addName(Name
, i
+ 1)) {
584 WithColor::error() << "Repeated section name: '" << Name
585 << "' at YAML section number " << i
<< ".\n";
590 auto SecNo
= 1 + Doc
.Sections
.size();
591 // Add special sections after input sections, if necessary.
592 for (const auto &Name
: implicitSectionNames())
593 if (!SN2I
.addName(Name
, SecNo
)) {
594 // Account for this section, since it wasn't in the Doc
596 DotShStrtab
.add(Name
);
599 DotShStrtab
.finalize();
603 template <class ELFT
>
605 ELFState
<ELFT
>::buildSymbolIndex(std::size_t &StartIndex
,
606 const std::vector
<ELFYAML::Symbol
> &Symbols
) {
607 for (const auto &Sym
: Symbols
) {
609 if (Sym
.Name
.empty())
611 if (SymN2I
.addName(Sym
.Name
, StartIndex
)) {
612 WithColor::error() << "Repeated symbol name: '" << Sym
.Name
<< "'.\n";
619 template <class ELFT
>
620 int ELFState
<ELFT
>::writeELF(raw_ostream
&OS
, const ELFYAML::Object
&Doc
) {
621 ELFState
<ELFT
> State(Doc
);
622 if (!State
.buildSectionIndex())
625 std::size_t StartSymIndex
= 0;
626 if (!State
.buildSymbolIndex(StartSymIndex
, Doc
.Symbols
.Local
) ||
627 !State
.buildSymbolIndex(StartSymIndex
, Doc
.Symbols
.Global
) ||
628 !State
.buildSymbolIndex(StartSymIndex
, Doc
.Symbols
.Weak
))
632 State
.initELFHeader(Header
);
634 // TODO: Flesh out section header support.
636 std::vector
<Elf_Phdr
> PHeaders
;
637 State
.initProgramHeaders(PHeaders
);
639 // XXX: This offset is tightly coupled with the order that we write
641 const size_t SectionContentBeginOffset
= Header
.e_ehsize
+
642 Header
.e_phentsize
* Header
.e_phnum
+
643 Header
.e_shentsize
* Header
.e_shnum
;
644 ContiguousBlobAccumulator
CBA(SectionContentBeginOffset
);
646 std::vector
<Elf_Shdr
> SHeaders
;
647 if(!State
.initSectionHeaders(SHeaders
, CBA
))
650 // Populate SHeaders with implicit sections not present in the Doc
651 for (const auto &Name
: State
.implicitSectionNames())
652 if (State
.SN2I
.get(Name
) >= SHeaders
.size())
653 SHeaders
.push_back({});
655 // Initialize the implicit sections
656 auto Index
= State
.SN2I
.get(".symtab");
657 State
.initSymtabSectionHeader(SHeaders
[Index
], SymtabType::Static
, CBA
);
658 Index
= State
.SN2I
.get(".strtab");
659 State
.initStrtabSectionHeader(SHeaders
[Index
], ".strtab", State
.DotStrtab
, CBA
);
660 Index
= State
.SN2I
.get(".shstrtab");
661 State
.initStrtabSectionHeader(SHeaders
[Index
], ".shstrtab", State
.DotShStrtab
, CBA
);
662 if (State
.hasDynamicSymbols()) {
663 Index
= State
.SN2I
.get(".dynsym");
664 State
.initSymtabSectionHeader(SHeaders
[Index
], SymtabType::Dynamic
, CBA
);
665 SHeaders
[Index
].sh_flags
|= ELF::SHF_ALLOC
;
666 Index
= State
.SN2I
.get(".dynstr");
667 State
.initStrtabSectionHeader(SHeaders
[Index
], ".dynstr", State
.DotDynstr
, CBA
);
668 SHeaders
[Index
].sh_flags
|= ELF::SHF_ALLOC
;
671 // Now we can decide segment offsets
672 State
.setProgramHeaderLayout(PHeaders
, SHeaders
);
674 OS
.write((const char *)&Header
, sizeof(Header
));
675 writeArrayData(OS
, makeArrayRef(PHeaders
));
676 writeArrayData(OS
, makeArrayRef(SHeaders
));
677 CBA
.writeBlobToStream(OS
);
681 template <class ELFT
> bool ELFState
<ELFT
>::hasDynamicSymbols() const {
682 return Doc
.DynamicSymbols
.Global
.size() > 0 ||
683 Doc
.DynamicSymbols
.Weak
.size() > 0 ||
684 Doc
.DynamicSymbols
.Local
.size() > 0;
687 template <class ELFT
>
688 SmallVector
<const char *, 5> ELFState
<ELFT
>::implicitSectionNames() const {
689 if (!hasDynamicSymbols())
690 return {".symtab", ".strtab", ".shstrtab"};
691 return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"};
694 static bool is64Bit(const ELFYAML::Object
&Doc
) {
695 return Doc
.Header
.Class
== ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64
);
698 static bool isLittleEndian(const ELFYAML::Object
&Doc
) {
699 return Doc
.Header
.Data
== ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB
);
702 int yaml2elf(llvm::ELFYAML::Object
&Doc
, raw_ostream
&Out
) {
704 if (isLittleEndian(Doc
))
705 return ELFState
<object::ELF64LE
>::writeELF(Out
, Doc
);
707 return ELFState
<object::ELF64BE
>::writeELF(Out
, Doc
);
709 if (isLittleEndian(Doc
))
710 return ELFState
<object::ELF32LE
>::writeELF(Out
, Doc
);
712 return ELFState
<object::ELF32BE
>::writeELF(Out
, Doc
);