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/ADT/StringSet.h"
21 #include "llvm/Support/EndianStream.h"
22 #include "llvm/Support/MemoryBuffer.h"
23 #include "llvm/Support/WithColor.h"
24 #include "llvm/Support/YAMLTraits.h"
25 #include "llvm/Support/raw_ostream.h"
29 // This class is used to build up a contiguous binary blob while keeping
30 // track of an offset in the output (which notionally begins at
33 class ContiguousBlobAccumulator
{
34 const uint64_t InitialOffset
;
35 SmallVector
<char, 128> Buf
;
36 raw_svector_ostream OS
;
38 /// \returns The new offset.
39 uint64_t padToAlignment(unsigned Align
) {
42 uint64_t CurrentOffset
= InitialOffset
+ OS
.tell();
43 uint64_t AlignedOffset
= alignTo(CurrentOffset
, Align
);
44 OS
.write_zeros(AlignedOffset
- CurrentOffset
);
45 return AlignedOffset
; // == CurrentOffset;
49 ContiguousBlobAccumulator(uint64_t InitialOffset_
)
50 : InitialOffset(InitialOffset_
), Buf(), OS(Buf
) {}
51 template <class Integer
>
52 raw_ostream
&getOSAndAlignedOffset(Integer
&Offset
, unsigned Align
) {
53 Offset
= padToAlignment(Align
);
56 void writeBlobToStream(raw_ostream
&Out
) { Out
<< OS
.str(); }
58 } // end anonymous namespace
60 // Used to keep track of section and symbol names, so that in the YAML file
61 // sections and symbols can be referenced by name instead of by index.
64 StringMap
<unsigned> Map
;
67 /// \Returns false if name is already present in the map.
68 bool addName(StringRef Name
, unsigned Ndx
) {
69 return Map
.insert({Name
, Ndx
}).second
;
71 /// \Returns false if name is not present in the map.
72 bool lookup(StringRef Name
, unsigned &Idx
) const {
73 auto I
= Map
.find(Name
);
79 /// Asserts if name is not present in the map.
80 unsigned get(StringRef Name
) const {
82 if (lookup(Name
, Idx
))
84 assert(false && "Expected section not found in index");
87 unsigned size() const { return Map
.size(); }
89 } // end anonymous namespace
92 static size_t arrayDataSize(ArrayRef
<T
> A
) {
93 return A
.size() * sizeof(T
);
97 static void writeArrayData(raw_ostream
&OS
, ArrayRef
<T
> A
) {
98 OS
.write((const char *)A
.data(), arrayDataSize(A
));
102 static void zero(T
&Obj
) {
103 memset(&Obj
, 0, sizeof(Obj
));
107 /// "Single point of truth" for the ELF file construction.
108 /// TODO: This class still has a ways to go before it is truly a "single
110 template <class ELFT
>
112 typedef typename
ELFT::Ehdr Elf_Ehdr
;
113 typedef typename
ELFT::Phdr Elf_Phdr
;
114 typedef typename
ELFT::Shdr Elf_Shdr
;
115 typedef typename
ELFT::Sym Elf_Sym
;
116 typedef typename
ELFT::Rel Elf_Rel
;
117 typedef typename
ELFT::Rela Elf_Rela
;
118 typedef typename
ELFT::Relr Elf_Relr
;
119 typedef typename
ELFT::Dyn Elf_Dyn
;
121 enum class SymtabType
{ Static
, Dynamic
};
123 /// The future ".strtab" section.
124 StringTableBuilder DotStrtab
{StringTableBuilder::ELF
};
126 /// The future ".shstrtab" section.
127 StringTableBuilder DotShStrtab
{StringTableBuilder::ELF
};
129 /// The future ".dynstr" section.
130 StringTableBuilder DotDynstr
{StringTableBuilder::ELF
};
134 ELFYAML::Object
&Doc
;
136 bool buildSectionIndex();
137 bool buildSymbolIndex(ArrayRef
<ELFYAML::Symbol
> Symbols
);
138 void initELFHeader(Elf_Ehdr
&Header
);
139 void initProgramHeaders(std::vector
<Elf_Phdr
> &PHeaders
);
140 bool initImplicitHeader(ELFState
<ELFT
> &State
, ContiguousBlobAccumulator
&CBA
,
141 Elf_Shdr
&Header
, StringRef SecName
,
142 ELFYAML::Section
*YAMLSec
);
143 bool initSectionHeaders(ELFState
<ELFT
> &State
,
144 std::vector
<Elf_Shdr
> &SHeaders
,
145 ContiguousBlobAccumulator
&CBA
);
146 void initSymtabSectionHeader(Elf_Shdr
&SHeader
, SymtabType STType
,
147 ContiguousBlobAccumulator
&CBA
,
148 ELFYAML::Section
*YAMLSec
);
149 void initStrtabSectionHeader(Elf_Shdr
&SHeader
, StringRef Name
,
150 StringTableBuilder
&STB
,
151 ContiguousBlobAccumulator
&CBA
,
152 ELFYAML::Section
*YAMLSec
);
153 void setProgramHeaderLayout(std::vector
<Elf_Phdr
> &PHeaders
,
154 std::vector
<Elf_Shdr
> &SHeaders
);
155 bool writeSectionContent(Elf_Shdr
&SHeader
,
156 const ELFYAML::RawContentSection
&Section
,
157 ContiguousBlobAccumulator
&CBA
);
158 bool writeSectionContent(Elf_Shdr
&SHeader
,
159 const ELFYAML::RelocationSection
&Section
,
160 ContiguousBlobAccumulator
&CBA
);
161 bool writeSectionContent(Elf_Shdr
&SHeader
, const ELFYAML::Group
&Group
,
162 ContiguousBlobAccumulator
&CBA
);
163 bool writeSectionContent(Elf_Shdr
&SHeader
,
164 const ELFYAML::SymverSection
&Section
,
165 ContiguousBlobAccumulator
&CBA
);
166 bool writeSectionContent(Elf_Shdr
&SHeader
,
167 const ELFYAML::VerneedSection
&Section
,
168 ContiguousBlobAccumulator
&CBA
);
169 bool writeSectionContent(Elf_Shdr
&SHeader
,
170 const ELFYAML::VerdefSection
&Section
,
171 ContiguousBlobAccumulator
&CBA
);
172 bool writeSectionContent(Elf_Shdr
&SHeader
,
173 const ELFYAML::MipsABIFlags
&Section
,
174 ContiguousBlobAccumulator
&CBA
);
175 bool writeSectionContent(Elf_Shdr
&SHeader
,
176 const ELFYAML::DynamicSection
&Section
,
177 ContiguousBlobAccumulator
&CBA
);
178 ELFState(ELFYAML::Object
&D
);
181 static int writeELF(raw_ostream
&OS
, ELFYAML::Object
&Doc
);
184 void finalizeStrings();
186 } // end anonymous namespace
188 template <class ELFT
>
189 ELFState
<ELFT
>::ELFState(ELFYAML::Object
&D
) : Doc(D
) {
190 StringSet
<> DocSections
;
191 for (std::unique_ptr
<ELFYAML::Section
> &D
: Doc
.Sections
)
192 if (!D
->Name
.empty())
193 DocSections
.insert(D
->Name
);
195 // Insert SHT_NULL section implicitly when it is not defined in YAML.
196 if (Doc
.Sections
.empty() || Doc
.Sections
.front()->Type
!= ELF::SHT_NULL
)
198 Doc
.Sections
.begin(),
199 llvm::make_unique
<ELFYAML::Section
>(
200 ELFYAML::Section::SectionKind::RawContent
, /*IsImplicit=*/true));
202 std::vector
<StringRef
> ImplicitSections
= {".symtab", ".strtab", ".shstrtab"};
203 if (!Doc
.DynamicSymbols
.empty())
204 ImplicitSections
.insert(ImplicitSections
.end(), {".dynsym", ".dynstr"});
206 // Insert placeholders for implicit sections that are not
207 // defined explicitly in YAML.
208 for (StringRef SecName
: ImplicitSections
) {
209 if (DocSections
.count(SecName
))
212 std::unique_ptr
<ELFYAML::Section
> Sec
= llvm::make_unique
<ELFYAML::Section
>(
213 ELFYAML::Section::SectionKind::RawContent
, true /*IsImplicit*/);
215 Doc
.Sections
.push_back(std::move(Sec
));
219 template <class ELFT
>
220 void ELFState
<ELFT
>::initELFHeader(Elf_Ehdr
&Header
) {
221 using namespace llvm::ELF
;
223 Header
.e_ident
[EI_MAG0
] = 0x7f;
224 Header
.e_ident
[EI_MAG1
] = 'E';
225 Header
.e_ident
[EI_MAG2
] = 'L';
226 Header
.e_ident
[EI_MAG3
] = 'F';
227 Header
.e_ident
[EI_CLASS
] = ELFT::Is64Bits
? ELFCLASS64
: ELFCLASS32
;
228 Header
.e_ident
[EI_DATA
] = Doc
.Header
.Data
;
229 Header
.e_ident
[EI_VERSION
] = EV_CURRENT
;
230 Header
.e_ident
[EI_OSABI
] = Doc
.Header
.OSABI
;
231 Header
.e_ident
[EI_ABIVERSION
] = Doc
.Header
.ABIVersion
;
232 Header
.e_type
= Doc
.Header
.Type
;
233 Header
.e_machine
= Doc
.Header
.Machine
;
234 Header
.e_version
= EV_CURRENT
;
235 Header
.e_entry
= Doc
.Header
.Entry
;
236 Header
.e_phoff
= sizeof(Header
);
237 Header
.e_flags
= Doc
.Header
.Flags
;
238 Header
.e_ehsize
= sizeof(Elf_Ehdr
);
239 Header
.e_phentsize
= sizeof(Elf_Phdr
);
240 Header
.e_phnum
= Doc
.ProgramHeaders
.size();
243 Doc
.Header
.SHEntSize
? (uint16_t)*Doc
.Header
.SHEntSize
: sizeof(Elf_Shdr
);
244 // Immediately following the ELF header and program headers.
247 ? (typename
ELFT::uint
)(*Doc
.Header
.SHOffset
)
248 : sizeof(Header
) + sizeof(Elf_Phdr
) * Doc
.ProgramHeaders
.size();
250 Doc
.Header
.SHNum
? (uint16_t)*Doc
.Header
.SHNum
: Doc
.Sections
.size();
251 Header
.e_shstrndx
= Doc
.Header
.SHStrNdx
? (uint16_t)*Doc
.Header
.SHStrNdx
252 : SN2I
.get(".shstrtab");
255 template <class ELFT
>
256 void ELFState
<ELFT
>::initProgramHeaders(std::vector
<Elf_Phdr
> &PHeaders
) {
257 for (const auto &YamlPhdr
: Doc
.ProgramHeaders
) {
259 Phdr
.p_type
= YamlPhdr
.Type
;
260 Phdr
.p_flags
= YamlPhdr
.Flags
;
261 Phdr
.p_vaddr
= YamlPhdr
.VAddr
;
262 Phdr
.p_paddr
= YamlPhdr
.PAddr
;
263 PHeaders
.push_back(Phdr
);
267 static bool convertSectionIndex(NameToIdxMap
&SN2I
, StringRef SecName
,
268 StringRef IndexSrc
, unsigned &IndexDest
) {
269 if (!SN2I
.lookup(IndexSrc
, IndexDest
) && !to_integer(IndexSrc
, IndexDest
)) {
270 WithColor::error() << "Unknown section referenced: '" << IndexSrc
271 << "' at YAML section '" << SecName
<< "'.\n";
277 template <class ELFT
>
278 bool ELFState
<ELFT
>::initImplicitHeader(ELFState
<ELFT
> &State
,
279 ContiguousBlobAccumulator
&CBA
,
280 Elf_Shdr
&Header
, StringRef SecName
,
281 ELFYAML::Section
*YAMLSec
) {
282 // Check if the header was already initialized.
283 if (Header
.sh_offset
)
286 if (SecName
== ".symtab")
287 State
.initSymtabSectionHeader(Header
, SymtabType::Static
, CBA
, YAMLSec
);
288 else if (SecName
== ".strtab")
289 State
.initStrtabSectionHeader(Header
, SecName
, State
.DotStrtab
, CBA
,
291 else if (SecName
== ".shstrtab")
292 State
.initStrtabSectionHeader(Header
, SecName
, State
.DotShStrtab
, CBA
,
295 else if (SecName
== ".dynsym")
296 State
.initSymtabSectionHeader(Header
, SymtabType::Dynamic
, CBA
, YAMLSec
);
297 else if (SecName
== ".dynstr")
298 State
.initStrtabSectionHeader(Header
, SecName
, State
.DotDynstr
, CBA
,
303 // Override the sh_offset/sh_size fields if requested.
305 if (YAMLSec
->ShOffset
)
306 Header
.sh_offset
= *YAMLSec
->ShOffset
;
308 Header
.sh_size
= *YAMLSec
->ShSize
;
314 static StringRef
dropUniqueSuffix(StringRef S
) {
315 size_t SuffixPos
= S
.rfind(" [");
316 if (SuffixPos
== StringRef::npos
)
318 return S
.substr(0, SuffixPos
);
321 template <class ELFT
>
322 bool ELFState
<ELFT
>::initSectionHeaders(ELFState
<ELFT
> &State
,
323 std::vector
<Elf_Shdr
> &SHeaders
,
324 ContiguousBlobAccumulator
&CBA
) {
325 // Ensure SHN_UNDEF entry is present. An all-zero section header is a
326 // valid SHN_UNDEF entry since SHT_NULL == 0.
327 SHeaders
.resize(Doc
.Sections
.size());
329 for (size_t I
= 0; I
< Doc
.Sections
.size(); ++I
) {
330 ELFYAML::Section
*Sec
= Doc
.Sections
[I
].get();
331 if (I
== 0 && Sec
->IsImplicit
)
334 // We have a few sections like string or symbol tables that are usually
335 // added implicitly to the end. However, if they are explicitly specified
336 // in the YAML, we need to write them here. This ensures the file offset
338 Elf_Shdr
&SHeader
= SHeaders
[I
];
339 if (initImplicitHeader(State
, CBA
, SHeader
, Sec
->Name
,
340 Sec
->IsImplicit
? nullptr : Sec
))
343 assert(Sec
&& "It can't be null unless it is an implicit section. But all "
344 "implicit sections should already have been handled above.");
346 SHeader
.sh_name
= DotShStrtab
.getOffset(dropUniqueSuffix(Sec
->Name
));
347 SHeader
.sh_type
= Sec
->Type
;
349 SHeader
.sh_flags
= *Sec
->Flags
;
350 SHeader
.sh_addr
= Sec
->Address
;
351 SHeader
.sh_addralign
= Sec
->AddressAlign
;
353 if (!Sec
->Link
.empty()) {
355 if (!convertSectionIndex(SN2I
, Sec
->Name
, Sec
->Link
, Index
))
357 SHeader
.sh_link
= Index
;
361 if (auto RawSec
= dyn_cast
<ELFYAML::RawContentSection
>(Sec
)) {
362 // We do not write any content for special SHN_UNDEF section.
364 SHeader
.sh_size
= *RawSec
->Size
;
366 SHeader
.sh_info
= *RawSec
->Info
;
369 SHeader
.sh_entsize
= *Sec
->EntSize
;
370 } else if (auto S
= dyn_cast
<ELFYAML::RawContentSection
>(Sec
)) {
371 if (!writeSectionContent(SHeader
, *S
, CBA
))
373 } else if (auto S
= dyn_cast
<ELFYAML::RelocationSection
>(Sec
)) {
374 if (!writeSectionContent(SHeader
, *S
, CBA
))
376 } else if (auto S
= dyn_cast
<ELFYAML::Group
>(Sec
)) {
377 if (!writeSectionContent(SHeader
, *S
, CBA
))
379 } else if (auto S
= dyn_cast
<ELFYAML::MipsABIFlags
>(Sec
)) {
380 if (!writeSectionContent(SHeader
, *S
, CBA
))
382 } else if (auto S
= dyn_cast
<ELFYAML::NoBitsSection
>(Sec
)) {
383 SHeader
.sh_entsize
= 0;
384 SHeader
.sh_size
= S
->Size
;
385 // SHT_NOBITS section does not have content
386 // so just to setup the section offset.
387 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
388 } else if (auto S
= dyn_cast
<ELFYAML::DynamicSection
>(Sec
)) {
389 if (!writeSectionContent(SHeader
, *S
, CBA
))
391 } else if (auto S
= dyn_cast
<ELFYAML::SymverSection
>(Sec
)) {
392 if (!writeSectionContent(SHeader
, *S
, CBA
))
394 } else if (auto S
= dyn_cast
<ELFYAML::VerneedSection
>(Sec
)) {
395 if (!writeSectionContent(SHeader
, *S
, CBA
))
397 } else if (auto S
= dyn_cast
<ELFYAML::VerdefSection
>(Sec
)) {
398 if (!writeSectionContent(SHeader
, *S
, CBA
))
401 llvm_unreachable("Unknown section type");
403 // Override the sh_offset/sh_size fields if requested.
406 SHeader
.sh_offset
= *Sec
->ShOffset
;
408 SHeader
.sh_size
= *Sec
->ShSize
;
415 static size_t findFirstNonGlobal(ArrayRef
<ELFYAML::Symbol
> Symbols
) {
416 for (size_t I
= 0; I
< Symbols
.size(); ++I
)
417 if (Symbols
[I
].Binding
.value
!= ELF::STB_LOCAL
)
419 return Symbols
.size();
422 static uint64_t writeRawSectionData(raw_ostream
&OS
,
423 const ELFYAML::RawContentSection
&RawSec
) {
424 size_t ContentSize
= 0;
425 if (RawSec
.Content
) {
426 RawSec
.Content
->writeAsBinary(OS
);
427 ContentSize
= RawSec
.Content
->binary_size();
433 OS
.write_zeros(*RawSec
.Size
- ContentSize
);
437 template <class ELFT
>
438 static std::vector
<typename
ELFT::Sym
>
439 toELFSymbols(NameToIdxMap
&SN2I
, ArrayRef
<ELFYAML::Symbol
> Symbols
,
440 const StringTableBuilder
&Strtab
) {
441 using Elf_Sym
= typename
ELFT::Sym
;
443 std::vector
<Elf_Sym
> Ret
;
444 Ret
.resize(Symbols
.size() + 1);
447 for (const auto &Sym
: Symbols
) {
448 Elf_Sym
&Symbol
= Ret
[++I
];
450 // If NameIndex, which contains the name offset, is explicitly specified, we
451 // use it. This is useful for preparing broken objects. Otherwise, we add
452 // the specified Name to the string table builder to get its offset.
454 Symbol
.st_name
= *Sym
.NameIndex
;
455 else if (!Sym
.Name
.empty())
456 Symbol
.st_name
= Strtab
.getOffset(dropUniqueSuffix(Sym
.Name
));
458 Symbol
.setBindingAndType(Sym
.Binding
, Sym
.Type
);
459 if (!Sym
.Section
.empty()) {
461 if (!SN2I
.lookup(Sym
.Section
, Index
)) {
462 WithColor::error() << "Unknown section referenced: '" << Sym
.Section
463 << "' by YAML symbol " << Sym
.Name
<< ".\n";
466 Symbol
.st_shndx
= Index
;
467 } else if (Sym
.Index
) {
468 Symbol
.st_shndx
= *Sym
.Index
;
470 // else Symbol.st_shndex == SHN_UNDEF (== 0), since it was zero'd earlier.
471 Symbol
.st_value
= Sym
.Value
;
472 Symbol
.st_other
= Sym
.Other
;
473 Symbol
.st_size
= Sym
.Size
;
479 template <class ELFT
>
480 void ELFState
<ELFT
>::initSymtabSectionHeader(Elf_Shdr
&SHeader
,
482 ContiguousBlobAccumulator
&CBA
,
483 ELFYAML::Section
*YAMLSec
) {
485 bool IsStatic
= STType
== SymtabType::Static
;
486 const auto &Symbols
= IsStatic
? Doc
.Symbols
: Doc
.DynamicSymbols
;
488 ELFYAML::RawContentSection
*RawSec
=
489 dyn_cast_or_null
<ELFYAML::RawContentSection
>(YAMLSec
);
490 if (RawSec
&& !Symbols
.empty() && (RawSec
->Content
|| RawSec
->Size
)) {
492 WithColor::error() << "Cannot specify both `Content` and " +
493 (IsStatic
? Twine("`Symbols`")
494 : Twine("`DynamicSymbols`")) +
495 " for symbol table section '"
496 << RawSec
->Name
<< "'.\n";
498 WithColor::error() << "Cannot specify both `Size` and " +
499 (IsStatic
? Twine("`Symbols`")
500 : Twine("`DynamicSymbols`")) +
501 " for symbol table section '"
502 << RawSec
->Name
<< "'.\n";
507 SHeader
.sh_name
= DotShStrtab
.getOffset(IsStatic
? ".symtab" : ".dynsym");
510 SHeader
.sh_type
= YAMLSec
->Type
;
512 SHeader
.sh_type
= IsStatic
? ELF::SHT_SYMTAB
: ELF::SHT_DYNSYM
;
514 if (RawSec
&& !RawSec
->Link
.empty()) {
515 // If the Link field is explicitly defined in the document,
518 if (!convertSectionIndex(SN2I
, RawSec
->Name
, RawSec
->Link
, Index
))
520 SHeader
.sh_link
= Index
;
522 // When we describe the .dynsym section in the document explicitly, it is
523 // allowed to omit the "DynamicSymbols" tag. In this case .dynstr is not
524 // added implicitly and we should be able to leave the Link zeroed if
525 // .dynstr is not defined.
528 Link
= SN2I
.get(".strtab");
530 SN2I
.lookup(".dynstr", Link
);
531 SHeader
.sh_link
= Link
;
534 if (YAMLSec
&& YAMLSec
->Flags
)
535 SHeader
.sh_flags
= *YAMLSec
->Flags
;
537 SHeader
.sh_flags
= ELF::SHF_ALLOC
;
539 // If the symbol table section is explicitly described in the YAML
540 // then we should set the fields requested.
541 SHeader
.sh_info
= (RawSec
&& RawSec
->Info
) ? (unsigned)(*RawSec
->Info
)
542 : findFirstNonGlobal(Symbols
) + 1;
543 SHeader
.sh_entsize
= (YAMLSec
&& YAMLSec
->EntSize
)
544 ? (uint64_t)(*YAMLSec
->EntSize
)
546 SHeader
.sh_addralign
= YAMLSec
? (uint64_t)YAMLSec
->AddressAlign
: 8;
547 SHeader
.sh_addr
= YAMLSec
? (uint64_t)YAMLSec
->Address
: 0;
549 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
550 if (RawSec
&& (RawSec
->Content
|| RawSec
->Size
)) {
551 assert(Symbols
.empty());
552 SHeader
.sh_size
= writeRawSectionData(OS
, *RawSec
);
556 std::vector
<Elf_Sym
> Syms
=
557 toELFSymbols
<ELFT
>(SN2I
, Symbols
, IsStatic
? DotStrtab
: DotDynstr
);
558 writeArrayData(OS
, makeArrayRef(Syms
));
559 SHeader
.sh_size
= arrayDataSize(makeArrayRef(Syms
));
562 template <class ELFT
>
563 void ELFState
<ELFT
>::initStrtabSectionHeader(Elf_Shdr
&SHeader
, StringRef Name
,
564 StringTableBuilder
&STB
,
565 ContiguousBlobAccumulator
&CBA
,
566 ELFYAML::Section
*YAMLSec
) {
568 SHeader
.sh_name
= DotShStrtab
.getOffset(Name
);
569 SHeader
.sh_type
= YAMLSec
? YAMLSec
->Type
: ELF::SHT_STRTAB
;
570 SHeader
.sh_addralign
= YAMLSec
? (uint64_t)YAMLSec
->AddressAlign
: 1;
572 ELFYAML::RawContentSection
*RawSec
=
573 dyn_cast_or_null
<ELFYAML::RawContentSection
>(YAMLSec
);
575 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
576 if (RawSec
&& (RawSec
->Content
|| RawSec
->Size
)) {
577 SHeader
.sh_size
= writeRawSectionData(OS
, *RawSec
);
580 SHeader
.sh_size
= STB
.getSize();
583 if (YAMLSec
&& YAMLSec
->EntSize
)
584 SHeader
.sh_entsize
= *YAMLSec
->EntSize
;
586 if (RawSec
&& RawSec
->Info
)
587 SHeader
.sh_info
= *RawSec
->Info
;
589 if (YAMLSec
&& YAMLSec
->Flags
)
590 SHeader
.sh_flags
= *YAMLSec
->Flags
;
591 else if (Name
== ".dynstr")
592 SHeader
.sh_flags
= ELF::SHF_ALLOC
;
594 // If the section is explicitly described in the YAML
595 // then we want to use its section address.
597 SHeader
.sh_addr
= YAMLSec
->Address
;
600 template <class ELFT
>
601 void ELFState
<ELFT
>::setProgramHeaderLayout(std::vector
<Elf_Phdr
> &PHeaders
,
602 std::vector
<Elf_Shdr
> &SHeaders
) {
603 uint32_t PhdrIdx
= 0;
604 for (auto &YamlPhdr
: Doc
.ProgramHeaders
) {
605 Elf_Phdr
&PHeader
= PHeaders
[PhdrIdx
++];
607 std::vector
<Elf_Shdr
*> Sections
;
608 for (const ELFYAML::SectionName
&SecName
: YamlPhdr
.Sections
) {
610 if (!SN2I
.lookup(SecName
.Section
, Index
)) {
611 WithColor::error() << "Unknown section referenced: '" << SecName
.Section
612 << "' by program header.\n";
615 Sections
.push_back(&SHeaders
[Index
]);
618 if (YamlPhdr
.Offset
) {
619 PHeader
.p_offset
= *YamlPhdr
.Offset
;
621 if (YamlPhdr
.Sections
.size())
622 PHeader
.p_offset
= UINT32_MAX
;
624 PHeader
.p_offset
= 0;
626 // Find the minimum offset for the program header.
627 for (Elf_Shdr
*SHeader
: Sections
)
628 PHeader
.p_offset
= std::min(PHeader
.p_offset
, SHeader
->sh_offset
);
631 // Find the maximum offset of the end of a section in order to set p_filesz,
632 // if not set explicitly.
633 if (YamlPhdr
.FileSize
) {
634 PHeader
.p_filesz
= *YamlPhdr
.FileSize
;
636 PHeader
.p_filesz
= 0;
637 for (Elf_Shdr
*SHeader
: Sections
) {
638 uint64_t EndOfSection
;
639 if (SHeader
->sh_type
== llvm::ELF::SHT_NOBITS
)
640 EndOfSection
= SHeader
->sh_offset
;
642 EndOfSection
= SHeader
->sh_offset
+ SHeader
->sh_size
;
643 uint64_t EndOfSegment
= PHeader
.p_offset
+ PHeader
.p_filesz
;
644 EndOfSegment
= std::max(EndOfSegment
, EndOfSection
);
645 PHeader
.p_filesz
= EndOfSegment
- PHeader
.p_offset
;
649 // If not set explicitly, find the memory size by adding the size of
650 // sections at the end of the segment. These should be empty (size of zero)
651 // and NOBITS sections.
652 if (YamlPhdr
.MemSize
) {
653 PHeader
.p_memsz
= *YamlPhdr
.MemSize
;
655 PHeader
.p_memsz
= PHeader
.p_filesz
;
656 for (Elf_Shdr
*SHeader
: Sections
)
657 if (SHeader
->sh_offset
== PHeader
.p_offset
+ PHeader
.p_filesz
)
658 PHeader
.p_memsz
+= SHeader
->sh_size
;
661 // Set the alignment of the segment to be the same as the maximum alignment
662 // of the sections with the same offset so that by default the segment
663 // has a valid and sensible alignment.
664 if (YamlPhdr
.Align
) {
665 PHeader
.p_align
= *YamlPhdr
.Align
;
668 for (Elf_Shdr
*SHeader
: Sections
)
669 if (SHeader
->sh_offset
== PHeader
.p_offset
)
670 PHeader
.p_align
= std::max(PHeader
.p_align
, SHeader
->sh_addralign
);
675 template <class ELFT
>
676 bool ELFState
<ELFT
>::writeSectionContent(
677 Elf_Shdr
&SHeader
, const ELFYAML::RawContentSection
&Section
,
678 ContiguousBlobAccumulator
&CBA
) {
680 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
681 SHeader
.sh_size
= writeRawSectionData(OS
, Section
);
684 SHeader
.sh_entsize
= *Section
.EntSize
;
685 else if (Section
.Type
== llvm::ELF::SHT_RELR
)
686 SHeader
.sh_entsize
= sizeof(Elf_Relr
);
688 SHeader
.sh_entsize
= 0;
691 SHeader
.sh_info
= *Section
.Info
;
696 static bool isMips64EL(const ELFYAML::Object
&Doc
) {
697 return Doc
.Header
.Machine
== ELFYAML::ELF_EM(llvm::ELF::EM_MIPS
) &&
698 Doc
.Header
.Class
== ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64
) &&
699 Doc
.Header
.Data
== ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB
);
702 template <class ELFT
>
704 ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
705 const ELFYAML::RelocationSection
&Section
,
706 ContiguousBlobAccumulator
&CBA
) {
707 assert((Section
.Type
== llvm::ELF::SHT_REL
||
708 Section
.Type
== llvm::ELF::SHT_RELA
) &&
709 "Section type is not SHT_REL nor SHT_RELA");
711 bool IsRela
= Section
.Type
== llvm::ELF::SHT_RELA
;
712 SHeader
.sh_entsize
= IsRela
? sizeof(Elf_Rela
) : sizeof(Elf_Rel
);
713 SHeader
.sh_size
= SHeader
.sh_entsize
* Section
.Relocations
.size();
715 // For relocation section set link to .symtab by default.
716 if (Section
.Link
.empty())
717 SHeader
.sh_link
= SN2I
.get(".symtab");
720 if (!Section
.RelocatableSec
.empty() &&
721 !convertSectionIndex(SN2I
, Section
.Name
, Section
.RelocatableSec
, Index
))
723 SHeader
.sh_info
= Index
;
725 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
727 for (const auto &Rel
: Section
.Relocations
) {
729 // If a relocation references a symbol, try to look one up in the symbol
730 // table. If it is not there, treat the value as a symbol index.
731 if (Rel
.Symbol
&& !SymN2I
.lookup(*Rel
.Symbol
, SymIdx
) &&
732 !to_integer(*Rel
.Symbol
, SymIdx
)) {
733 WithColor::error() << "Unknown symbol referenced: '" << *Rel
.Symbol
734 << "' at YAML section '" << Section
.Name
<< "'.\n";
741 REntry
.r_offset
= Rel
.Offset
;
742 REntry
.r_addend
= Rel
.Addend
;
743 REntry
.setSymbolAndType(SymIdx
, Rel
.Type
, isMips64EL(Doc
));
744 OS
.write((const char *)&REntry
, sizeof(REntry
));
748 REntry
.r_offset
= Rel
.Offset
;
749 REntry
.setSymbolAndType(SymIdx
, Rel
.Type
, isMips64EL(Doc
));
750 OS
.write((const char *)&REntry
, sizeof(REntry
));
756 template <class ELFT
>
757 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
758 const ELFYAML::Group
&Section
,
759 ContiguousBlobAccumulator
&CBA
) {
760 assert(Section
.Type
== llvm::ELF::SHT_GROUP
&&
761 "Section type is not SHT_GROUP");
763 SHeader
.sh_entsize
= 4;
764 SHeader
.sh_size
= SHeader
.sh_entsize
* Section
.Members
.size();
767 if (!SymN2I
.lookup(Section
.Signature
, SymIdx
) &&
768 !to_integer(Section
.Signature
, SymIdx
)) {
769 WithColor::error() << "Unknown symbol referenced: '" << Section
.Signature
770 << "' at YAML section '" << Section
.Name
<< "'.\n";
773 SHeader
.sh_info
= SymIdx
;
776 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
778 for (const ELFYAML::SectionOrType
&Member
: Section
.Members
) {
779 unsigned int SectionIndex
= 0;
780 if (Member
.sectionNameOrType
== "GRP_COMDAT")
781 SectionIndex
= llvm::ELF::GRP_COMDAT
;
782 else if (!convertSectionIndex(SN2I
, Section
.Name
, Member
.sectionNameOrType
,
785 support::endian::write
<uint32_t>(OS
, SectionIndex
, ELFT::TargetEndianness
);
790 template <class ELFT
>
791 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
792 const ELFYAML::SymverSection
&Section
,
793 ContiguousBlobAccumulator
&CBA
) {
795 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
796 for (uint16_t Version
: Section
.Entries
)
797 support::endian::write
<uint16_t>(OS
, Version
, ELFT::TargetEndianness
);
799 SHeader
.sh_entsize
= Section
.EntSize
? (uint64_t)*Section
.EntSize
: 2;
800 SHeader
.sh_size
= Section
.Entries
.size() * SHeader
.sh_entsize
;
804 template <class ELFT
>
805 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
806 const ELFYAML::VerdefSection
&Section
,
807 ContiguousBlobAccumulator
&CBA
) {
808 typedef typename
ELFT::Verdef Elf_Verdef
;
809 typedef typename
ELFT::Verdaux Elf_Verdaux
;
811 CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
814 for (size_t I
= 0; I
< Section
.Entries
.size(); ++I
) {
815 const ELFYAML::VerdefEntry
&E
= Section
.Entries
[I
];
818 VerDef
.vd_version
= E
.Version
;
819 VerDef
.vd_flags
= E
.Flags
;
820 VerDef
.vd_ndx
= E
.VersionNdx
;
821 VerDef
.vd_hash
= E
.Hash
;
822 VerDef
.vd_aux
= sizeof(Elf_Verdef
);
823 VerDef
.vd_cnt
= E
.VerNames
.size();
824 if (I
== Section
.Entries
.size() - 1)
828 sizeof(Elf_Verdef
) + E
.VerNames
.size() * sizeof(Elf_Verdaux
);
829 OS
.write((const char *)&VerDef
, sizeof(Elf_Verdef
));
831 for (size_t J
= 0; J
< E
.VerNames
.size(); ++J
, ++AuxCnt
) {
833 VernAux
.vda_name
= DotDynstr
.getOffset(E
.VerNames
[J
]);
834 if (J
== E
.VerNames
.size() - 1)
835 VernAux
.vda_next
= 0;
837 VernAux
.vda_next
= sizeof(Elf_Verdaux
);
838 OS
.write((const char *)&VernAux
, sizeof(Elf_Verdaux
));
842 SHeader
.sh_size
= Section
.Entries
.size() * sizeof(Elf_Verdef
) +
843 AuxCnt
* sizeof(Elf_Verdaux
);
844 SHeader
.sh_info
= Section
.Info
;
849 template <class ELFT
>
850 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
851 const ELFYAML::VerneedSection
&Section
,
852 ContiguousBlobAccumulator
&CBA
) {
853 typedef typename
ELFT::Verneed Elf_Verneed
;
854 typedef typename
ELFT::Vernaux Elf_Vernaux
;
856 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
859 for (size_t I
= 0; I
< Section
.VerneedV
.size(); ++I
) {
860 const ELFYAML::VerneedEntry
&VE
= Section
.VerneedV
[I
];
863 VerNeed
.vn_version
= VE
.Version
;
864 VerNeed
.vn_file
= DotDynstr
.getOffset(VE
.File
);
865 if (I
== Section
.VerneedV
.size() - 1)
869 sizeof(Elf_Verneed
) + VE
.AuxV
.size() * sizeof(Elf_Vernaux
);
870 VerNeed
.vn_cnt
= VE
.AuxV
.size();
871 VerNeed
.vn_aux
= sizeof(Elf_Verneed
);
872 OS
.write((const char *)&VerNeed
, sizeof(Elf_Verneed
));
874 for (size_t J
= 0; J
< VE
.AuxV
.size(); ++J
, ++AuxCnt
) {
875 const ELFYAML::VernauxEntry
&VAuxE
= VE
.AuxV
[J
];
878 VernAux
.vna_hash
= VAuxE
.Hash
;
879 VernAux
.vna_flags
= VAuxE
.Flags
;
880 VernAux
.vna_other
= VAuxE
.Other
;
881 VernAux
.vna_name
= DotDynstr
.getOffset(VAuxE
.Name
);
882 if (J
== VE
.AuxV
.size() - 1)
883 VernAux
.vna_next
= 0;
885 VernAux
.vna_next
= sizeof(Elf_Vernaux
);
886 OS
.write((const char *)&VernAux
, sizeof(Elf_Vernaux
));
890 SHeader
.sh_size
= Section
.VerneedV
.size() * sizeof(Elf_Verneed
) +
891 AuxCnt
* sizeof(Elf_Vernaux
);
892 SHeader
.sh_info
= Section
.Info
;
897 template <class ELFT
>
898 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
899 const ELFYAML::MipsABIFlags
&Section
,
900 ContiguousBlobAccumulator
&CBA
) {
901 assert(Section
.Type
== llvm::ELF::SHT_MIPS_ABIFLAGS
&&
902 "Section type is not SHT_MIPS_ABIFLAGS");
904 object::Elf_Mips_ABIFlags
<ELFT
> Flags
;
906 SHeader
.sh_entsize
= sizeof(Flags
);
907 SHeader
.sh_size
= SHeader
.sh_entsize
;
909 auto &OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
910 Flags
.version
= Section
.Version
;
911 Flags
.isa_level
= Section
.ISALevel
;
912 Flags
.isa_rev
= Section
.ISARevision
;
913 Flags
.gpr_size
= Section
.GPRSize
;
914 Flags
.cpr1_size
= Section
.CPR1Size
;
915 Flags
.cpr2_size
= Section
.CPR2Size
;
916 Flags
.fp_abi
= Section
.FpABI
;
917 Flags
.isa_ext
= Section
.ISAExtension
;
918 Flags
.ases
= Section
.ASEs
;
919 Flags
.flags1
= Section
.Flags1
;
920 Flags
.flags2
= Section
.Flags2
;
921 OS
.write((const char *)&Flags
, sizeof(Flags
));
926 template <class ELFT
>
927 bool ELFState
<ELFT
>::writeSectionContent(Elf_Shdr
&SHeader
,
928 const ELFYAML::DynamicSection
&Section
,
929 ContiguousBlobAccumulator
&CBA
) {
930 typedef typename
ELFT::uint uintX_t
;
932 assert(Section
.Type
== llvm::ELF::SHT_DYNAMIC
&&
933 "Section type is not SHT_DYNAMIC");
935 if (!Section
.Entries
.empty() && Section
.Content
) {
937 << "Cannot specify both raw content and explicit entries "
938 "for dynamic section '"
939 << Section
.Name
<< "'.\n";
944 SHeader
.sh_size
= Section
.Content
->binary_size();
946 SHeader
.sh_size
= 2 * sizeof(uintX_t
) * Section
.Entries
.size();
948 SHeader
.sh_entsize
= *Section
.EntSize
;
950 SHeader
.sh_entsize
= sizeof(Elf_Dyn
);
952 raw_ostream
&OS
= CBA
.getOSAndAlignedOffset(SHeader
.sh_offset
, SHeader
.sh_addralign
);
953 for (const ELFYAML::DynamicEntry
&DE
: Section
.Entries
) {
954 support::endian::write
<uintX_t
>(OS
, DE
.Tag
, ELFT::TargetEndianness
);
955 support::endian::write
<uintX_t
>(OS
, DE
.Val
, ELFT::TargetEndianness
);
958 Section
.Content
->writeAsBinary(OS
);
963 template <class ELFT
> bool ELFState
<ELFT
>::buildSectionIndex() {
964 for (unsigned I
= 0, E
= Doc
.Sections
.size(); I
!= E
; ++I
) {
965 StringRef Name
= Doc
.Sections
[I
]->Name
;
969 DotShStrtab
.add(dropUniqueSuffix(Name
));
970 if (!SN2I
.addName(Name
, I
)) {
971 WithColor::error() << "Repeated section name: '" << Name
972 << "' at YAML section number " << I
<< ".\n";
977 DotShStrtab
.finalize();
981 template <class ELFT
>
982 bool ELFState
<ELFT
>::buildSymbolIndex(ArrayRef
<ELFYAML::Symbol
> Symbols
) {
983 bool GlobalSymbolSeen
= false;
985 for (const auto &Sym
: Symbols
) {
988 StringRef Name
= Sym
.Name
;
989 if (Sym
.Binding
.value
== ELF::STB_LOCAL
&& GlobalSymbolSeen
) {
990 WithColor::error() << "Local symbol '" + Name
+
991 "' after global in Symbols list.\n";
994 if (Sym
.Binding
.value
!= ELF::STB_LOCAL
)
995 GlobalSymbolSeen
= true;
997 if (!Name
.empty() && !SymN2I
.addName(Name
, I
)) {
998 WithColor::error() << "Repeated symbol name: '" << Name
<< "'.\n";
1005 template <class ELFT
> void ELFState
<ELFT
>::finalizeStrings() {
1006 // Add the regular symbol names to .strtab section.
1007 for (const ELFYAML::Symbol
&Sym
: Doc
.Symbols
)
1008 DotStrtab
.add(dropUniqueSuffix(Sym
.Name
));
1009 DotStrtab
.finalize();
1011 // Add the dynamic symbol names to .dynstr section.
1012 for (const ELFYAML::Symbol
&Sym
: Doc
.DynamicSymbols
)
1013 DotDynstr
.add(dropUniqueSuffix(Sym
.Name
));
1015 // SHT_GNU_verdef and SHT_GNU_verneed sections might also
1016 // add strings to .dynstr section.
1017 for (const std::unique_ptr
<ELFYAML::Section
> &Sec
: Doc
.Sections
) {
1018 if (auto VerNeed
= dyn_cast
<ELFYAML::VerneedSection
>(Sec
.get())) {
1019 for (const ELFYAML::VerneedEntry
&VE
: VerNeed
->VerneedV
) {
1020 DotDynstr
.add(VE
.File
);
1021 for (const ELFYAML::VernauxEntry
&Aux
: VE
.AuxV
)
1022 DotDynstr
.add(Aux
.Name
);
1024 } else if (auto VerDef
= dyn_cast
<ELFYAML::VerdefSection
>(Sec
.get())) {
1025 for (const ELFYAML::VerdefEntry
&E
: VerDef
->Entries
)
1026 for (StringRef Name
: E
.VerNames
)
1027 DotDynstr
.add(Name
);
1031 DotDynstr
.finalize();
1034 template <class ELFT
>
1035 int ELFState
<ELFT
>::writeELF(raw_ostream
&OS
, ELFYAML::Object
&Doc
) {
1036 ELFState
<ELFT
> State(Doc
);
1038 // Finalize .strtab and .dynstr sections. We do that early because want to
1039 // finalize the string table builders before writing the content of the
1040 // sections that might want to use them.
1041 State
.finalizeStrings();
1043 if (!State
.buildSectionIndex())
1046 if (!State
.buildSymbolIndex(Doc
.Symbols
))
1050 State
.initELFHeader(Header
);
1052 // TODO: Flesh out section header support.
1054 std::vector
<Elf_Phdr
> PHeaders
;
1055 State
.initProgramHeaders(PHeaders
);
1057 // XXX: This offset is tightly coupled with the order that we write
1059 const size_t SectionContentBeginOffset
= Header
.e_ehsize
+
1060 Header
.e_phentsize
* Header
.e_phnum
+
1061 Header
.e_shentsize
* Header
.e_shnum
;
1062 ContiguousBlobAccumulator
CBA(SectionContentBeginOffset
);
1064 std::vector
<Elf_Shdr
> SHeaders
;
1065 if (!State
.initSectionHeaders(State
, SHeaders
, CBA
))
1068 // Now we can decide segment offsets
1069 State
.setProgramHeaderLayout(PHeaders
, SHeaders
);
1071 OS
.write((const char *)&Header
, sizeof(Header
));
1072 writeArrayData(OS
, makeArrayRef(PHeaders
));
1073 writeArrayData(OS
, makeArrayRef(SHeaders
));
1074 CBA
.writeBlobToStream(OS
);
1078 int yaml2elf(llvm::ELFYAML::Object
&Doc
, raw_ostream
&Out
) {
1079 bool IsLE
= Doc
.Header
.Data
== ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB
);
1080 bool Is64Bit
= Doc
.Header
.Class
== ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64
);
1083 return ELFState
<object::ELF64LE
>::writeELF(Out
, Doc
);
1084 return ELFState
<object::ELF64BE
>::writeELF(Out
, Doc
);
1087 return ELFState
<object::ELF32LE
>::writeELF(Out
, Doc
);
1088 return ELFState
<object::ELF32BE
>::writeELF(Out
, Doc
);