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 void writeSectionContent(Elf_Shdr
&SHeader
,
163 const ELFYAML::DynamicSection
&Section
,
164 ContiguousBlobAccumulator
&CBA
);
165 bool hasDynamicSymbols() const;
166 SmallVector
<const char *, 5> implicitSectionNames() const;
168 // - SHT_NULL entry (placed first, i.e. 0'th entry)
169 // - symbol table (.symtab) (defaults to after last yaml section)
170 // - string table (.strtab) (defaults to after .symtab)
171 // - section header string table (.shstrtab) (defaults to after .strtab)
172 // - dynamic symbol table (.dynsym) (defaults to after .shstrtab)
173 // - dynamic string table (.dynstr) (defaults to after .dynsym)
174 unsigned getDotSymTabSecNo() const { return SN2I
.get(".symtab"); }
175 unsigned getDotStrTabSecNo() const { return SN2I
.get(".strtab"); }
176 unsigned getDotShStrTabSecNo() const { return SN2I
.get(".shstrtab"); }
177 unsigned getDotDynSymSecNo() const { return SN2I
.get(".dynsym"); }
178 unsigned getDotDynStrSecNo() const { return SN2I
.get(".dynstr"); }
179 unsigned getSectionCount() const { return SN2I
.size() + 1; }
181 ELFState(const ELFYAML::Object
&D
) : Doc(D
) {}
184 static int writeELF(raw_ostream
&OS
, const ELFYAML::Object
&Doc
);
186 } // end anonymous namespace
188 template <class ELFT
>
189 void ELFState
<ELFT
>::initELFHeader(Elf_Ehdr
&Header
) {
190 using namespace llvm::ELF
;
192 Header
.e_ident
[EI_MAG0
] = 0x7f;
193 Header
.e_ident
[EI_MAG1
] = 'E';
194 Header
.e_ident
[EI_MAG2
] = 'L';
195 Header
.e_ident
[EI_MAG3
] = 'F';
196 Header
.e_ident
[EI_CLASS
] = ELFT::Is64Bits
? ELFCLASS64
: ELFCLASS32
;
197 bool IsLittleEndian
= ELFT::TargetEndianness
== support::little
;
198 Header
.e_ident
[EI_DATA
] = IsLittleEndian
? ELFDATA2LSB
: ELFDATA2MSB
;
199 Header
.e_ident
[EI_VERSION
] = EV_CURRENT
;
200 Header
.e_ident
[EI_OSABI
] = Doc
.Header
.OSABI
;
201 Header
.e_ident
[EI_ABIVERSION
] = Doc
.Header
.ABIVersion
;
202 Header
.e_type
= Doc
.Header
.Type
;
203 Header
.e_machine
= Doc
.Header
.Machine
;
204 Header
.e_version
= EV_CURRENT
;
205 Header
.e_entry
= Doc
.Header
.Entry
;
206 Header
.e_phoff
= sizeof(Header
);
207 Header
.e_flags
= Doc
.Header
.Flags
;
208 Header
.e_ehsize
= sizeof(Elf_Ehdr
);
209 Header
.e_phentsize
= sizeof(Elf_Phdr
);
210 Header
.e_phnum
= Doc
.ProgramHeaders
.size();
211 Header
.e_shentsize
= sizeof(Elf_Shdr
);
212 // Immediately following the ELF header and program headers.
214 sizeof(Header
) + sizeof(Elf_Phdr
) * Doc
.ProgramHeaders
.size();
215 Header
.e_shnum
= getSectionCount();
216 Header
.e_shstrndx
= getDotShStrTabSecNo();
219 template <class ELFT
>
220 void ELFState
<ELFT
>::initProgramHeaders(std::vector
<Elf_Phdr
> &PHeaders
) {
221 for (const auto &YamlPhdr
: Doc
.ProgramHeaders
) {
223 Phdr
.p_type
= YamlPhdr
.Type
;
224 Phdr
.p_flags
= YamlPhdr
.Flags
;
225 Phdr
.p_vaddr
= YamlPhdr
.VAddr
;
226 Phdr
.p_paddr
= YamlPhdr
.PAddr
;
227 PHeaders
.push_back(Phdr
);
231 static bool convertSectionIndex(NameToIdxMap
&SN2I
, StringRef SecName
,
232 StringRef IndexSrc
, unsigned &IndexDest
) {
233 if (SN2I
.lookup(IndexSrc
, IndexDest
) && !to_integer(IndexSrc
, IndexDest
)) {
234 WithColor::error() << "Unknown section referenced: '" << IndexSrc
235 << "' at YAML section '" << SecName
<< "'.\n";
241 template <class ELFT
>
242 bool ELFState
<ELFT
>::initSectionHeaders(std::vector
<Elf_Shdr
> &SHeaders
,
243 ContiguousBlobAccumulator
&CBA
) {
244 // Ensure SHN_UNDEF entry is present. An all-zero section header is a
245 // valid SHN_UNDEF entry since SHT_NULL == 0.
248 SHeaders
.push_back(SHeader
);
250 for (const auto &Sec
: Doc
.Sections
) {
252 SHeader
.sh_name
= DotShStrtab
.getOffset(Sec
->Name
);
253 SHeader
.sh_type
= Sec
->Type
;
254 SHeader
.sh_flags
= Sec
->Flags
;
255 SHeader
.sh_addr
= Sec
->Address
;
256 SHeader
.sh_addralign
= Sec
->AddressAlign
;
258 if (!Sec
->Link
.empty()) {
260 if (!convertSectionIndex(SN2I
, Sec
->Name
, Sec
->Link
, Index
))
262 SHeader
.sh_link
= Index
;
265 if (auto S
= dyn_cast
<ELFYAML::RawContentSection
>(Sec
.get()))
266 writeSectionContent(SHeader
, *S
, CBA
);
267 else if (auto S
= dyn_cast
<ELFYAML::RelocationSection
>(Sec
.get())) {
269 // For relocation section set link to .symtab by default.
270 SHeader
.sh_link
= getDotSymTabSecNo();
273 if (!convertSectionIndex(SN2I
, S
->Name
, S
->RelocatableSec
, Index
))
275 SHeader
.sh_info
= Index
;
276 if (!writeSectionContent(SHeader
, *S
, CBA
))
278 } else if (auto S
= dyn_cast
<ELFYAML::Group
>(Sec
.get())) {
280 if (SymN2I
.lookup(S
->Signature
, SymIdx
) &&
281 !to_integer(S
->Signature
, SymIdx
)) {
282 WithColor::error() << "Unknown symbol referenced: '" << S
->Signature
283 << "' at YAML section '" << S
->Name
<< "'.\n";
286 SHeader
.sh_info
= SymIdx
;
287 if (!writeSectionContent(SHeader
, *S
, CBA
))
289 } else if (auto S
= dyn_cast
<ELFYAML::MipsABIFlags
>(Sec
.get())) {
290 if (!writeSectionContent(SHeader
, *S
, CBA
))
292 } else if (auto S
= dyn_cast
<ELFYAML::NoBitsSection
>(Sec
.get())) {
293 SHeader
.sh_entsize
= 0;
294 SHeader
.sh_size
= S
->Size
;
295 // SHT_NOBITS section does not have content
296 // so just to setup the section offset.
297 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
298 } else if (auto S
= dyn_cast
<ELFYAML::DynamicSection
>(Sec
.get())) {
299 writeSectionContent(SHeader
, *S
, CBA
);
301 llvm_unreachable("Unknown section type");
303 SHeaders
.push_back(SHeader
);
308 template <class ELFT
>
309 void ELFState
<ELFT
>::initSymtabSectionHeader(Elf_Shdr
&SHeader
,
311 ContiguousBlobAccumulator
&CBA
) {
313 bool IsStatic
= STType
== SymtabType::Static
;
314 SHeader
.sh_name
= DotShStrtab
.getOffset(IsStatic
? ".symtab" : ".dynsym");
315 SHeader
.sh_type
= IsStatic
? ELF::SHT_SYMTAB
: ELF::SHT_DYNSYM
;
316 SHeader
.sh_link
= IsStatic
? getDotStrTabSecNo() : getDotDynStrSecNo();
317 const auto &Symbols
= IsStatic
? Doc
.Symbols
: Doc
.DynamicSymbols
;
318 auto &Strtab
= IsStatic
? DotStrtab
: DotDynstr
;
319 // One greater than symbol table index of the last local symbol.
320 SHeader
.sh_info
= Symbols
.Local
.size() + 1;
321 SHeader
.sh_entsize
= sizeof(Elf_Sym
);
322 SHeader
.sh_addralign
= 8;
324 std::vector
<Elf_Sym
> Syms
;
326 // Ensure STN_UNDEF is present
332 // Add symbol names to .strtab or .dynstr.
333 for (const auto &Sym
: Symbols
.Local
)
334 Strtab
.add(Sym
.Name
);
335 for (const auto &Sym
: Symbols
.Global
)
336 Strtab
.add(Sym
.Name
);
337 for (const auto &Sym
: Symbols
.Weak
)
338 Strtab
.add(Sym
.Name
);
341 addSymbols(Symbols
.Local
, Syms
, ELF::STB_LOCAL
, Strtab
);
342 addSymbols(Symbols
.Global
, Syms
, ELF::STB_GLOBAL
, Strtab
);
343 addSymbols(Symbols
.Weak
, Syms
, ELF::STB_WEAK
, Strtab
);
346 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
),
348 SHeader
.sh_size
= arrayDataSize(makeArrayRef(Syms
));
351 template <class ELFT
>
352 void ELFState
<ELFT
>::initStrtabSectionHeader(Elf_Shdr
&SHeader
, StringRef Name
,
353 StringTableBuilder
&STB
,
354 ContiguousBlobAccumulator
&CBA
) {
356 SHeader
.sh_name
= DotShStrtab
.getOffset(Name
);
357 SHeader
.sh_type
= ELF::SHT_STRTAB
;
358 STB
.write(CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
));
359 SHeader
.sh_size
= STB
.getSize();
360 SHeader
.sh_addralign
= 1;
363 template <class ELFT
>
364 void ELFState
<ELFT
>::setProgramHeaderLayout(std::vector
<Elf_Phdr
> &PHeaders
,
365 std::vector
<Elf_Shdr
> &SHeaders
) {
366 uint32_t PhdrIdx
= 0;
367 for (auto &YamlPhdr
: Doc
.ProgramHeaders
) {
368 auto &PHeader
= PHeaders
[PhdrIdx
++];
370 if (YamlPhdr
.Sections
.size())
371 PHeader
.p_offset
= UINT32_MAX
;
373 PHeader
.p_offset
= 0;
375 // Find the minimum offset for the program header.
376 for (auto SecName
: YamlPhdr
.Sections
) {
378 SN2I
.lookup(SecName
.Section
, Index
);
379 const auto &SHeader
= SHeaders
[Index
];
380 PHeader
.p_offset
= std::min(PHeader
.p_offset
, SHeader
.sh_offset
);
383 // Find the maximum offset of the end of a section in order to set p_filesz.
384 PHeader
.p_filesz
= 0;
385 for (auto SecName
: YamlPhdr
.Sections
) {
387 SN2I
.lookup(SecName
.Section
, Index
);
388 const auto &SHeader
= SHeaders
[Index
];
389 uint64_t EndOfSection
;
390 if (SHeader
.sh_type
== llvm::ELF::SHT_NOBITS
)
391 EndOfSection
= SHeader
.sh_offset
;
393 EndOfSection
= SHeader
.sh_offset
+ SHeader
.sh_size
;
394 uint64_t EndOfSegment
= PHeader
.p_offset
+ PHeader
.p_filesz
;
395 EndOfSegment
= std::max(EndOfSegment
, EndOfSection
);
396 PHeader
.p_filesz
= EndOfSegment
- PHeader
.p_offset
;
399 // Find the memory size by adding the size of sections at the end of the
400 // segment. These should be empty (size of zero) and NOBITS sections.
401 PHeader
.p_memsz
= PHeader
.p_filesz
;
402 for (auto SecName
: YamlPhdr
.Sections
) {
404 SN2I
.lookup(SecName
.Section
, Index
);
405 const auto &SHeader
= SHeaders
[Index
];
406 if (SHeader
.sh_offset
== PHeader
.p_offset
+ PHeader
.p_filesz
)
407 PHeader
.p_memsz
+= SHeader
.sh_size
;
410 // Set the alignment of the segment to be the same as the maximum alignment
411 // of the sections with the same offset so that by default the segment
412 // has a valid and sensible alignment.
413 if (YamlPhdr
.Align
) {
414 PHeader
.p_align
= *YamlPhdr
.Align
;
417 for (auto SecName
: YamlPhdr
.Sections
) {
419 SN2I
.lookup(SecName
.Section
, Index
);
420 const auto &SHeader
= SHeaders
[Index
];
421 if (SHeader
.sh_offset
== PHeader
.p_offset
)
422 PHeader
.p_align
= std::max(PHeader
.p_align
, SHeader
.sh_addralign
);
428 template <class ELFT
>
429 void ELFState
<ELFT
>::addSymbols(const std::vector
<ELFYAML::Symbol
> &Symbols
,
430 std::vector
<Elf_Sym
> &Syms
,
431 unsigned SymbolBinding
,
432 const StringTableBuilder
&Strtab
) {
433 for (const auto &Sym
: Symbols
) {
436 if (!Sym
.Name
.empty())
437 Symbol
.st_name
= Strtab
.getOffset(Sym
.Name
);
438 Symbol
.setBindingAndType(SymbolBinding
, Sym
.Type
);
439 if (!Sym
.Section
.empty()) {
441 if (SN2I
.lookup(Sym
.Section
, Index
)) {
442 WithColor::error() << "Unknown section referenced: '" << Sym
.Section
443 << "' by YAML symbol " << Sym
.Name
<< ".\n";
446 Symbol
.st_shndx
= Index
;
447 } else if (Sym
.Index
) {
448 Symbol
.st_shndx
= *Sym
.Index
;
450 // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
451 Symbol
.st_value
= Sym
.Value
;
452 Symbol
.st_other
= Sym
.Other
;
453 Symbol
.st_size
= Sym
.Size
;
454 Syms
.push_back(Symbol
);
458 template <class ELFT
>
460 ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
461 const ELFYAML::RawContentSection
&Section
,
462 ContiguousBlobAccumulator
&CBA
) {
463 assert(Section
.Size
>= Section
.Content
.binary_size() &&
464 "Section size and section content are inconsistent");
466 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
467 Section
.Content
.writeAsBinary(OS
);
468 for (auto i
= Section
.Content
.binary_size(); i
< Section
.Size
; ++i
)
471 SHeader
.sh_entsize
= *Section
.EntSize
;
472 else if (Section
.Type
== llvm::ELF::SHT_RELR
)
473 SHeader
.sh_entsize
= sizeof(Elf_Relr
);
475 SHeader
.sh_entsize
= 0;
476 SHeader
.sh_size
= Section
.Size
;
479 static bool isMips64EL(const ELFYAML::Object
&Doc
) {
480 return Doc
.Header
.Machine
== ELFYAML::ELF_EM(llvm::ELF::EM_MIPS
) &&
481 Doc
.Header
.Class
== ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64
) &&
482 Doc
.Header
.Data
== ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB
);
485 template <class ELFT
>
487 ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
488 const ELFYAML::RelocationSection
&Section
,
489 ContiguousBlobAccumulator
&CBA
) {
490 assert((Section
.Type
== llvm::ELF::SHT_REL
||
491 Section
.Type
== llvm::ELF::SHT_RELA
) &&
492 "Section type is not SHT_REL nor SHT_RELA");
494 bool IsRela
= Section
.Type
== llvm::ELF::SHT_RELA
;
495 SHeader
.sh_entsize
= IsRela
? sizeof(Elf_Rela
) : sizeof(Elf_Rel
);
496 SHeader
.sh_size
= SHeader
.sh_entsize
* Section
.Relocations
.size();
498 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
500 for (const auto &Rel
: Section
.Relocations
) {
502 // Some special relocation, R_ARM_v4BX for instance, does not have
503 // an external reference. So it ignores the return value of lookup()
506 SymN2I
.lookup(*Rel
.Symbol
, SymIdx
);
511 REntry
.r_offset
= Rel
.Offset
;
512 REntry
.r_addend
= Rel
.Addend
;
513 REntry
.setSymbolAndType(SymIdx
, Rel
.Type
, isMips64EL(Doc
));
514 OS
.write((const char *)&REntry
, sizeof(REntry
));
518 REntry
.r_offset
= Rel
.Offset
;
519 REntry
.setSymbolAndType(SymIdx
, Rel
.Type
, isMips64EL(Doc
));
520 OS
.write((const char *)&REntry
, sizeof(REntry
));
526 template <class ELFT
>
527 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
528 const ELFYAML::Group
&Section
,
529 ContiguousBlobAccumulator
&CBA
) {
530 typedef typename
ELFT::Word Elf_Word
;
531 assert(Section
.Type
== llvm::ELF::SHT_GROUP
&&
532 "Section type is not SHT_GROUP");
534 SHeader
.sh_entsize
= sizeof(Elf_Word
);
535 SHeader
.sh_size
= SHeader
.sh_entsize
* Section
.Members
.size();
537 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
539 for (auto member
: Section
.Members
) {
541 unsigned int sectionIndex
= 0;
542 if (member
.sectionNameOrType
== "GRP_COMDAT")
543 sectionIndex
= llvm::ELF::GRP_COMDAT
;
544 else if (!convertSectionIndex(SN2I
, Section
.Name
, member
.sectionNameOrType
,
548 OS
.write((const char *)&SIdx
, sizeof(SIdx
));
553 template <class ELFT
>
554 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
555 const ELFYAML::MipsABIFlags
&Section
,
556 ContiguousBlobAccumulator
&CBA
) {
557 assert(Section
.Type
== llvm::ELF::SHT_MIPS_ABIFLAGS
&&
558 "Section type is not SHT_MIPS_ABIFLAGS");
560 object::Elf_Mips_ABIFlags
<ELFT
> Flags
;
562 SHeader
.sh_entsize
= sizeof(Flags
);
563 SHeader
.sh_size
= SHeader
.sh_entsize
;
565 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
566 Flags
.version
= Section
.Version
;
567 Flags
.isa_level
= Section
.ISALevel
;
568 Flags
.isa_rev
= Section
.ISARevision
;
569 Flags
.gpr_size
= Section
.GPRSize
;
570 Flags
.cpr1_size
= Section
.CPR1Size
;
571 Flags
.cpr2_size
= Section
.CPR2Size
;
572 Flags
.fp_abi
= Section
.FpABI
;
573 Flags
.isa_ext
= Section
.ISAExtension
;
574 Flags
.ases
= Section
.ASEs
;
575 Flags
.flags1
= Section
.Flags1
;
576 Flags
.flags2
= Section
.Flags2
;
577 OS
.write((const char *)&Flags
, sizeof(Flags
));
582 template <class ELFT
>
583 void ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
584 const ELFYAML::DynamicSection
&Section
,
585 ContiguousBlobAccumulator
&CBA
) {
586 typedef typename
ELFT::Addr Elf_Addr
;
587 assert(Section
.Type
== llvm::ELF::SHT_DYNAMIC
&&
588 "Section type is not SHT_DYNAMIC");
590 SHeader
.sh_size
= 2 * sizeof(Elf_Addr
) * Section
.Entries
.size();
592 SHeader
.sh_entsize
= *Section
.EntSize
;
594 SHeader
.sh_entsize
= sizeof(Elf_Dyn
);
596 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
597 for (const ELFYAML::DynamicEntry
&DE
: Section
.Entries
) {
598 Elf_Addr Tag
= (Elf_Addr
)DE
.Tag
;
599 OS
.write((const char *)&Tag
, sizeof(Elf_Addr
));
600 Elf_Addr Val
= (Elf_Addr
)DE
.Val
;
601 OS
.write((const char *)&Val
, sizeof(Elf_Addr
));
605 template <class ELFT
> bool ELFState
<ELFT
>::buildSectionIndex() {
606 for (unsigned i
= 0, e
= Doc
.Sections
.size(); i
!= e
; ++i
) {
607 StringRef Name
= Doc
.Sections
[i
]->Name
;
608 DotShStrtab
.add(Name
);
609 // "+ 1" to take into account the SHT_NULL entry.
610 if (SN2I
.addName(Name
, i
+ 1)) {
611 WithColor::error() << "Repeated section name: '" << Name
612 << "' at YAML section number " << i
<< ".\n";
617 auto SecNo
= 1 + Doc
.Sections
.size();
618 // Add special sections after input sections, if necessary.
619 for (const auto &Name
: implicitSectionNames())
620 if (!SN2I
.addName(Name
, SecNo
)) {
621 // Account for this section, since it wasn't in the Doc
623 DotShStrtab
.add(Name
);
626 DotShStrtab
.finalize();
630 template <class ELFT
>
632 ELFState
<ELFT
>::buildSymbolIndex(std::size_t &StartIndex
,
633 const std::vector
<ELFYAML::Symbol
> &Symbols
) {
634 for (const auto &Sym
: Symbols
) {
636 if (Sym
.Name
.empty())
638 if (SymN2I
.addName(Sym
.Name
, StartIndex
)) {
639 WithColor::error() << "Repeated symbol name: '" << Sym
.Name
<< "'.\n";
646 template <class ELFT
>
647 int ELFState
<ELFT
>::writeELF(raw_ostream
&OS
, const ELFYAML::Object
&Doc
) {
648 ELFState
<ELFT
> State(Doc
);
649 if (!State
.buildSectionIndex())
652 std::size_t StartSymIndex
= 0;
653 if (!State
.buildSymbolIndex(StartSymIndex
, Doc
.Symbols
.Local
) ||
654 !State
.buildSymbolIndex(StartSymIndex
, Doc
.Symbols
.Global
) ||
655 !State
.buildSymbolIndex(StartSymIndex
, Doc
.Symbols
.Weak
))
659 State
.initELFHeader(Header
);
661 // TODO: Flesh out section header support.
663 std::vector
<Elf_Phdr
> PHeaders
;
664 State
.initProgramHeaders(PHeaders
);
666 // XXX: This offset is tightly coupled with the order that we write
668 const size_t SectionContentBeginOffset
= Header
.e_ehsize
+
669 Header
.e_phentsize
* Header
.e_phnum
+
670 Header
.e_shentsize
* Header
.e_shnum
;
671 ContiguousBlobAccumulator
CBA(SectionContentBeginOffset
);
673 std::vector
<Elf_Shdr
> SHeaders
;
674 if(!State
.initSectionHeaders(SHeaders
, CBA
))
677 // Populate SHeaders with implicit sections not present in the Doc
678 for (const auto &Name
: State
.implicitSectionNames())
679 if (State
.SN2I
.get(Name
) >= SHeaders
.size())
680 SHeaders
.push_back({});
682 // Initialize the implicit sections
683 auto Index
= State
.SN2I
.get(".symtab");
684 State
.initSymtabSectionHeader(SHeaders
[Index
], SymtabType::Static
, CBA
);
685 Index
= State
.SN2I
.get(".strtab");
686 State
.initStrtabSectionHeader(SHeaders
[Index
], ".strtab", State
.DotStrtab
, CBA
);
687 Index
= State
.SN2I
.get(".shstrtab");
688 State
.initStrtabSectionHeader(SHeaders
[Index
], ".shstrtab", State
.DotShStrtab
, CBA
);
689 if (State
.hasDynamicSymbols()) {
690 Index
= State
.SN2I
.get(".dynsym");
691 State
.initSymtabSectionHeader(SHeaders
[Index
], SymtabType::Dynamic
, CBA
);
692 SHeaders
[Index
].sh_flags
|= ELF::SHF_ALLOC
;
693 Index
= State
.SN2I
.get(".dynstr");
694 State
.initStrtabSectionHeader(SHeaders
[Index
], ".dynstr", State
.DotDynstr
, CBA
);
695 SHeaders
[Index
].sh_flags
|= ELF::SHF_ALLOC
;
698 // Now we can decide segment offsets
699 State
.setProgramHeaderLayout(PHeaders
, SHeaders
);
701 OS
.write((const char *)&Header
, sizeof(Header
));
702 writeArrayData(OS
, makeArrayRef(PHeaders
));
703 writeArrayData(OS
, makeArrayRef(SHeaders
));
704 CBA
.writeBlobToStream(OS
);
708 template <class ELFT
> bool ELFState
<ELFT
>::hasDynamicSymbols() const {
709 return Doc
.DynamicSymbols
.Global
.size() > 0 ||
710 Doc
.DynamicSymbols
.Weak
.size() > 0 ||
711 Doc
.DynamicSymbols
.Local
.size() > 0;
714 template <class ELFT
>
715 SmallVector
<const char *, 5> ELFState
<ELFT
>::implicitSectionNames() const {
716 if (!hasDynamicSymbols())
717 return {".symtab", ".strtab", ".shstrtab"};
718 return {".symtab", ".strtab", ".shstrtab", ".dynsym", ".dynstr"};
721 static bool is64Bit(const ELFYAML::Object
&Doc
) {
722 return Doc
.Header
.Class
== ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64
);
725 static bool isLittleEndian(const ELFYAML::Object
&Doc
) {
726 return Doc
.Header
.Data
== ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB
);
729 int yaml2elf(llvm::ELFYAML::Object
&Doc
, raw_ostream
&Out
) {
731 if (isLittleEndian(Doc
))
732 return ELFState
<object::ELF64LE
>::writeELF(Out
, Doc
);
734 return ELFState
<object::ELF64BE
>::writeELF(Out
, Doc
);
736 if (isLittleEndian(Doc
))
737 return ELFState
<object::ELF32LE
>::writeELF(Out
, Doc
);
739 return ELFState
<object::ELF32BE
>::writeELF(Out
, Doc
);