1 | //===- yaml2elf - Convert YAML to a ELF object file -----------------------===// |
2 | // |
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 |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | /// |
9 | /// \file |
10 | /// The ELF component of yaml2obj. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "llvm/ADT/ArrayRef.h" |
15 | #include "llvm/ADT/DenseMap.h" |
16 | #include "llvm/ADT/SetVector.h" |
17 | #include "llvm/ADT/StringSet.h" |
18 | #include "llvm/BinaryFormat/ELF.h" |
19 | #include "llvm/MC/StringTableBuilder.h" |
20 | #include "llvm/Object/ELFObjectFile.h" |
21 | #include "llvm/Object/ELFTypes.h" |
22 | #include "llvm/ObjectYAML/DWARFEmitter.h" |
23 | #include "llvm/ObjectYAML/DWARFYAML.h" |
24 | #include "llvm/ObjectYAML/ELFYAML.h" |
25 | #include "llvm/ObjectYAML/yaml2obj.h" |
26 | #include "llvm/Support/EndianStream.h" |
27 | #include "llvm/Support/Errc.h" |
28 | #include "llvm/Support/Error.h" |
29 | #include "llvm/Support/LEB128.h" |
30 | #include "llvm/Support/MemoryBuffer.h" |
31 | #include "llvm/Support/WithColor.h" |
32 | #include "llvm/Support/YAMLTraits.h" |
33 | #include "llvm/Support/raw_ostream.h" |
34 | #include <optional> |
35 | #include <variant> |
36 | |
37 | using namespace llvm; |
38 | |
39 | // This class is used to build up a contiguous binary blob while keeping |
40 | // track of an offset in the output (which notionally begins at |
41 | // `InitialOffset`). |
42 | // The blob might be limited to an arbitrary size. All attempts to write data |
43 | // are ignored and the error condition is remembered once the limit is reached. |
44 | // Such an approach allows us to simplify the code by delaying error reporting |
45 | // and doing it at a convenient time. |
46 | namespace { |
47 | class ContiguousBlobAccumulator { |
48 | const uint64_t InitialOffset; |
49 | const uint64_t MaxSize; |
50 | |
51 | SmallVector<char, 128> Buf; |
52 | raw_svector_ostream OS; |
53 | Error ReachedLimitErr = Error::success(); |
54 | |
55 | bool checkLimit(uint64_t Size) { |
56 | if (!ReachedLimitErr && getOffset() + Size <= MaxSize) |
57 | return true; |
58 | if (!ReachedLimitErr) |
59 | ReachedLimitErr = createStringError(EC: errc::invalid_argument, |
60 | S: "reached the output size limit" ); |
61 | return false; |
62 | } |
63 | |
64 | public: |
65 | ContiguousBlobAccumulator(uint64_t BaseOffset, uint64_t SizeLimit) |
66 | : InitialOffset(BaseOffset), MaxSize(SizeLimit), OS(Buf) {} |
67 | |
68 | uint64_t tell() const { return OS.tell(); } |
69 | uint64_t getOffset() const { return InitialOffset + OS.tell(); } |
70 | void writeBlobToStream(raw_ostream &Out) const { Out << OS.str(); } |
71 | |
72 | Error takeLimitError() { |
73 | // Request to write 0 bytes to check we did not reach the limit. |
74 | checkLimit(Size: 0); |
75 | return std::move(ReachedLimitErr); |
76 | } |
77 | |
78 | /// \returns The new offset. |
79 | uint64_t padToAlignment(unsigned Align) { |
80 | uint64_t CurrentOffset = getOffset(); |
81 | if (ReachedLimitErr) |
82 | return CurrentOffset; |
83 | |
84 | uint64_t AlignedOffset = alignTo(Value: CurrentOffset, Align: Align == 0 ? 1 : Align); |
85 | uint64_t PaddingSize = AlignedOffset - CurrentOffset; |
86 | if (!checkLimit(Size: PaddingSize)) |
87 | return CurrentOffset; |
88 | |
89 | writeZeros(Num: PaddingSize); |
90 | return AlignedOffset; |
91 | } |
92 | |
93 | raw_ostream *getRawOS(uint64_t Size) { |
94 | if (checkLimit(Size)) |
95 | return &OS; |
96 | return nullptr; |
97 | } |
98 | |
99 | void writeAsBinary(const yaml::BinaryRef &Bin, uint64_t N = UINT64_MAX) { |
100 | if (!checkLimit(Size: Bin.binary_size())) |
101 | return; |
102 | Bin.writeAsBinary(OS, N); |
103 | } |
104 | |
105 | void writeZeros(uint64_t Num) { |
106 | if (checkLimit(Size: Num)) |
107 | OS.write_zeros(NumZeros: Num); |
108 | } |
109 | |
110 | void write(const char *Ptr, size_t Size) { |
111 | if (checkLimit(Size)) |
112 | OS.write(Ptr, Size); |
113 | } |
114 | |
115 | void write(unsigned char C) { |
116 | if (checkLimit(Size: 1)) |
117 | OS.write(C); |
118 | } |
119 | |
120 | unsigned writeULEB128(uint64_t Val) { |
121 | if (!checkLimit(Size: sizeof(uint64_t))) |
122 | return 0; |
123 | return encodeULEB128(Value: Val, OS); |
124 | } |
125 | |
126 | unsigned writeSLEB128(int64_t Val) { |
127 | if (!checkLimit(Size: 10)) |
128 | return 0; |
129 | return encodeSLEB128(Value: Val, OS); |
130 | } |
131 | |
132 | template <typename T> void write(T Val, llvm::endianness E) { |
133 | if (checkLimit(Size: sizeof(T))) |
134 | support::endian::write<T>(OS, Val, E); |
135 | } |
136 | |
137 | void updateDataAt(uint64_t Pos, void *Data, size_t Size) { |
138 | assert(Pos >= InitialOffset && Pos + Size <= getOffset()); |
139 | memcpy(dest: &Buf[Pos - InitialOffset], src: Data, n: Size); |
140 | } |
141 | }; |
142 | |
143 | // Used to keep track of section and symbol names, so that in the YAML file |
144 | // sections and symbols can be referenced by name instead of by index. |
145 | class NameToIdxMap { |
146 | StringMap<unsigned> Map; |
147 | |
148 | public: |
149 | /// \Returns false if name is already present in the map. |
150 | bool addName(StringRef Name, unsigned Ndx) { |
151 | return Map.insert(KV: {Name, Ndx}).second; |
152 | } |
153 | /// \Returns false if name is not present in the map. |
154 | bool lookup(StringRef Name, unsigned &Idx) const { |
155 | auto I = Map.find(Key: Name); |
156 | if (I == Map.end()) |
157 | return false; |
158 | Idx = I->getValue(); |
159 | return true; |
160 | } |
161 | /// Asserts if name is not present in the map. |
162 | unsigned get(StringRef Name) const { |
163 | unsigned Idx; |
164 | if (lookup(Name, Idx)) |
165 | return Idx; |
166 | assert(false && "Expected section not found in index" ); |
167 | return 0; |
168 | } |
169 | unsigned size() const { return Map.size(); } |
170 | }; |
171 | |
172 | namespace { |
173 | struct Fragment { |
174 | uint64_t Offset; |
175 | uint64_t Size; |
176 | uint32_t Type; |
177 | uint64_t AddrAlign; |
178 | }; |
179 | } // namespace |
180 | |
181 | /// "Single point of truth" for the ELF file construction. |
182 | /// TODO: This class still has a ways to go before it is truly a "single |
183 | /// point of truth". |
184 | template <class ELFT> class ELFState { |
185 | LLVM_ELF_IMPORT_TYPES_ELFT(ELFT) |
186 | |
187 | enum class SymtabType { Static, Dynamic }; |
188 | |
189 | /// The future symbol table string section. |
190 | StringTableBuilder DotStrtab{StringTableBuilder::ELF}; |
191 | |
192 | /// The future section header string table section, if a unique string table |
193 | /// is needed. Don't reference this variable direectly: use the |
194 | /// ShStrtabStrings member instead. |
195 | StringTableBuilder DotShStrtab{StringTableBuilder::ELF}; |
196 | |
197 | /// The future dynamic symbol string section. |
198 | StringTableBuilder DotDynstr{StringTableBuilder::ELF}; |
199 | |
200 | /// The name of the section header string table section. If it is .strtab or |
201 | /// .dynstr, the section header strings will be written to the same string |
202 | /// table as the static/dynamic symbols respectively. Otherwise a dedicated |
203 | /// section will be created with that name. |
204 | StringRef = ".shstrtab" ; |
205 | StringTableBuilder *ShStrtabStrings = &DotShStrtab; |
206 | |
207 | NameToIdxMap SN2I; |
208 | NameToIdxMap SymN2I; |
209 | NameToIdxMap DynSymN2I; |
210 | ELFYAML::Object &Doc; |
211 | |
212 | StringSet<> ; |
213 | |
214 | uint64_t LocationCounter = 0; |
215 | bool HasError = false; |
216 | yaml::ErrorHandler ErrHandler; |
217 | void reportError(const Twine &Msg); |
218 | void reportError(Error Err); |
219 | |
220 | std::vector<Elf_Sym> toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols, |
221 | const StringTableBuilder &Strtab); |
222 | unsigned toSectionIndex(StringRef S, StringRef LocSec, StringRef LocSym = "" ); |
223 | unsigned toSymbolIndex(StringRef S, StringRef LocSec, bool IsDynamic); |
224 | |
225 | void buildSectionIndex(); |
226 | void buildSymbolIndexes(); |
227 | void initProgramHeaders(std::vector<Elf_Phdr> &); |
228 | bool initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &, |
229 | StringRef SecName, ELFYAML::Section *YAMLSec); |
230 | void initSectionHeaders(std::vector<Elf_Shdr> &, |
231 | ContiguousBlobAccumulator &CBA); |
232 | void initSymtabSectionHeader(Elf_Shdr &, SymtabType STType, |
233 | ContiguousBlobAccumulator &CBA, |
234 | ELFYAML::Section *YAMLSec); |
235 | void initStrtabSectionHeader(Elf_Shdr &, StringRef Name, |
236 | StringTableBuilder &STB, |
237 | ContiguousBlobAccumulator &CBA, |
238 | ELFYAML::Section *YAMLSec); |
239 | void initDWARFSectionHeader(Elf_Shdr &, StringRef Name, |
240 | ContiguousBlobAccumulator &CBA, |
241 | ELFYAML::Section *YAMLSec); |
242 | void setProgramHeaderLayout(std::vector<Elf_Phdr> &, |
243 | std::vector<Elf_Shdr> &); |
244 | |
245 | std::vector<Fragment> |
246 | getPhdrFragments(const ELFYAML::ProgramHeader &Phdr, |
247 | ArrayRef<typename ELFT::Shdr> ); |
248 | |
249 | void finalizeStrings(); |
250 | void writeELFHeader(raw_ostream &OS); |
251 | void writeSectionContent(Elf_Shdr &, |
252 | const ELFYAML::NoBitsSection &Section, |
253 | ContiguousBlobAccumulator &CBA); |
254 | void writeSectionContent(Elf_Shdr &, |
255 | const ELFYAML::RawContentSection &Section, |
256 | ContiguousBlobAccumulator &CBA); |
257 | void writeSectionContent(Elf_Shdr &, |
258 | const ELFYAML::RelocationSection &Section, |
259 | ContiguousBlobAccumulator &CBA); |
260 | void writeSectionContent(Elf_Shdr &, |
261 | const ELFYAML::RelrSection &Section, |
262 | ContiguousBlobAccumulator &CBA); |
263 | void writeSectionContent(Elf_Shdr &, |
264 | const ELFYAML::GroupSection &Group, |
265 | ContiguousBlobAccumulator &CBA); |
266 | void writeSectionContent(Elf_Shdr &, |
267 | const ELFYAML::SymtabShndxSection &Shndx, |
268 | ContiguousBlobAccumulator &CBA); |
269 | void writeSectionContent(Elf_Shdr &, |
270 | const ELFYAML::SymverSection &Section, |
271 | ContiguousBlobAccumulator &CBA); |
272 | void writeSectionContent(Elf_Shdr &, |
273 | const ELFYAML::VerneedSection &Section, |
274 | ContiguousBlobAccumulator &CBA); |
275 | void writeSectionContent(Elf_Shdr &, |
276 | const ELFYAML::VerdefSection &Section, |
277 | ContiguousBlobAccumulator &CBA); |
278 | void writeSectionContent(Elf_Shdr &, |
279 | const ELFYAML::ARMIndexTableSection &Section, |
280 | ContiguousBlobAccumulator &CBA); |
281 | void writeSectionContent(Elf_Shdr &, |
282 | const ELFYAML::MipsABIFlags &Section, |
283 | ContiguousBlobAccumulator &CBA); |
284 | void writeSectionContent(Elf_Shdr &, |
285 | const ELFYAML::DynamicSection &Section, |
286 | ContiguousBlobAccumulator &CBA); |
287 | void writeSectionContent(Elf_Shdr &, |
288 | const ELFYAML::StackSizesSection &Section, |
289 | ContiguousBlobAccumulator &CBA); |
290 | void writeSectionContent(Elf_Shdr &, |
291 | const ELFYAML::BBAddrMapSection &Section, |
292 | ContiguousBlobAccumulator &CBA); |
293 | void writeSectionContent(Elf_Shdr &, |
294 | const ELFYAML::HashSection &Section, |
295 | ContiguousBlobAccumulator &CBA); |
296 | void writeSectionContent(Elf_Shdr &, |
297 | const ELFYAML::AddrsigSection &Section, |
298 | ContiguousBlobAccumulator &CBA); |
299 | void writeSectionContent(Elf_Shdr &, |
300 | const ELFYAML::NoteSection &Section, |
301 | ContiguousBlobAccumulator &CBA); |
302 | void writeSectionContent(Elf_Shdr &, |
303 | const ELFYAML::GnuHashSection &Section, |
304 | ContiguousBlobAccumulator &CBA); |
305 | void writeSectionContent(Elf_Shdr &, |
306 | const ELFYAML::LinkerOptionsSection &Section, |
307 | ContiguousBlobAccumulator &CBA); |
308 | void writeSectionContent(Elf_Shdr &, |
309 | const ELFYAML::DependentLibrariesSection &Section, |
310 | ContiguousBlobAccumulator &CBA); |
311 | void writeSectionContent(Elf_Shdr &, |
312 | const ELFYAML::CallGraphProfileSection &Section, |
313 | ContiguousBlobAccumulator &CBA); |
314 | |
315 | void writeFill(ELFYAML::Fill &Fill, ContiguousBlobAccumulator &CBA); |
316 | |
317 | ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH); |
318 | |
319 | void assignSectionAddress(Elf_Shdr &, ELFYAML::Section *YAMLSec); |
320 | |
321 | DenseMap<StringRef, size_t> buildSectionHeaderReorderMap(); |
322 | |
323 | BumpPtrAllocator StringAlloc; |
324 | uint64_t alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align, |
325 | std::optional<llvm::yaml::Hex64> Offset); |
326 | |
327 | uint64_t getSectionNameOffset(StringRef Name); |
328 | |
329 | public: |
330 | static bool writeELF(raw_ostream &OS, ELFYAML::Object &Doc, |
331 | yaml::ErrorHandler EH, uint64_t MaxSize); |
332 | }; |
333 | } // end anonymous namespace |
334 | |
335 | template <class T> static size_t arrayDataSize(ArrayRef<T> A) { |
336 | return A.size() * sizeof(T); |
337 | } |
338 | |
339 | template <class T> static void writeArrayData(raw_ostream &OS, ArrayRef<T> A) { |
340 | OS.write((const char *)A.data(), arrayDataSize(A)); |
341 | } |
342 | |
343 | template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); } |
344 | |
345 | template <class ELFT> |
346 | ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) |
347 | : Doc(D), ErrHandler(EH) { |
348 | // The input may explicitly request to store the section header table strings |
349 | // in the same string table as dynamic or static symbol names. Set the |
350 | // ShStrtabStrings member accordingly. |
351 | if (Doc.Header.SectionHeaderStringTable) { |
352 | SectionHeaderStringTableName = *Doc.Header.SectionHeaderStringTable; |
353 | if (*Doc.Header.SectionHeaderStringTable == ".strtab" ) |
354 | ShStrtabStrings = &DotStrtab; |
355 | else if (*Doc.Header.SectionHeaderStringTable == ".dynstr" ) |
356 | ShStrtabStrings = &DotDynstr; |
357 | // Otherwise, the unique table will be used. |
358 | } |
359 | |
360 | std::vector<ELFYAML::Section *> Sections = Doc.getSections(); |
361 | // Insert SHT_NULL section implicitly when it is not defined in YAML. |
362 | if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL) |
363 | Doc.Chunks.insert( |
364 | position: Doc.Chunks.begin(), |
365 | x: std::make_unique<ELFYAML::Section>( |
366 | args: ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/args: true)); |
367 | |
368 | StringSet<> DocSections; |
369 | ELFYAML::SectionHeaderTable *SecHdrTable = nullptr; |
370 | for (size_t I = 0; I < Doc.Chunks.size(); ++I) { |
371 | const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I]; |
372 | |
373 | // We might have an explicit section header table declaration. |
374 | if (auto S = dyn_cast<ELFYAML::SectionHeaderTable>(Val: C.get())) { |
375 | if (SecHdrTable) |
376 | reportError("multiple section header tables are not allowed" ); |
377 | SecHdrTable = S; |
378 | continue; |
379 | } |
380 | |
381 | // We add a technical suffix for each unnamed section/fill. It does not |
382 | // affect the output, but allows us to map them by name in the code and |
383 | // report better error messages. |
384 | if (C->Name.empty()) { |
385 | std::string NewName = ELFYAML::appendUniqueSuffix( |
386 | /*Name=*/"" , Msg: "index " + Twine(I)); |
387 | C->Name = StringRef(NewName).copy(A&: StringAlloc); |
388 | assert(ELFYAML::dropUniqueSuffix(C->Name).empty()); |
389 | } |
390 | |
391 | if (!DocSections.insert(key: C->Name).second) |
392 | reportError("repeated section/fill name: '" + C->Name + |
393 | "' at YAML section/fill number " + Twine(I)); |
394 | } |
395 | |
396 | SmallSetVector<StringRef, 8> ImplicitSections; |
397 | if (Doc.DynamicSymbols) { |
398 | if (SectionHeaderStringTableName == ".dynsym" ) |
399 | reportError("cannot use '.dynsym' as the section header name table when " |
400 | "there are dynamic symbols" ); |
401 | ImplicitSections.insert(X: ".dynsym" ); |
402 | ImplicitSections.insert(X: ".dynstr" ); |
403 | } |
404 | if (Doc.Symbols) { |
405 | if (SectionHeaderStringTableName == ".symtab" ) |
406 | reportError("cannot use '.symtab' as the section header name table when " |
407 | "there are symbols" ); |
408 | ImplicitSections.insert(X: ".symtab" ); |
409 | } |
410 | if (Doc.DWARF) |
411 | for (StringRef DebugSecName : Doc.DWARF->getNonEmptySectionNames()) { |
412 | std::string SecName = ("." + DebugSecName).str(); |
413 | // TODO: For .debug_str it should be possible to share the string table, |
414 | // in the same manner as the symbol string tables. |
415 | if (SectionHeaderStringTableName == SecName) |
416 | reportError("cannot use '" + SecName + |
417 | "' as the section header name table when it is needed for " |
418 | "DWARF output" ); |
419 | ImplicitSections.insert(X: StringRef(SecName).copy(A&: StringAlloc)); |
420 | } |
421 | // TODO: Only create the .strtab here if any symbols have been requested. |
422 | ImplicitSections.insert(X: ".strtab" ); |
423 | if (!SecHdrTable || !SecHdrTable->NoHeaders.value_or(u: false)) |
424 | ImplicitSections.insert(X: SectionHeaderStringTableName); |
425 | |
426 | // Insert placeholders for implicit sections that are not |
427 | // defined explicitly in YAML. |
428 | for (StringRef SecName : ImplicitSections) { |
429 | if (DocSections.count(Key: SecName)) |
430 | continue; |
431 | |
432 | std::unique_ptr<ELFYAML::Section> Sec = std::make_unique<ELFYAML::Section>( |
433 | args: ELFYAML::Chunk::ChunkKind::RawContent, args: true /*IsImplicit*/); |
434 | Sec->Name = SecName; |
435 | |
436 | if (SecName == SectionHeaderStringTableName) |
437 | Sec->Type = ELF::SHT_STRTAB; |
438 | else if (SecName == ".dynsym" ) |
439 | Sec->Type = ELF::SHT_DYNSYM; |
440 | else if (SecName == ".symtab" ) |
441 | Sec->Type = ELF::SHT_SYMTAB; |
442 | else |
443 | Sec->Type = ELF::SHT_STRTAB; |
444 | |
445 | // When the section header table is explicitly defined at the end of the |
446 | // sections list, it is reasonable to assume that the user wants to reorder |
447 | // section headers, but still wants to place the section header table after |
448 | // all sections, like it normally happens. In this case we want to insert |
449 | // other implicit sections right before the section header table. |
450 | if (Doc.Chunks.back().get() == SecHdrTable) |
451 | Doc.Chunks.insert(position: Doc.Chunks.end() - 1, x: std::move(Sec)); |
452 | else |
453 | Doc.Chunks.push_back(x: std::move(Sec)); |
454 | } |
455 | |
456 | // Insert the section header table implicitly at the end, when it is not |
457 | // explicitly defined. |
458 | if (!SecHdrTable) |
459 | Doc.Chunks.push_back( |
460 | x: std::make_unique<ELFYAML::SectionHeaderTable>(/*IsImplicit=*/args: true)); |
461 | } |
462 | |
463 | template <class ELFT> |
464 | void ELFState<ELFT>::(raw_ostream &OS) { |
465 | using namespace llvm::ELF; |
466 | |
467 | Elf_Ehdr ; |
468 | zero(Header); |
469 | Header.e_ident[EI_MAG0] = 0x7f; |
470 | Header.e_ident[EI_MAG1] = 'E'; |
471 | Header.e_ident[EI_MAG2] = 'L'; |
472 | Header.e_ident[EI_MAG3] = 'F'; |
473 | Header.e_ident[EI_CLASS] = ELFT::Is64Bits ? ELFCLASS64 : ELFCLASS32; |
474 | Header.e_ident[EI_DATA] = Doc.Header.Data; |
475 | Header.e_ident[EI_VERSION] = EV_CURRENT; |
476 | Header.e_ident[EI_OSABI] = Doc.Header.OSABI; |
477 | Header.e_ident[EI_ABIVERSION] = Doc.Header.ABIVersion; |
478 | Header.e_type = Doc.Header.Type; |
479 | |
480 | if (Doc.Header.Machine) |
481 | Header.e_machine = *Doc.Header.Machine; |
482 | else |
483 | Header.e_machine = EM_NONE; |
484 | |
485 | Header.e_version = EV_CURRENT; |
486 | Header.e_entry = Doc.Header.Entry; |
487 | Header.e_flags = Doc.Header.Flags; |
488 | Header.e_ehsize = sizeof(Elf_Ehdr); |
489 | |
490 | if (Doc.Header.EPhOff) |
491 | Header.e_phoff = *Doc.Header.EPhOff; |
492 | else if (!Doc.ProgramHeaders.empty()) |
493 | Header.e_phoff = sizeof(Header); |
494 | else |
495 | Header.e_phoff = 0; |
496 | |
497 | if (Doc.Header.EPhEntSize) |
498 | Header.e_phentsize = *Doc.Header.EPhEntSize; |
499 | else if (!Doc.ProgramHeaders.empty()) |
500 | Header.e_phentsize = sizeof(Elf_Phdr); |
501 | else |
502 | Header.e_phentsize = 0; |
503 | |
504 | if (Doc.Header.EPhNum) |
505 | Header.e_phnum = *Doc.Header.EPhNum; |
506 | else if (!Doc.ProgramHeaders.empty()) |
507 | Header.e_phnum = Doc.ProgramHeaders.size(); |
508 | else |
509 | Header.e_phnum = 0; |
510 | |
511 | Header.e_shentsize = Doc.Header.EShEntSize ? (uint16_t)*Doc.Header.EShEntSize |
512 | : sizeof(Elf_Shdr); |
513 | |
514 | const ELFYAML::SectionHeaderTable & = |
515 | Doc.getSectionHeaderTable(); |
516 | |
517 | if (Doc.Header.EShOff) |
518 | Header.e_shoff = *Doc.Header.EShOff; |
519 | else if (SectionHeaders.Offset) |
520 | Header.e_shoff = *SectionHeaders.Offset; |
521 | else |
522 | Header.e_shoff = 0; |
523 | |
524 | if (Doc.Header.EShNum) |
525 | Header.e_shnum = *Doc.Header.EShNum; |
526 | else |
527 | Header.e_shnum = SectionHeaders.getNumHeaders(SectionsNum: Doc.getSections().size()); |
528 | |
529 | if (Doc.Header.EShStrNdx) |
530 | Header.e_shstrndx = *Doc.Header.EShStrNdx; |
531 | else if (SectionHeaders.Offset && |
532 | !ExcludedSectionHeaders.count(Key: SectionHeaderStringTableName)) |
533 | Header.e_shstrndx = SN2I.get(Name: SectionHeaderStringTableName); |
534 | else |
535 | Header.e_shstrndx = 0; |
536 | |
537 | OS.write(Ptr: (const char *)&Header, Size: sizeof(Header)); |
538 | } |
539 | |
540 | template <class ELFT> |
541 | void ELFState<ELFT>::(std::vector<Elf_Phdr> &) { |
542 | DenseMap<StringRef, ELFYAML::Fill *> NameToFill; |
543 | DenseMap<StringRef, size_t> NameToIndex; |
544 | for (size_t I = 0, E = Doc.Chunks.size(); I != E; ++I) { |
545 | if (auto S = dyn_cast<ELFYAML::Fill>(Val: Doc.Chunks[I].get())) |
546 | NameToFill[S->Name] = S; |
547 | NameToIndex[Doc.Chunks[I]->Name] = I + 1; |
548 | } |
549 | |
550 | std::vector<ELFYAML::Section *> Sections = Doc.getSections(); |
551 | for (size_t I = 0, E = Doc.ProgramHeaders.size(); I != E; ++I) { |
552 | ELFYAML::ProgramHeader &YamlPhdr = Doc.ProgramHeaders[I]; |
553 | Elf_Phdr Phdr; |
554 | zero(Phdr); |
555 | Phdr.p_type = YamlPhdr.Type; |
556 | Phdr.p_flags = YamlPhdr.Flags; |
557 | Phdr.p_vaddr = YamlPhdr.VAddr; |
558 | Phdr.p_paddr = YamlPhdr.PAddr; |
559 | PHeaders.push_back(Phdr); |
560 | |
561 | if (!YamlPhdr.FirstSec && !YamlPhdr.LastSec) |
562 | continue; |
563 | |
564 | // Get the index of the section, or 0 in the case when the section doesn't exist. |
565 | size_t First = NameToIndex[*YamlPhdr.FirstSec]; |
566 | if (!First) |
567 | reportError("unknown section or fill referenced: '" + *YamlPhdr.FirstSec + |
568 | "' by the 'FirstSec' key of the program header with index " + |
569 | Twine(I)); |
570 | size_t Last = NameToIndex[*YamlPhdr.LastSec]; |
571 | if (!Last) |
572 | reportError("unknown section or fill referenced: '" + *YamlPhdr.LastSec + |
573 | "' by the 'LastSec' key of the program header with index " + |
574 | Twine(I)); |
575 | if (!First || !Last) |
576 | continue; |
577 | |
578 | if (First > Last) |
579 | reportError("program header with index " + Twine(I) + |
580 | ": the section index of " + *YamlPhdr.FirstSec + |
581 | " is greater than the index of " + *YamlPhdr.LastSec); |
582 | |
583 | for (size_t I = First; I <= Last; ++I) |
584 | YamlPhdr.Chunks.push_back(x: Doc.Chunks[I - 1].get()); |
585 | } |
586 | } |
587 | |
588 | template <class ELFT> |
589 | unsigned ELFState<ELFT>::toSectionIndex(StringRef S, StringRef LocSec, |
590 | StringRef LocSym) { |
591 | assert(LocSec.empty() || LocSym.empty()); |
592 | |
593 | unsigned Index; |
594 | if (!SN2I.lookup(Name: S, Idx&: Index) && !to_integer(S, Num&: Index)) { |
595 | if (!LocSym.empty()) |
596 | reportError("unknown section referenced: '" + S + "' by YAML symbol '" + |
597 | LocSym + "'" ); |
598 | else |
599 | reportError("unknown section referenced: '" + S + "' by YAML section '" + |
600 | LocSec + "'" ); |
601 | return 0; |
602 | } |
603 | |
604 | const ELFYAML::SectionHeaderTable & = |
605 | Doc.getSectionHeaderTable(); |
606 | if (SectionHeaders.IsImplicit || |
607 | (SectionHeaders.NoHeaders && !*SectionHeaders.NoHeaders) || |
608 | SectionHeaders.isDefault()) |
609 | return Index; |
610 | |
611 | assert(!SectionHeaders.NoHeaders.value_or(false) || !SectionHeaders.Sections); |
612 | size_t FirstExcluded = |
613 | SectionHeaders.Sections ? SectionHeaders.Sections->size() : 0; |
614 | if (Index > FirstExcluded) { |
615 | if (LocSym.empty()) |
616 | reportError("unable to link '" + LocSec + "' to excluded section '" + S + |
617 | "'" ); |
618 | else |
619 | reportError("excluded section referenced: '" + S + "' by symbol '" + |
620 | LocSym + "'" ); |
621 | } |
622 | return Index; |
623 | } |
624 | |
625 | template <class ELFT> |
626 | unsigned ELFState<ELFT>::toSymbolIndex(StringRef S, StringRef LocSec, |
627 | bool IsDynamic) { |
628 | const NameToIdxMap &SymMap = IsDynamic ? DynSymN2I : SymN2I; |
629 | unsigned Index; |
630 | // Here we try to look up S in the symbol table. If it is not there, |
631 | // treat its value as a symbol index. |
632 | if (!SymMap.lookup(Name: S, Idx&: Index) && !to_integer(S, Num&: Index)) { |
633 | reportError("unknown symbol referenced: '" + S + "' by YAML section '" + |
634 | LocSec + "'" ); |
635 | return 0; |
636 | } |
637 | return Index; |
638 | } |
639 | |
640 | template <class ELFT> |
641 | static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) { |
642 | if (!From) |
643 | return; |
644 | if (From->ShAddrAlign) |
645 | To.sh_addralign = *From->ShAddrAlign; |
646 | if (From->ShFlags) |
647 | To.sh_flags = *From->ShFlags; |
648 | if (From->ShName) |
649 | To.sh_name = *From->ShName; |
650 | if (From->ShOffset) |
651 | To.sh_offset = *From->ShOffset; |
652 | if (From->ShSize) |
653 | To.sh_size = *From->ShSize; |
654 | if (From->ShType) |
655 | To.sh_type = *From->ShType; |
656 | } |
657 | |
658 | template <class ELFT> |
659 | bool ELFState<ELFT>::(ContiguousBlobAccumulator &CBA, |
660 | Elf_Shdr &, StringRef SecName, |
661 | ELFYAML::Section *YAMLSec) { |
662 | // Check if the header was already initialized. |
663 | if (Header.sh_offset) |
664 | return false; |
665 | |
666 | if (SecName == ".strtab" ) |
667 | initStrtabSectionHeader(SHeader&: Header, Name: SecName, STB&: DotStrtab, CBA, YAMLSec); |
668 | else if (SecName == ".dynstr" ) |
669 | initStrtabSectionHeader(SHeader&: Header, Name: SecName, STB&: DotDynstr, CBA, YAMLSec); |
670 | else if (SecName == SectionHeaderStringTableName) |
671 | initStrtabSectionHeader(SHeader&: Header, Name: SecName, STB&: *ShStrtabStrings, CBA, YAMLSec); |
672 | else if (SecName == ".symtab" ) |
673 | initSymtabSectionHeader(SHeader&: Header, STType: SymtabType::Static, CBA, YAMLSec); |
674 | else if (SecName == ".dynsym" ) |
675 | initSymtabSectionHeader(SHeader&: Header, STType: SymtabType::Dynamic, CBA, YAMLSec); |
676 | else if (SecName.starts_with(Prefix: ".debug_" )) { |
677 | // If a ".debug_*" section's type is a preserved one, e.g., SHT_DYNAMIC, we |
678 | // will not treat it as a debug section. |
679 | if (YAMLSec && !isa<ELFYAML::RawContentSection>(Val: YAMLSec)) |
680 | return false; |
681 | initDWARFSectionHeader(SHeader&: Header, Name: SecName, CBA, YAMLSec); |
682 | } else |
683 | return false; |
684 | |
685 | LocationCounter += Header.sh_size; |
686 | |
687 | // Override section fields if requested. |
688 | overrideFields<ELFT>(YAMLSec, Header); |
689 | return true; |
690 | } |
691 | |
692 | constexpr char SuffixStart = '('; |
693 | constexpr char SuffixEnd = ')'; |
694 | |
695 | std::string llvm::ELFYAML::appendUniqueSuffix(StringRef Name, |
696 | const Twine &Msg) { |
697 | // Do not add a space when a Name is empty. |
698 | std::string Ret = Name.empty() ? "" : Name.str() + ' '; |
699 | return Ret + (Twine(SuffixStart) + Msg + Twine(SuffixEnd)).str(); |
700 | } |
701 | |
702 | StringRef llvm::ELFYAML::dropUniqueSuffix(StringRef S) { |
703 | if (S.empty() || S.back() != SuffixEnd) |
704 | return S; |
705 | |
706 | // A special case for empty names. See appendUniqueSuffix() above. |
707 | size_t SuffixPos = S.rfind(C: SuffixStart); |
708 | if (SuffixPos == 0) |
709 | return "" ; |
710 | |
711 | if (SuffixPos == StringRef::npos || S[SuffixPos - 1] != ' ') |
712 | return S; |
713 | return S.substr(Start: 0, N: SuffixPos - 1); |
714 | } |
715 | |
716 | template <class ELFT> |
717 | uint64_t ELFState<ELFT>::getSectionNameOffset(StringRef Name) { |
718 | // If a section is excluded from section headers, we do not save its name in |
719 | // the string table. |
720 | if (ExcludedSectionHeaders.count(Key: Name)) |
721 | return 0; |
722 | return ShStrtabStrings->getOffset(S: Name); |
723 | } |
724 | |
725 | static uint64_t writeContent(ContiguousBlobAccumulator &CBA, |
726 | const std::optional<yaml::BinaryRef> &Content, |
727 | const std::optional<llvm::yaml::Hex64> &Size) { |
728 | size_t ContentSize = 0; |
729 | if (Content) { |
730 | CBA.writeAsBinary(Bin: *Content); |
731 | ContentSize = Content->binary_size(); |
732 | } |
733 | |
734 | if (!Size) |
735 | return ContentSize; |
736 | |
737 | CBA.writeZeros(Num: *Size - ContentSize); |
738 | return *Size; |
739 | } |
740 | |
741 | static StringRef getDefaultLinkSec(unsigned SecType) { |
742 | switch (SecType) { |
743 | case ELF::SHT_REL: |
744 | case ELF::SHT_RELA: |
745 | case ELF::SHT_GROUP: |
746 | case ELF::SHT_LLVM_CALL_GRAPH_PROFILE: |
747 | case ELF::SHT_LLVM_ADDRSIG: |
748 | return ".symtab" ; |
749 | case ELF::SHT_GNU_versym: |
750 | case ELF::SHT_HASH: |
751 | case ELF::SHT_GNU_HASH: |
752 | return ".dynsym" ; |
753 | case ELF::SHT_DYNSYM: |
754 | case ELF::SHT_GNU_verdef: |
755 | case ELF::SHT_GNU_verneed: |
756 | return ".dynstr" ; |
757 | case ELF::SHT_SYMTAB: |
758 | return ".strtab" ; |
759 | default: |
760 | return "" ; |
761 | } |
762 | } |
763 | |
764 | template <class ELFT> |
765 | void ELFState<ELFT>::(std::vector<Elf_Shdr> &, |
766 | ContiguousBlobAccumulator &CBA) { |
767 | // Ensure SHN_UNDEF entry is present. An all-zero section header is a |
768 | // valid SHN_UNDEF entry since SHT_NULL == 0. |
769 | SHeaders.resize(Doc.getSections().size()); |
770 | |
771 | for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) { |
772 | if (ELFYAML::Fill *S = dyn_cast<ELFYAML::Fill>(Val: D.get())) { |
773 | S->Offset = alignToOffset(CBA, /*Align=*/1, Offset: S->Offset); |
774 | writeFill(Fill&: *S, CBA); |
775 | LocationCounter += S->Size; |
776 | continue; |
777 | } |
778 | |
779 | if (ELFYAML::SectionHeaderTable *S = |
780 | dyn_cast<ELFYAML::SectionHeaderTable>(Val: D.get())) { |
781 | if (S->NoHeaders.value_or(u: false)) |
782 | continue; |
783 | |
784 | if (!S->Offset) |
785 | S->Offset = alignToOffset(CBA, Align: sizeof(typename ELFT::uint), |
786 | /*Offset=*/std::nullopt); |
787 | else |
788 | S->Offset = alignToOffset(CBA, /*Align=*/1, Offset: S->Offset); |
789 | |
790 | uint64_t Size = S->getNumHeaders(SectionsNum: SHeaders.size()) * sizeof(Elf_Shdr); |
791 | // The full section header information might be not available here, so |
792 | // fill the space with zeroes as a placeholder. |
793 | CBA.writeZeros(Num: Size); |
794 | LocationCounter += Size; |
795 | continue; |
796 | } |
797 | |
798 | ELFYAML::Section *Sec = cast<ELFYAML::Section>(Val: D.get()); |
799 | bool IsFirstUndefSection = Sec == Doc.getSections().front(); |
800 | if (IsFirstUndefSection && Sec->IsImplicit) |
801 | continue; |
802 | |
803 | Elf_Shdr & = SHeaders[SN2I.get(Name: Sec->Name)]; |
804 | if (Sec->Link) { |
805 | SHeader.sh_link = toSectionIndex(S: *Sec->Link, LocSec: Sec->Name); |
806 | } else { |
807 | StringRef LinkSec = getDefaultLinkSec(SecType: Sec->Type); |
808 | unsigned Link = 0; |
809 | if (!LinkSec.empty() && !ExcludedSectionHeaders.count(Key: LinkSec) && |
810 | SN2I.lookup(Name: LinkSec, Idx&: Link)) |
811 | SHeader.sh_link = Link; |
812 | } |
813 | |
814 | if (Sec->EntSize) |
815 | SHeader.sh_entsize = *Sec->EntSize; |
816 | else |
817 | SHeader.sh_entsize = ELFYAML::getDefaultShEntSize<ELFT>( |
818 | Doc.Header.Machine.value_or(u: ELF::EM_NONE), Sec->Type, Sec->Name); |
819 | |
820 | // We have a few sections like string or symbol tables that are usually |
821 | // added implicitly to the end. However, if they are explicitly specified |
822 | // in the YAML, we need to write them here. This ensures the file offset |
823 | // remains correct. |
824 | if (initImplicitHeader(CBA, Header&: SHeader, SecName: Sec->Name, |
825 | YAMLSec: Sec->IsImplicit ? nullptr : Sec)) |
826 | continue; |
827 | |
828 | assert(Sec && "It can't be null unless it is an implicit section. But all " |
829 | "implicit sections should already have been handled above." ); |
830 | |
831 | SHeader.sh_name = |
832 | getSectionNameOffset(Name: ELFYAML::dropUniqueSuffix(S: Sec->Name)); |
833 | SHeader.sh_type = Sec->Type; |
834 | if (Sec->Flags) |
835 | SHeader.sh_flags = *Sec->Flags; |
836 | SHeader.sh_addralign = Sec->AddressAlign; |
837 | |
838 | // Set the offset for all sections, except the SHN_UNDEF section with index |
839 | // 0 when not explicitly requested. |
840 | if (!IsFirstUndefSection || Sec->Offset) |
841 | SHeader.sh_offset = alignToOffset(CBA, Align: SHeader.sh_addralign, Offset: Sec->Offset); |
842 | |
843 | assignSectionAddress(SHeader, YAMLSec: Sec); |
844 | |
845 | if (IsFirstUndefSection) { |
846 | if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Val: Sec)) { |
847 | // We do not write any content for special SHN_UNDEF section. |
848 | if (RawSec->Size) |
849 | SHeader.sh_size = *RawSec->Size; |
850 | if (RawSec->Info) |
851 | SHeader.sh_info = *RawSec->Info; |
852 | } |
853 | |
854 | LocationCounter += SHeader.sh_size; |
855 | overrideFields<ELFT>(Sec, SHeader); |
856 | continue; |
857 | } |
858 | |
859 | if (!isa<ELFYAML::NoBitsSection>(Val: Sec) && (Sec->Content || Sec->Size)) |
860 | SHeader.sh_size = writeContent(CBA, Content: Sec->Content, Size: Sec->Size); |
861 | |
862 | if (auto S = dyn_cast<ELFYAML::RawContentSection>(Val: Sec)) { |
863 | writeSectionContent(SHeader, *S, CBA); |
864 | } else if (auto S = dyn_cast<ELFYAML::SymtabShndxSection>(Val: Sec)) { |
865 | writeSectionContent(SHeader, *S, CBA); |
866 | } else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Val: Sec)) { |
867 | writeSectionContent(SHeader, *S, CBA); |
868 | } else if (auto S = dyn_cast<ELFYAML::RelrSection>(Val: Sec)) { |
869 | writeSectionContent(SHeader, *S, CBA); |
870 | } else if (auto S = dyn_cast<ELFYAML::GroupSection>(Val: Sec)) { |
871 | writeSectionContent(SHeader, *S, CBA); |
872 | } else if (auto S = dyn_cast<ELFYAML::ARMIndexTableSection>(Val: Sec)) { |
873 | writeSectionContent(SHeader, *S, CBA); |
874 | } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Val: Sec)) { |
875 | writeSectionContent(SHeader, *S, CBA); |
876 | } else if (auto S = dyn_cast<ELFYAML::NoBitsSection>(Val: Sec)) { |
877 | writeSectionContent(SHeader, *S, CBA); |
878 | } else if (auto S = dyn_cast<ELFYAML::DynamicSection>(Val: Sec)) { |
879 | writeSectionContent(SHeader, *S, CBA); |
880 | } else if (auto S = dyn_cast<ELFYAML::SymverSection>(Val: Sec)) { |
881 | writeSectionContent(SHeader, *S, CBA); |
882 | } else if (auto S = dyn_cast<ELFYAML::VerneedSection>(Val: Sec)) { |
883 | writeSectionContent(SHeader, *S, CBA); |
884 | } else if (auto S = dyn_cast<ELFYAML::VerdefSection>(Val: Sec)) { |
885 | writeSectionContent(SHeader, *S, CBA); |
886 | } else if (auto S = dyn_cast<ELFYAML::StackSizesSection>(Val: Sec)) { |
887 | writeSectionContent(SHeader, *S, CBA); |
888 | } else if (auto S = dyn_cast<ELFYAML::HashSection>(Val: Sec)) { |
889 | writeSectionContent(SHeader, *S, CBA); |
890 | } else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Val: Sec)) { |
891 | writeSectionContent(SHeader, *S, CBA); |
892 | } else if (auto S = dyn_cast<ELFYAML::LinkerOptionsSection>(Val: Sec)) { |
893 | writeSectionContent(SHeader, *S, CBA); |
894 | } else if (auto S = dyn_cast<ELFYAML::NoteSection>(Val: Sec)) { |
895 | writeSectionContent(SHeader, *S, CBA); |
896 | } else if (auto S = dyn_cast<ELFYAML::GnuHashSection>(Val: Sec)) { |
897 | writeSectionContent(SHeader, *S, CBA); |
898 | } else if (auto S = dyn_cast<ELFYAML::DependentLibrariesSection>(Val: Sec)) { |
899 | writeSectionContent(SHeader, *S, CBA); |
900 | } else if (auto S = dyn_cast<ELFYAML::CallGraphProfileSection>(Val: Sec)) { |
901 | writeSectionContent(SHeader, *S, CBA); |
902 | } else if (auto S = dyn_cast<ELFYAML::BBAddrMapSection>(Val: Sec)) { |
903 | writeSectionContent(SHeader, *S, CBA); |
904 | } else { |
905 | llvm_unreachable("Unknown section type" ); |
906 | } |
907 | |
908 | LocationCounter += SHeader.sh_size; |
909 | |
910 | // Override section fields if requested. |
911 | overrideFields<ELFT>(Sec, SHeader); |
912 | } |
913 | } |
914 | |
915 | template <class ELFT> |
916 | void ELFState<ELFT>::assignSectionAddress(Elf_Shdr &, |
917 | ELFYAML::Section *YAMLSec) { |
918 | if (YAMLSec && YAMLSec->Address) { |
919 | SHeader.sh_addr = *YAMLSec->Address; |
920 | LocationCounter = *YAMLSec->Address; |
921 | return; |
922 | } |
923 | |
924 | // sh_addr represents the address in the memory image of a process. Sections |
925 | // in a relocatable object file or non-allocatable sections do not need |
926 | // sh_addr assignment. |
927 | if (Doc.Header.Type.value == ELF::ET_REL || |
928 | !(SHeader.sh_flags & ELF::SHF_ALLOC)) |
929 | return; |
930 | |
931 | LocationCounter = |
932 | alignTo(LocationCounter, SHeader.sh_addralign ? SHeader.sh_addralign : 1); |
933 | SHeader.sh_addr = LocationCounter; |
934 | } |
935 | |
936 | static size_t findFirstNonGlobal(ArrayRef<ELFYAML::Symbol> Symbols) { |
937 | for (size_t I = 0; I < Symbols.size(); ++I) |
938 | if (Symbols[I].Binding.value != ELF::STB_LOCAL) |
939 | return I; |
940 | return Symbols.size(); |
941 | } |
942 | |
943 | template <class ELFT> |
944 | std::vector<typename ELFT::Sym> |
945 | ELFState<ELFT>::toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols, |
946 | const StringTableBuilder &Strtab) { |
947 | std::vector<Elf_Sym> Ret; |
948 | Ret.resize(Symbols.size() + 1); |
949 | |
950 | size_t I = 0; |
951 | for (const ELFYAML::Symbol &Sym : Symbols) { |
952 | Elf_Sym &Symbol = Ret[++I]; |
953 | |
954 | // If NameIndex, which contains the name offset, is explicitly specified, we |
955 | // use it. This is useful for preparing broken objects. Otherwise, we add |
956 | // the specified Name to the string table builder to get its offset. |
957 | if (Sym.StName) |
958 | Symbol.st_name = *Sym.StName; |
959 | else if (!Sym.Name.empty()) |
960 | Symbol.st_name = Strtab.getOffset(S: ELFYAML::dropUniqueSuffix(S: Sym.Name)); |
961 | |
962 | Symbol.setBindingAndType(Sym.Binding, Sym.Type); |
963 | if (Sym.Section) |
964 | Symbol.st_shndx = toSectionIndex(S: *Sym.Section, LocSec: "" , LocSym: Sym.Name); |
965 | else if (Sym.Index) |
966 | Symbol.st_shndx = *Sym.Index; |
967 | |
968 | Symbol.st_value = Sym.Value.value_or(u: yaml::Hex64(0)); |
969 | Symbol.st_other = Sym.Other ? *Sym.Other : 0; |
970 | Symbol.st_size = Sym.Size.value_or(u: yaml::Hex64(0)); |
971 | } |
972 | |
973 | return Ret; |
974 | } |
975 | |
976 | template <class ELFT> |
977 | void ELFState<ELFT>::(Elf_Shdr &, |
978 | SymtabType STType, |
979 | ContiguousBlobAccumulator &CBA, |
980 | ELFYAML::Section *YAMLSec) { |
981 | |
982 | bool IsStatic = STType == SymtabType::Static; |
983 | ArrayRef<ELFYAML::Symbol> Symbols; |
984 | if (IsStatic && Doc.Symbols) |
985 | Symbols = *Doc.Symbols; |
986 | else if (!IsStatic && Doc.DynamicSymbols) |
987 | Symbols = *Doc.DynamicSymbols; |
988 | |
989 | ELFYAML::RawContentSection *RawSec = |
990 | dyn_cast_or_null<ELFYAML::RawContentSection>(Val: YAMLSec); |
991 | if (RawSec && (RawSec->Content || RawSec->Size)) { |
992 | bool HasSymbolsDescription = |
993 | (IsStatic && Doc.Symbols) || (!IsStatic && Doc.DynamicSymbols); |
994 | if (HasSymbolsDescription) { |
995 | StringRef Property = (IsStatic ? "`Symbols`" : "`DynamicSymbols`" ); |
996 | if (RawSec->Content) |
997 | reportError("cannot specify both `Content` and " + Property + |
998 | " for symbol table section '" + RawSec->Name + "'" ); |
999 | if (RawSec->Size) |
1000 | reportError("cannot specify both `Size` and " + Property + |
1001 | " for symbol table section '" + RawSec->Name + "'" ); |
1002 | return; |
1003 | } |
1004 | } |
1005 | |
1006 | SHeader.sh_name = getSectionNameOffset(Name: IsStatic ? ".symtab" : ".dynsym" ); |
1007 | |
1008 | if (YAMLSec) |
1009 | SHeader.sh_type = YAMLSec->Type; |
1010 | else |
1011 | SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM; |
1012 | |
1013 | if (YAMLSec && YAMLSec->Flags) |
1014 | SHeader.sh_flags = *YAMLSec->Flags; |
1015 | else if (!IsStatic) |
1016 | SHeader.sh_flags = ELF::SHF_ALLOC; |
1017 | |
1018 | // If the symbol table section is explicitly described in the YAML |
1019 | // then we should set the fields requested. |
1020 | SHeader.sh_info = (RawSec && RawSec->Info) ? (unsigned)(*RawSec->Info) |
1021 | : findFirstNonGlobal(Symbols) + 1; |
1022 | SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 8; |
1023 | |
1024 | assignSectionAddress(SHeader, YAMLSec); |
1025 | |
1026 | SHeader.sh_offset = alignToOffset(CBA, Align: SHeader.sh_addralign, |
1027 | Offset: RawSec ? RawSec->Offset : std::nullopt); |
1028 | |
1029 | if (RawSec && (RawSec->Content || RawSec->Size)) { |
1030 | assert(Symbols.empty()); |
1031 | SHeader.sh_size = writeContent(CBA, Content: RawSec->Content, Size: RawSec->Size); |
1032 | return; |
1033 | } |
1034 | |
1035 | std::vector<Elf_Sym> Syms = |
1036 | toELFSymbols(Symbols, Strtab: IsStatic ? DotStrtab : DotDynstr); |
1037 | SHeader.sh_size = Syms.size() * sizeof(Elf_Sym); |
1038 | CBA.write((const char *)Syms.data(), SHeader.sh_size); |
1039 | } |
1040 | |
1041 | template <class ELFT> |
1042 | void ELFState<ELFT>::(Elf_Shdr &, StringRef Name, |
1043 | StringTableBuilder &STB, |
1044 | ContiguousBlobAccumulator &CBA, |
1045 | ELFYAML::Section *YAMLSec) { |
1046 | SHeader.sh_name = getSectionNameOffset(Name: ELFYAML::dropUniqueSuffix(S: Name)); |
1047 | SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_STRTAB; |
1048 | SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1; |
1049 | |
1050 | ELFYAML::RawContentSection *RawSec = |
1051 | dyn_cast_or_null<ELFYAML::RawContentSection>(Val: YAMLSec); |
1052 | |
1053 | SHeader.sh_offset = alignToOffset(CBA, Align: SHeader.sh_addralign, |
1054 | Offset: YAMLSec ? YAMLSec->Offset : std::nullopt); |
1055 | |
1056 | if (RawSec && (RawSec->Content || RawSec->Size)) { |
1057 | SHeader.sh_size = writeContent(CBA, Content: RawSec->Content, Size: RawSec->Size); |
1058 | } else { |
1059 | if (raw_ostream *OS = CBA.getRawOS(Size: STB.getSize())) |
1060 | STB.write(OS&: *OS); |
1061 | SHeader.sh_size = STB.getSize(); |
1062 | } |
1063 | |
1064 | if (RawSec && RawSec->Info) |
1065 | SHeader.sh_info = *RawSec->Info; |
1066 | |
1067 | if (YAMLSec && YAMLSec->Flags) |
1068 | SHeader.sh_flags = *YAMLSec->Flags; |
1069 | else if (Name == ".dynstr" ) |
1070 | SHeader.sh_flags = ELF::SHF_ALLOC; |
1071 | |
1072 | assignSectionAddress(SHeader, YAMLSec); |
1073 | } |
1074 | |
1075 | static bool shouldEmitDWARF(DWARFYAML::Data &DWARF, StringRef Name) { |
1076 | SetVector<StringRef> DebugSecNames = DWARF.getNonEmptySectionNames(); |
1077 | return Name.consume_front(Prefix: "." ) && DebugSecNames.count(key: Name); |
1078 | } |
1079 | |
1080 | template <class ELFT> |
1081 | Expected<uint64_t> emitDWARF(typename ELFT::Shdr &, StringRef Name, |
1082 | const DWARFYAML::Data &DWARF, |
1083 | ContiguousBlobAccumulator &CBA) { |
1084 | // We are unable to predict the size of debug data, so we request to write 0 |
1085 | // bytes. This should always return us an output stream unless CBA is already |
1086 | // in an error state. |
1087 | raw_ostream *OS = CBA.getRawOS(Size: 0); |
1088 | if (!OS) |
1089 | return 0; |
1090 | |
1091 | uint64_t BeginOffset = CBA.tell(); |
1092 | |
1093 | auto EmitFunc = DWARFYAML::getDWARFEmitterByName(SecName: Name.substr(Start: 1)); |
1094 | if (Error Err = EmitFunc(*OS, DWARF)) |
1095 | return std::move(Err); |
1096 | |
1097 | return CBA.tell() - BeginOffset; |
1098 | } |
1099 | |
1100 | template <class ELFT> |
1101 | void ELFState<ELFT>::(Elf_Shdr &, StringRef Name, |
1102 | ContiguousBlobAccumulator &CBA, |
1103 | ELFYAML::Section *YAMLSec) { |
1104 | SHeader.sh_name = getSectionNameOffset(Name: ELFYAML::dropUniqueSuffix(S: Name)); |
1105 | SHeader.sh_type = YAMLSec ? YAMLSec->Type : ELF::SHT_PROGBITS; |
1106 | SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 1; |
1107 | SHeader.sh_offset = alignToOffset(CBA, Align: SHeader.sh_addralign, |
1108 | Offset: YAMLSec ? YAMLSec->Offset : std::nullopt); |
1109 | |
1110 | ELFYAML::RawContentSection *RawSec = |
1111 | dyn_cast_or_null<ELFYAML::RawContentSection>(Val: YAMLSec); |
1112 | if (Doc.DWARF && shouldEmitDWARF(DWARF&: *Doc.DWARF, Name)) { |
1113 | if (RawSec && (RawSec->Content || RawSec->Size)) |
1114 | reportError("cannot specify section '" + Name + |
1115 | "' contents in the 'DWARF' entry and the 'Content' " |
1116 | "or 'Size' in the 'Sections' entry at the same time" ); |
1117 | else { |
1118 | if (Expected<uint64_t> ShSizeOrErr = |
1119 | emitDWARF<ELFT>(SHeader, Name, *Doc.DWARF, CBA)) |
1120 | SHeader.sh_size = *ShSizeOrErr; |
1121 | else |
1122 | reportError(ShSizeOrErr.takeError()); |
1123 | } |
1124 | } else if (RawSec) |
1125 | SHeader.sh_size = writeContent(CBA, Content: RawSec->Content, Size: RawSec->Size); |
1126 | else |
1127 | llvm_unreachable("debug sections can only be initialized via the 'DWARF' " |
1128 | "entry or a RawContentSection" ); |
1129 | |
1130 | if (RawSec && RawSec->Info) |
1131 | SHeader.sh_info = *RawSec->Info; |
1132 | |
1133 | if (YAMLSec && YAMLSec->Flags) |
1134 | SHeader.sh_flags = *YAMLSec->Flags; |
1135 | else if (Name == ".debug_str" ) |
1136 | SHeader.sh_flags = ELF::SHF_MERGE | ELF::SHF_STRINGS; |
1137 | |
1138 | assignSectionAddress(SHeader, YAMLSec); |
1139 | } |
1140 | |
1141 | template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) { |
1142 | ErrHandler(Msg); |
1143 | HasError = true; |
1144 | } |
1145 | |
1146 | template <class ELFT> void ELFState<ELFT>::reportError(Error Err) { |
1147 | handleAllErrors(std::move(Err), [&](const ErrorInfoBase &Err) { |
1148 | reportError(Err.message()); |
1149 | }); |
1150 | } |
1151 | |
1152 | template <class ELFT> |
1153 | std::vector<Fragment> |
1154 | ELFState<ELFT>::(const ELFYAML::ProgramHeader &Phdr, |
1155 | ArrayRef<Elf_Shdr> ) { |
1156 | std::vector<Fragment> Ret; |
1157 | for (const ELFYAML::Chunk *C : Phdr.Chunks) { |
1158 | if (const ELFYAML::Fill *F = dyn_cast<ELFYAML::Fill>(Val: C)) { |
1159 | Ret.push_back(x: {.Offset: *F->Offset, .Size: F->Size, .Type: llvm::ELF::SHT_PROGBITS, |
1160 | /*ShAddrAlign=*/.AddrAlign: 1}); |
1161 | continue; |
1162 | } |
1163 | |
1164 | const ELFYAML::Section *S = cast<ELFYAML::Section>(Val: C); |
1165 | const Elf_Shdr &H = SHeaders[SN2I.get(Name: S->Name)]; |
1166 | Ret.push_back({H.sh_offset, H.sh_size, H.sh_type, H.sh_addralign}); |
1167 | } |
1168 | return Ret; |
1169 | } |
1170 | |
1171 | template <class ELFT> |
1172 | void ELFState<ELFT>::(std::vector<Elf_Phdr> &, |
1173 | std::vector<Elf_Shdr> &) { |
1174 | uint32_t PhdrIdx = 0; |
1175 | for (auto &YamlPhdr : Doc.ProgramHeaders) { |
1176 | Elf_Phdr & = PHeaders[PhdrIdx++]; |
1177 | std::vector<Fragment> Fragments = getPhdrFragments(Phdr: YamlPhdr, SHeaders); |
1178 | if (!llvm::is_sorted(Fragments, [](const Fragment &A, const Fragment &B) { |
1179 | return A.Offset < B.Offset; |
1180 | })) |
1181 | reportError("sections in the program header with index " + |
1182 | Twine(PhdrIdx) + " are not sorted by their file offset" ); |
1183 | |
1184 | if (YamlPhdr.Offset) { |
1185 | if (!Fragments.empty() && *YamlPhdr.Offset > Fragments.front().Offset) |
1186 | reportError("'Offset' for segment with index " + Twine(PhdrIdx) + |
1187 | " must be less than or equal to the minimum file offset of " |
1188 | "all included sections (0x" + |
1189 | Twine::utohexstr(Val: Fragments.front().Offset) + ")" ); |
1190 | PHeader.p_offset = *YamlPhdr.Offset; |
1191 | } else if (!Fragments.empty()) { |
1192 | PHeader.p_offset = Fragments.front().Offset; |
1193 | } |
1194 | |
1195 | // Set the file size if not set explicitly. |
1196 | if (YamlPhdr.FileSize) { |
1197 | PHeader.p_filesz = *YamlPhdr.FileSize; |
1198 | } else if (!Fragments.empty()) { |
1199 | uint64_t FileSize = Fragments.back().Offset - PHeader.p_offset; |
1200 | // SHT_NOBITS sections occupy no physical space in a file, we should not |
1201 | // take their sizes into account when calculating the file size of a |
1202 | // segment. |
1203 | if (Fragments.back().Type != llvm::ELF::SHT_NOBITS) |
1204 | FileSize += Fragments.back().Size; |
1205 | PHeader.p_filesz = FileSize; |
1206 | } |
1207 | |
1208 | // Find the maximum offset of the end of a section in order to set p_memsz. |
1209 | uint64_t MemOffset = PHeader.p_offset; |
1210 | for (const Fragment &F : Fragments) |
1211 | MemOffset = std::max(a: MemOffset, b: F.Offset + F.Size); |
1212 | // Set the memory size if not set explicitly. |
1213 | PHeader.p_memsz = YamlPhdr.MemSize ? uint64_t(*YamlPhdr.MemSize) |
1214 | : MemOffset - PHeader.p_offset; |
1215 | |
1216 | if (YamlPhdr.Align) { |
1217 | PHeader.p_align = *YamlPhdr.Align; |
1218 | } else { |
1219 | // Set the alignment of the segment to be the maximum alignment of the |
1220 | // sections so that by default the segment has a valid and sensible |
1221 | // alignment. |
1222 | PHeader.p_align = 1; |
1223 | for (const Fragment &F : Fragments) |
1224 | PHeader.p_align = std::max(a: (uint64_t)PHeader.p_align, b: F.AddrAlign); |
1225 | } |
1226 | } |
1227 | } |
1228 | |
1229 | bool llvm::ELFYAML::( |
1230 | ArrayRef<ELFYAML::ProgramHeader> Phdrs, const ELFYAML::NoBitsSection &S) { |
1231 | for (const ELFYAML::ProgramHeader &PH : Phdrs) { |
1232 | auto It = llvm::find_if( |
1233 | Range: PH.Chunks, P: [&](ELFYAML::Chunk *C) { return C->Name == S.Name; }); |
1234 | if (std::any_of(first: It, last: PH.Chunks.end(), pred: [](ELFYAML::Chunk *C) { |
1235 | return (isa<ELFYAML::Fill>(Val: C) || |
1236 | cast<ELFYAML::Section>(Val: C)->Type != ELF::SHT_NOBITS); |
1237 | })) |
1238 | return true; |
1239 | } |
1240 | return false; |
1241 | } |
1242 | |
1243 | template <class ELFT> |
1244 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1245 | const ELFYAML::NoBitsSection &S, |
1246 | ContiguousBlobAccumulator &CBA) { |
1247 | if (!S.Size) |
1248 | return; |
1249 | |
1250 | SHeader.sh_size = *S.Size; |
1251 | |
1252 | // When a nobits section is followed by a non-nobits section or fill |
1253 | // in the same segment, we allocate the file space for it. This behavior |
1254 | // matches linkers. |
1255 | if (shouldAllocateFileSpace(Phdrs: Doc.ProgramHeaders, S)) |
1256 | CBA.writeZeros(Num: *S.Size); |
1257 | } |
1258 | |
1259 | template <class ELFT> |
1260 | void ELFState<ELFT>::writeSectionContent( |
1261 | Elf_Shdr &, const ELFYAML::RawContentSection &Section, |
1262 | ContiguousBlobAccumulator &CBA) { |
1263 | if (Section.Info) |
1264 | SHeader.sh_info = *Section.Info; |
1265 | } |
1266 | |
1267 | static bool isMips64EL(const ELFYAML::Object &Obj) { |
1268 | return Obj.getMachine() == llvm::ELF::EM_MIPS && |
1269 | Obj.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64) && |
1270 | Obj.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); |
1271 | } |
1272 | |
1273 | template <class ELFT> |
1274 | void ELFState<ELFT>::writeSectionContent( |
1275 | Elf_Shdr &, const ELFYAML::RelocationSection &Section, |
1276 | ContiguousBlobAccumulator &CBA) { |
1277 | assert((Section.Type == llvm::ELF::SHT_REL || |
1278 | Section.Type == llvm::ELF::SHT_RELA || |
1279 | Section.Type == llvm::ELF::SHT_CREL) && |
1280 | "Section type is not SHT_REL nor SHT_RELA" ); |
1281 | |
1282 | if (!Section.RelocatableSec.empty()) |
1283 | SHeader.sh_info = toSectionIndex(S: Section.RelocatableSec, LocSec: Section.Name); |
1284 | |
1285 | if (!Section.Relocations) |
1286 | return; |
1287 | |
1288 | const bool IsCrel = Section.Type == llvm::ELF::SHT_CREL; |
1289 | const bool IsRela = Section.Type == llvm::ELF::SHT_RELA; |
1290 | typename ELFT::uint OffsetMask = 8, Offset = 0, Addend = 0; |
1291 | uint32_t SymIdx = 0, Type = 0; |
1292 | uint64_t CurrentOffset = CBA.getOffset(); |
1293 | if (IsCrel) |
1294 | for (const ELFYAML::Relocation &Rel : *Section.Relocations) |
1295 | OffsetMask |= Rel.Offset; |
1296 | const int Shift = llvm::countr_zero(OffsetMask); |
1297 | if (IsCrel) |
1298 | CBA.writeULEB128(Val: Section.Relocations->size() * 8 + ELF::CREL_HDR_ADDEND + |
1299 | Shift); |
1300 | for (const ELFYAML::Relocation &Rel : *Section.Relocations) { |
1301 | const bool IsDynamic = Section.Link && (*Section.Link == ".dynsym" ); |
1302 | uint32_t CurSymIdx = |
1303 | Rel.Symbol ? toSymbolIndex(S: *Rel.Symbol, LocSec: Section.Name, IsDynamic) : 0; |
1304 | if (IsCrel) { |
1305 | // The delta offset and flags member may be larger than uint64_t. Special |
1306 | // case the first byte (3 flag bits and 4 offset bits). Other ULEB128 |
1307 | // bytes encode the remaining delta offset bits. |
1308 | auto DeltaOffset = |
1309 | (static_cast<typename ELFT::uint>(Rel.Offset) - Offset) >> Shift; |
1310 | Offset = Rel.Offset; |
1311 | uint8_t B = |
1312 | DeltaOffset * 8 + (SymIdx != CurSymIdx) + (Type != Rel.Type ? 2 : 0) + |
1313 | (Addend != static_cast<typename ELFT::uint>(Rel.Addend) ? 4 : 0); |
1314 | if (DeltaOffset < 0x10) { |
1315 | CBA.write(C: B); |
1316 | } else { |
1317 | CBA.write(C: B | 0x80); |
1318 | CBA.writeULEB128(Val: DeltaOffset >> 4); |
1319 | } |
1320 | // Delta symidx/type/addend members (SLEB128). |
1321 | if (B & 1) { |
1322 | CBA.writeSLEB128( |
1323 | Val: std::make_signed_t<typename ELFT::uint>(CurSymIdx - SymIdx)); |
1324 | SymIdx = CurSymIdx; |
1325 | } |
1326 | if (B & 2) { |
1327 | CBA.writeSLEB128(Val: static_cast<int32_t>(Rel.Type - Type)); |
1328 | Type = Rel.Type; |
1329 | } |
1330 | if (B & 4) { |
1331 | CBA.writeSLEB128( |
1332 | Val: std::make_signed_t<typename ELFT::uint>(Rel.Addend - Addend)); |
1333 | Addend = Rel.Addend; |
1334 | } |
1335 | } else if (IsRela) { |
1336 | Elf_Rela REntry; |
1337 | zero(REntry); |
1338 | REntry.r_offset = Rel.Offset; |
1339 | REntry.r_addend = Rel.Addend; |
1340 | REntry.setSymbolAndType(CurSymIdx, Rel.Type, isMips64EL(Obj: Doc)); |
1341 | CBA.write(Ptr: (const char *)&REntry, Size: sizeof(REntry)); |
1342 | } else { |
1343 | Elf_Rel REntry; |
1344 | zero(REntry); |
1345 | REntry.r_offset = Rel.Offset; |
1346 | REntry.setSymbolAndType(CurSymIdx, Rel.Type, isMips64EL(Obj: Doc)); |
1347 | CBA.write(Ptr: (const char *)&REntry, Size: sizeof(REntry)); |
1348 | } |
1349 | } |
1350 | |
1351 | SHeader.sh_size = CBA.getOffset() - CurrentOffset; |
1352 | } |
1353 | |
1354 | template <class ELFT> |
1355 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1356 | const ELFYAML::RelrSection &Section, |
1357 | ContiguousBlobAccumulator &CBA) { |
1358 | if (!Section.Entries) |
1359 | return; |
1360 | |
1361 | for (llvm::yaml::Hex64 E : *Section.Entries) { |
1362 | if (!ELFT::Is64Bits && E > UINT32_MAX) |
1363 | reportError(Section.Name + ": the value is too large for 32-bits: 0x" + |
1364 | Twine::utohexstr(Val: E)); |
1365 | CBA.write<uintX_t>(E, ELFT::Endianness); |
1366 | } |
1367 | |
1368 | SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size(); |
1369 | } |
1370 | |
1371 | template <class ELFT> |
1372 | void ELFState<ELFT>::writeSectionContent( |
1373 | Elf_Shdr &, const ELFYAML::SymtabShndxSection &Shndx, |
1374 | ContiguousBlobAccumulator &CBA) { |
1375 | if (Shndx.Content || Shndx.Size) { |
1376 | SHeader.sh_size = writeContent(CBA, Content: Shndx.Content, Size: Shndx.Size); |
1377 | return; |
1378 | } |
1379 | |
1380 | if (!Shndx.Entries) |
1381 | return; |
1382 | |
1383 | for (uint32_t E : *Shndx.Entries) |
1384 | CBA.write<uint32_t>(E, ELFT::Endianness); |
1385 | SHeader.sh_size = Shndx.Entries->size() * SHeader.sh_entsize; |
1386 | } |
1387 | |
1388 | template <class ELFT> |
1389 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1390 | const ELFYAML::GroupSection &Section, |
1391 | ContiguousBlobAccumulator &CBA) { |
1392 | assert(Section.Type == llvm::ELF::SHT_GROUP && |
1393 | "Section type is not SHT_GROUP" ); |
1394 | |
1395 | if (Section.Signature) |
1396 | SHeader.sh_info = |
1397 | toSymbolIndex(S: *Section.Signature, LocSec: Section.Name, /*IsDynamic=*/false); |
1398 | |
1399 | if (!Section.Members) |
1400 | return; |
1401 | |
1402 | for (const ELFYAML::SectionOrType &Member : *Section.Members) { |
1403 | unsigned int SectionIndex = 0; |
1404 | if (Member.sectionNameOrType == "GRP_COMDAT" ) |
1405 | SectionIndex = llvm::ELF::GRP_COMDAT; |
1406 | else |
1407 | SectionIndex = toSectionIndex(S: Member.sectionNameOrType, LocSec: Section.Name); |
1408 | CBA.write<uint32_t>(SectionIndex, ELFT::Endianness); |
1409 | } |
1410 | SHeader.sh_size = SHeader.sh_entsize * Section.Members->size(); |
1411 | } |
1412 | |
1413 | template <class ELFT> |
1414 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1415 | const ELFYAML::SymverSection &Section, |
1416 | ContiguousBlobAccumulator &CBA) { |
1417 | if (!Section.Entries) |
1418 | return; |
1419 | |
1420 | for (uint16_t Version : *Section.Entries) |
1421 | CBA.write<uint16_t>(Version, ELFT::Endianness); |
1422 | SHeader.sh_size = Section.Entries->size() * SHeader.sh_entsize; |
1423 | } |
1424 | |
1425 | template <class ELFT> |
1426 | void ELFState<ELFT>::writeSectionContent( |
1427 | Elf_Shdr &, const ELFYAML::StackSizesSection &Section, |
1428 | ContiguousBlobAccumulator &CBA) { |
1429 | if (!Section.Entries) |
1430 | return; |
1431 | |
1432 | for (const ELFYAML::StackSizeEntry &E : *Section.Entries) { |
1433 | CBA.write<uintX_t>(E.Address, ELFT::Endianness); |
1434 | SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(Val: E.Size); |
1435 | } |
1436 | } |
1437 | |
1438 | template <class ELFT> |
1439 | void ELFState<ELFT>::writeSectionContent( |
1440 | Elf_Shdr &, const ELFYAML::BBAddrMapSection &Section, |
1441 | ContiguousBlobAccumulator &CBA) { |
1442 | if (!Section.Entries) { |
1443 | if (Section.PGOAnalyses) |
1444 | WithColor::warning() |
1445 | << "PGOAnalyses should not exist in SHT_LLVM_BB_ADDR_MAP when " |
1446 | "Entries does not exist" ; |
1447 | return; |
1448 | } |
1449 | |
1450 | const std::vector<ELFYAML::PGOAnalysisMapEntry> *PGOAnalyses = nullptr; |
1451 | if (Section.PGOAnalyses) { |
1452 | if (Section.Entries->size() != Section.PGOAnalyses->size()) |
1453 | WithColor::warning() << "PGOAnalyses must be the same length as Entries " |
1454 | "in SHT_LLVM_BB_ADDR_MAP" ; |
1455 | else |
1456 | PGOAnalyses = &Section.PGOAnalyses.value(); |
1457 | } |
1458 | |
1459 | for (const auto &[Idx, E] : llvm::enumerate(First: *Section.Entries)) { |
1460 | // Write version and feature values. |
1461 | if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP) { |
1462 | if (E.Version > 2) |
1463 | WithColor::warning() << "unsupported SHT_LLVM_BB_ADDR_MAP version: " |
1464 | << static_cast<int>(E.Version) |
1465 | << "; encoding using the most recent version" ; |
1466 | CBA.write(C: E.Version); |
1467 | CBA.write(C: E.Feature); |
1468 | SHeader.sh_size += 2; |
1469 | } |
1470 | auto FeatureOrErr = llvm::object::BBAddrMap::Features::decode(Val: E.Feature); |
1471 | bool MultiBBRangeFeatureEnabled = false; |
1472 | if (!FeatureOrErr) |
1473 | WithColor::warning() << toString(E: FeatureOrErr.takeError()); |
1474 | else |
1475 | MultiBBRangeFeatureEnabled = FeatureOrErr->MultiBBRange; |
1476 | bool MultiBBRange = |
1477 | MultiBBRangeFeatureEnabled || |
1478 | (E.NumBBRanges.has_value() && E.NumBBRanges.value() != 1) || |
1479 | (E.BBRanges && E.BBRanges->size() != 1); |
1480 | if (MultiBBRange && !MultiBBRangeFeatureEnabled) |
1481 | WithColor::warning() << "feature value(" << E.Feature |
1482 | << ") does not support multiple BB ranges." ; |
1483 | if (MultiBBRange) { |
1484 | // Write the number of basic block ranges, which is overridden by the |
1485 | // 'NumBBRanges' field when specified. |
1486 | uint64_t NumBBRanges = |
1487 | E.NumBBRanges.value_or(u: E.BBRanges ? E.BBRanges->size() : 0); |
1488 | SHeader.sh_size += CBA.writeULEB128(Val: NumBBRanges); |
1489 | } |
1490 | if (!E.BBRanges) |
1491 | continue; |
1492 | uint64_t TotalNumBlocks = 0; |
1493 | for (const ELFYAML::BBAddrMapEntry::BBRangeEntry &BBR : *E.BBRanges) { |
1494 | // Write the base address of the range. |
1495 | CBA.write<uintX_t>(BBR.BaseAddress, ELFT::Endianness); |
1496 | // Write number of BBEntries (number of basic blocks in this basic block |
1497 | // range). This is overridden by the 'NumBlocks' YAML field when |
1498 | // specified. |
1499 | uint64_t NumBlocks = |
1500 | BBR.NumBlocks.value_or(u: BBR.BBEntries ? BBR.BBEntries->size() : 0); |
1501 | SHeader.sh_size += sizeof(uintX_t) + CBA.writeULEB128(Val: NumBlocks); |
1502 | // Write all BBEntries in this BBRange. |
1503 | if (!BBR.BBEntries) |
1504 | continue; |
1505 | for (const ELFYAML::BBAddrMapEntry::BBEntry &BBE : *BBR.BBEntries) { |
1506 | ++TotalNumBlocks; |
1507 | if (Section.Type == llvm::ELF::SHT_LLVM_BB_ADDR_MAP && E.Version > 1) |
1508 | SHeader.sh_size += CBA.writeULEB128(Val: BBE.ID); |
1509 | SHeader.sh_size += CBA.writeULEB128(Val: BBE.AddressOffset); |
1510 | SHeader.sh_size += CBA.writeULEB128(Val: BBE.Size); |
1511 | SHeader.sh_size += CBA.writeULEB128(Val: BBE.Metadata); |
1512 | } |
1513 | } |
1514 | if (!PGOAnalyses) |
1515 | continue; |
1516 | const ELFYAML::PGOAnalysisMapEntry &PGOEntry = PGOAnalyses->at(n: Idx); |
1517 | |
1518 | if (PGOEntry.FuncEntryCount) |
1519 | SHeader.sh_size += CBA.writeULEB128(Val: *PGOEntry.FuncEntryCount); |
1520 | |
1521 | if (!PGOEntry.PGOBBEntries) |
1522 | continue; |
1523 | |
1524 | const auto &PGOBBEntries = PGOEntry.PGOBBEntries.value(); |
1525 | if (TotalNumBlocks != PGOBBEntries.size()) { |
1526 | WithColor::warning() << "PBOBBEntries must be the same length as " |
1527 | "BBEntries in SHT_LLVM_BB_ADDR_MAP.\n" |
1528 | << "Mismatch on function with address: " |
1529 | << E.getFunctionAddress(); |
1530 | continue; |
1531 | } |
1532 | |
1533 | for (const auto &PGOBBE : PGOBBEntries) { |
1534 | if (PGOBBE.BBFreq) |
1535 | SHeader.sh_size += CBA.writeULEB128(Val: *PGOBBE.BBFreq); |
1536 | if (PGOBBE.Successors) { |
1537 | SHeader.sh_size += CBA.writeULEB128(Val: PGOBBE.Successors->size()); |
1538 | for (const auto &[ID, BrProb] : *PGOBBE.Successors) { |
1539 | SHeader.sh_size += CBA.writeULEB128(Val: ID); |
1540 | SHeader.sh_size += CBA.writeULEB128(Val: BrProb); |
1541 | } |
1542 | } |
1543 | } |
1544 | } |
1545 | } |
1546 | |
1547 | template <class ELFT> |
1548 | void ELFState<ELFT>::writeSectionContent( |
1549 | Elf_Shdr &, const ELFYAML::LinkerOptionsSection &Section, |
1550 | ContiguousBlobAccumulator &CBA) { |
1551 | if (!Section.Options) |
1552 | return; |
1553 | |
1554 | for (const ELFYAML::LinkerOption &LO : *Section.Options) { |
1555 | CBA.write(Ptr: LO.Key.data(), Size: LO.Key.size()); |
1556 | CBA.write(C: '\0'); |
1557 | CBA.write(Ptr: LO.Value.data(), Size: LO.Value.size()); |
1558 | CBA.write(C: '\0'); |
1559 | SHeader.sh_size += (LO.Key.size() + LO.Value.size() + 2); |
1560 | } |
1561 | } |
1562 | |
1563 | template <class ELFT> |
1564 | void ELFState<ELFT>::writeSectionContent( |
1565 | Elf_Shdr &, const ELFYAML::DependentLibrariesSection &Section, |
1566 | ContiguousBlobAccumulator &CBA) { |
1567 | if (!Section.Libs) |
1568 | return; |
1569 | |
1570 | for (StringRef Lib : *Section.Libs) { |
1571 | CBA.write(Ptr: Lib.data(), Size: Lib.size()); |
1572 | CBA.write(C: '\0'); |
1573 | SHeader.sh_size += Lib.size() + 1; |
1574 | } |
1575 | } |
1576 | |
1577 | template <class ELFT> |
1578 | uint64_t |
1579 | ELFState<ELFT>::alignToOffset(ContiguousBlobAccumulator &CBA, uint64_t Align, |
1580 | std::optional<llvm::yaml::Hex64> Offset) { |
1581 | uint64_t CurrentOffset = CBA.getOffset(); |
1582 | uint64_t AlignedOffset; |
1583 | |
1584 | if (Offset) { |
1585 | if ((uint64_t)*Offset < CurrentOffset) { |
1586 | reportError("the 'Offset' value (0x" + |
1587 | Twine::utohexstr(Val: (uint64_t)*Offset) + ") goes backward" ); |
1588 | return CurrentOffset; |
1589 | } |
1590 | |
1591 | // We ignore an alignment when an explicit offset has been requested. |
1592 | AlignedOffset = *Offset; |
1593 | } else { |
1594 | AlignedOffset = alignTo(Value: CurrentOffset, Align: std::max(a: Align, b: (uint64_t)1)); |
1595 | } |
1596 | |
1597 | CBA.writeZeros(Num: AlignedOffset - CurrentOffset); |
1598 | return AlignedOffset; |
1599 | } |
1600 | |
1601 | template <class ELFT> |
1602 | void ELFState<ELFT>::writeSectionContent( |
1603 | Elf_Shdr &, const ELFYAML::CallGraphProfileSection &Section, |
1604 | ContiguousBlobAccumulator &CBA) { |
1605 | if (!Section.Entries) |
1606 | return; |
1607 | |
1608 | for (const ELFYAML::CallGraphEntryWeight &E : *Section.Entries) { |
1609 | CBA.write<uint64_t>(E.Weight, ELFT::Endianness); |
1610 | SHeader.sh_size += sizeof(object::Elf_CGProfile_Impl<ELFT>); |
1611 | } |
1612 | } |
1613 | |
1614 | template <class ELFT> |
1615 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1616 | const ELFYAML::HashSection &Section, |
1617 | ContiguousBlobAccumulator &CBA) { |
1618 | if (!Section.Bucket) |
1619 | return; |
1620 | |
1621 | CBA.write<uint32_t>( |
1622 | Section.NBucket.value_or(u: llvm::yaml::Hex64(Section.Bucket->size())), |
1623 | ELFT::Endianness); |
1624 | CBA.write<uint32_t>( |
1625 | Section.NChain.value_or(u: llvm::yaml::Hex64(Section.Chain->size())), |
1626 | ELFT::Endianness); |
1627 | |
1628 | for (uint32_t Val : *Section.Bucket) |
1629 | CBA.write<uint32_t>(Val, ELFT::Endianness); |
1630 | for (uint32_t Val : *Section.Chain) |
1631 | CBA.write<uint32_t>(Val, ELFT::Endianness); |
1632 | |
1633 | SHeader.sh_size = (2 + Section.Bucket->size() + Section.Chain->size()) * 4; |
1634 | } |
1635 | |
1636 | template <class ELFT> |
1637 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1638 | const ELFYAML::VerdefSection &Section, |
1639 | ContiguousBlobAccumulator &CBA) { |
1640 | |
1641 | if (Section.Info) |
1642 | SHeader.sh_info = *Section.Info; |
1643 | else if (Section.Entries) |
1644 | SHeader.sh_info = Section.Entries->size(); |
1645 | |
1646 | if (!Section.Entries) |
1647 | return; |
1648 | |
1649 | uint64_t AuxCnt = 0; |
1650 | for (size_t I = 0; I < Section.Entries->size(); ++I) { |
1651 | const ELFYAML::VerdefEntry &E = (*Section.Entries)[I]; |
1652 | |
1653 | Elf_Verdef VerDef; |
1654 | VerDef.vd_version = E.Version.value_or(u: 1); |
1655 | VerDef.vd_flags = E.Flags.value_or(u: 0); |
1656 | VerDef.vd_ndx = E.VersionNdx.value_or(u: 0); |
1657 | VerDef.vd_hash = E.Hash.value_or(u: 0); |
1658 | VerDef.vd_aux = sizeof(Elf_Verdef); |
1659 | VerDef.vd_cnt = E.VerNames.size(); |
1660 | if (I == Section.Entries->size() - 1) |
1661 | VerDef.vd_next = 0; |
1662 | else |
1663 | VerDef.vd_next = |
1664 | sizeof(Elf_Verdef) + E.VerNames.size() * sizeof(Elf_Verdaux); |
1665 | CBA.write(Ptr: (const char *)&VerDef, Size: sizeof(Elf_Verdef)); |
1666 | |
1667 | for (size_t J = 0; J < E.VerNames.size(); ++J, ++AuxCnt) { |
1668 | Elf_Verdaux VernAux; |
1669 | VernAux.vda_name = DotDynstr.getOffset(S: E.VerNames[J]); |
1670 | if (J == E.VerNames.size() - 1) |
1671 | VernAux.vda_next = 0; |
1672 | else |
1673 | VernAux.vda_next = sizeof(Elf_Verdaux); |
1674 | CBA.write(Ptr: (const char *)&VernAux, Size: sizeof(Elf_Verdaux)); |
1675 | } |
1676 | } |
1677 | |
1678 | SHeader.sh_size = Section.Entries->size() * sizeof(Elf_Verdef) + |
1679 | AuxCnt * sizeof(Elf_Verdaux); |
1680 | } |
1681 | |
1682 | template <class ELFT> |
1683 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1684 | const ELFYAML::VerneedSection &Section, |
1685 | ContiguousBlobAccumulator &CBA) { |
1686 | if (Section.Info) |
1687 | SHeader.sh_info = *Section.Info; |
1688 | else if (Section.VerneedV) |
1689 | SHeader.sh_info = Section.VerneedV->size(); |
1690 | |
1691 | if (!Section.VerneedV) |
1692 | return; |
1693 | |
1694 | uint64_t AuxCnt = 0; |
1695 | for (size_t I = 0; I < Section.VerneedV->size(); ++I) { |
1696 | const ELFYAML::VerneedEntry &VE = (*Section.VerneedV)[I]; |
1697 | |
1698 | Elf_Verneed VerNeed; |
1699 | VerNeed.vn_version = VE.Version; |
1700 | VerNeed.vn_file = DotDynstr.getOffset(S: VE.File); |
1701 | if (I == Section.VerneedV->size() - 1) |
1702 | VerNeed.vn_next = 0; |
1703 | else |
1704 | VerNeed.vn_next = |
1705 | sizeof(Elf_Verneed) + VE.AuxV.size() * sizeof(Elf_Vernaux); |
1706 | VerNeed.vn_cnt = VE.AuxV.size(); |
1707 | VerNeed.vn_aux = sizeof(Elf_Verneed); |
1708 | CBA.write(Ptr: (const char *)&VerNeed, Size: sizeof(Elf_Verneed)); |
1709 | |
1710 | for (size_t J = 0; J < VE.AuxV.size(); ++J, ++AuxCnt) { |
1711 | const ELFYAML::VernauxEntry &VAuxE = VE.AuxV[J]; |
1712 | |
1713 | Elf_Vernaux VernAux; |
1714 | VernAux.vna_hash = VAuxE.Hash; |
1715 | VernAux.vna_flags = VAuxE.Flags; |
1716 | VernAux.vna_other = VAuxE.Other; |
1717 | VernAux.vna_name = DotDynstr.getOffset(S: VAuxE.Name); |
1718 | if (J == VE.AuxV.size() - 1) |
1719 | VernAux.vna_next = 0; |
1720 | else |
1721 | VernAux.vna_next = sizeof(Elf_Vernaux); |
1722 | CBA.write(Ptr: (const char *)&VernAux, Size: sizeof(Elf_Vernaux)); |
1723 | } |
1724 | } |
1725 | |
1726 | SHeader.sh_size = Section.VerneedV->size() * sizeof(Elf_Verneed) + |
1727 | AuxCnt * sizeof(Elf_Vernaux); |
1728 | } |
1729 | |
1730 | template <class ELFT> |
1731 | void ELFState<ELFT>::writeSectionContent( |
1732 | Elf_Shdr &, const ELFYAML::ARMIndexTableSection &Section, |
1733 | ContiguousBlobAccumulator &CBA) { |
1734 | if (!Section.Entries) |
1735 | return; |
1736 | |
1737 | for (const ELFYAML::ARMIndexTableEntry &E : *Section.Entries) { |
1738 | CBA.write<uint32_t>(E.Offset, ELFT::Endianness); |
1739 | CBA.write<uint32_t>(E.Value, ELFT::Endianness); |
1740 | } |
1741 | SHeader.sh_size = Section.Entries->size() * 8; |
1742 | } |
1743 | |
1744 | template <class ELFT> |
1745 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1746 | const ELFYAML::MipsABIFlags &Section, |
1747 | ContiguousBlobAccumulator &CBA) { |
1748 | assert(Section.Type == llvm::ELF::SHT_MIPS_ABIFLAGS && |
1749 | "Section type is not SHT_MIPS_ABIFLAGS" ); |
1750 | |
1751 | object::Elf_Mips_ABIFlags<ELFT> Flags; |
1752 | zero(Flags); |
1753 | SHeader.sh_size = SHeader.sh_entsize; |
1754 | |
1755 | Flags.version = Section.Version; |
1756 | Flags.isa_level = Section.ISALevel; |
1757 | Flags.isa_rev = Section.ISARevision; |
1758 | Flags.gpr_size = Section.GPRSize; |
1759 | Flags.cpr1_size = Section.CPR1Size; |
1760 | Flags.cpr2_size = Section.CPR2Size; |
1761 | Flags.fp_abi = Section.FpABI; |
1762 | Flags.isa_ext = Section.ISAExtension; |
1763 | Flags.ases = Section.ASEs; |
1764 | Flags.flags1 = Section.Flags1; |
1765 | Flags.flags2 = Section.Flags2; |
1766 | CBA.write(Ptr: (const char *)&Flags, Size: sizeof(Flags)); |
1767 | } |
1768 | |
1769 | template <class ELFT> |
1770 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1771 | const ELFYAML::DynamicSection &Section, |
1772 | ContiguousBlobAccumulator &CBA) { |
1773 | assert(Section.Type == llvm::ELF::SHT_DYNAMIC && |
1774 | "Section type is not SHT_DYNAMIC" ); |
1775 | |
1776 | if (!Section.Entries) |
1777 | return; |
1778 | |
1779 | for (const ELFYAML::DynamicEntry &DE : *Section.Entries) { |
1780 | CBA.write<uintX_t>(DE.Tag, ELFT::Endianness); |
1781 | CBA.write<uintX_t>(DE.Val, ELFT::Endianness); |
1782 | } |
1783 | SHeader.sh_size = 2 * sizeof(uintX_t) * Section.Entries->size(); |
1784 | } |
1785 | |
1786 | template <class ELFT> |
1787 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1788 | const ELFYAML::AddrsigSection &Section, |
1789 | ContiguousBlobAccumulator &CBA) { |
1790 | if (!Section.Symbols) |
1791 | return; |
1792 | |
1793 | for (StringRef Sym : *Section.Symbols) |
1794 | SHeader.sh_size += |
1795 | CBA.writeULEB128(Val: toSymbolIndex(S: Sym, LocSec: Section.Name, /*IsDynamic=*/false)); |
1796 | } |
1797 | |
1798 | template <class ELFT> |
1799 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1800 | const ELFYAML::NoteSection &Section, |
1801 | ContiguousBlobAccumulator &CBA) { |
1802 | if (!Section.Notes) |
1803 | return; |
1804 | |
1805 | uint64_t Offset = CBA.tell(); |
1806 | for (const ELFYAML::NoteEntry &NE : *Section.Notes) { |
1807 | // Write name size. |
1808 | if (NE.Name.empty()) |
1809 | CBA.write<uint32_t>(0, ELFT::Endianness); |
1810 | else |
1811 | CBA.write<uint32_t>(NE.Name.size() + 1, ELFT::Endianness); |
1812 | |
1813 | // Write description size. |
1814 | if (NE.Desc.binary_size() == 0) |
1815 | CBA.write<uint32_t>(0, ELFT::Endianness); |
1816 | else |
1817 | CBA.write<uint32_t>(NE.Desc.binary_size(), ELFT::Endianness); |
1818 | |
1819 | // Write type. |
1820 | CBA.write<uint32_t>(NE.Type, ELFT::Endianness); |
1821 | |
1822 | // Write name, null terminator and padding. |
1823 | if (!NE.Name.empty()) { |
1824 | CBA.write(Ptr: NE.Name.data(), Size: NE.Name.size()); |
1825 | CBA.write(C: '\0'); |
1826 | CBA.padToAlignment(Align: 4); |
1827 | } |
1828 | |
1829 | // Write description and padding. |
1830 | if (NE.Desc.binary_size() != 0) { |
1831 | CBA.writeAsBinary(Bin: NE.Desc); |
1832 | CBA.padToAlignment(Align: 4); |
1833 | } |
1834 | } |
1835 | |
1836 | SHeader.sh_size = CBA.tell() - Offset; |
1837 | } |
1838 | |
1839 | template <class ELFT> |
1840 | void ELFState<ELFT>::writeSectionContent(Elf_Shdr &, |
1841 | const ELFYAML::GnuHashSection &Section, |
1842 | ContiguousBlobAccumulator &CBA) { |
1843 | if (!Section.HashBuckets) |
1844 | return; |
1845 | |
1846 | if (!Section.Header) |
1847 | return; |
1848 | |
1849 | // We write the header first, starting with the hash buckets count. Normally |
1850 | // it is the number of entries in HashBuckets, but the "NBuckets" property can |
1851 | // be used to override this field, which is useful for producing broken |
1852 | // objects. |
1853 | if (Section.Header->NBuckets) |
1854 | CBA.write<uint32_t>(*Section.Header->NBuckets, ELFT::Endianness); |
1855 | else |
1856 | CBA.write<uint32_t>(Section.HashBuckets->size(), ELFT::Endianness); |
1857 | |
1858 | // Write the index of the first symbol in the dynamic symbol table accessible |
1859 | // via the hash table. |
1860 | CBA.write<uint32_t>(Section.Header->SymNdx, ELFT::Endianness); |
1861 | |
1862 | // Write the number of words in the Bloom filter. As above, the "MaskWords" |
1863 | // property can be used to set this field to any value. |
1864 | if (Section.Header->MaskWords) |
1865 | CBA.write<uint32_t>(*Section.Header->MaskWords, ELFT::Endianness); |
1866 | else |
1867 | CBA.write<uint32_t>(Section.BloomFilter->size(), ELFT::Endianness); |
1868 | |
1869 | // Write the shift constant used by the Bloom filter. |
1870 | CBA.write<uint32_t>(Section.Header->Shift2, ELFT::Endianness); |
1871 | |
1872 | // We've finished writing the header. Now write the Bloom filter. |
1873 | for (llvm::yaml::Hex64 Val : *Section.BloomFilter) |
1874 | CBA.write<uintX_t>(Val, ELFT::Endianness); |
1875 | |
1876 | // Write an array of hash buckets. |
1877 | for (llvm::yaml::Hex32 Val : *Section.HashBuckets) |
1878 | CBA.write<uint32_t>(Val, ELFT::Endianness); |
1879 | |
1880 | // Write an array of hash values. |
1881 | for (llvm::yaml::Hex32 Val : *Section.HashValues) |
1882 | CBA.write<uint32_t>(Val, ELFT::Endianness); |
1883 | |
1884 | SHeader.sh_size = 16 /*Header size*/ + |
1885 | Section.BloomFilter->size() * sizeof(typename ELFT::uint) + |
1886 | Section.HashBuckets->size() * 4 + |
1887 | Section.HashValues->size() * 4; |
1888 | } |
1889 | |
1890 | template <class ELFT> |
1891 | void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill, |
1892 | ContiguousBlobAccumulator &CBA) { |
1893 | size_t PatternSize = Fill.Pattern ? Fill.Pattern->binary_size() : 0; |
1894 | if (!PatternSize) { |
1895 | CBA.writeZeros(Num: Fill.Size); |
1896 | return; |
1897 | } |
1898 | |
1899 | // Fill the content with the specified pattern. |
1900 | uint64_t Written = 0; |
1901 | for (; Written + PatternSize <= Fill.Size; Written += PatternSize) |
1902 | CBA.writeAsBinary(Bin: *Fill.Pattern); |
1903 | CBA.writeAsBinary(Bin: *Fill.Pattern, N: Fill.Size - Written); |
1904 | } |
1905 | |
1906 | template <class ELFT> |
1907 | DenseMap<StringRef, size_t> ELFState<ELFT>::() { |
1908 | const ELFYAML::SectionHeaderTable & = |
1909 | Doc.getSectionHeaderTable(); |
1910 | if (SectionHeaders.IsImplicit || SectionHeaders.NoHeaders || |
1911 | SectionHeaders.isDefault()) |
1912 | return DenseMap<StringRef, size_t>(); |
1913 | |
1914 | DenseMap<StringRef, size_t> Ret; |
1915 | size_t SecNdx = 0; |
1916 | StringSet<> Seen; |
1917 | |
1918 | auto AddSection = [&](const ELFYAML::SectionHeader &Hdr) { |
1919 | if (!Ret.try_emplace(Key: Hdr.Name, Args&: ++SecNdx).second) |
1920 | reportError("repeated section name: '" + Hdr.Name + |
1921 | "' in the section header description" ); |
1922 | Seen.insert(key: Hdr.Name); |
1923 | }; |
1924 | |
1925 | if (SectionHeaders.Sections) |
1926 | for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Sections) |
1927 | AddSection(Hdr); |
1928 | |
1929 | if (SectionHeaders.Excluded) |
1930 | for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded) |
1931 | AddSection(Hdr); |
1932 | |
1933 | for (const ELFYAML::Section *S : Doc.getSections()) { |
1934 | // Ignore special first SHT_NULL section. |
1935 | if (S == Doc.getSections().front()) |
1936 | continue; |
1937 | if (!Seen.count(Key: S->Name)) |
1938 | reportError("section '" + S->Name + |
1939 | "' should be present in the 'Sections' or 'Excluded' lists" ); |
1940 | Seen.erase(Key: S->Name); |
1941 | } |
1942 | |
1943 | for (const auto &It : Seen) |
1944 | reportError("section header contains undefined section '" + It.getKey() + |
1945 | "'" ); |
1946 | return Ret; |
1947 | } |
1948 | |
1949 | template <class ELFT> void ELFState<ELFT>::buildSectionIndex() { |
1950 | // A YAML description can have an explicit section header declaration that |
1951 | // allows to change the order of section headers. |
1952 | DenseMap<StringRef, size_t> ReorderMap = buildSectionHeaderReorderMap(); |
1953 | |
1954 | if (HasError) |
1955 | return; |
1956 | |
1957 | // Build excluded section headers map. |
1958 | std::vector<ELFYAML::Section *> Sections = Doc.getSections(); |
1959 | const ELFYAML::SectionHeaderTable & = |
1960 | Doc.getSectionHeaderTable(); |
1961 | if (SectionHeaders.Excluded) |
1962 | for (const ELFYAML::SectionHeader &Hdr : *SectionHeaders.Excluded) |
1963 | if (!ExcludedSectionHeaders.insert(key: Hdr.Name).second) |
1964 | llvm_unreachable("buildSectionIndex() failed" ); |
1965 | |
1966 | if (SectionHeaders.NoHeaders.value_or(u: false)) |
1967 | for (const ELFYAML::Section *S : Sections) |
1968 | if (!ExcludedSectionHeaders.insert(key: S->Name).second) |
1969 | llvm_unreachable("buildSectionIndex() failed" ); |
1970 | |
1971 | size_t SecNdx = -1; |
1972 | for (const ELFYAML::Section *S : Sections) { |
1973 | ++SecNdx; |
1974 | |
1975 | size_t Index = ReorderMap.empty() ? SecNdx : ReorderMap.lookup(Val: S->Name); |
1976 | if (!SN2I.addName(Name: S->Name, Ndx: Index)) |
1977 | llvm_unreachable("buildSectionIndex() failed" ); |
1978 | |
1979 | if (!ExcludedSectionHeaders.count(Key: S->Name)) |
1980 | ShStrtabStrings->add(S: ELFYAML::dropUniqueSuffix(S: S->Name)); |
1981 | } |
1982 | } |
1983 | |
1984 | template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() { |
1985 | auto Build = [this](ArrayRef<ELFYAML::Symbol> V, NameToIdxMap &Map) { |
1986 | for (size_t I = 0, S = V.size(); I < S; ++I) { |
1987 | const ELFYAML::Symbol &Sym = V[I]; |
1988 | if (!Sym.Name.empty() && !Map.addName(Name: Sym.Name, Ndx: I + 1)) |
1989 | reportError("repeated symbol name: '" + Sym.Name + "'" ); |
1990 | } |
1991 | }; |
1992 | |
1993 | if (Doc.Symbols) |
1994 | Build(*Doc.Symbols, SymN2I); |
1995 | if (Doc.DynamicSymbols) |
1996 | Build(*Doc.DynamicSymbols, DynSymN2I); |
1997 | } |
1998 | |
1999 | template <class ELFT> void ELFState<ELFT>::finalizeStrings() { |
2000 | // Add the regular symbol names to .strtab section. |
2001 | if (Doc.Symbols) |
2002 | for (const ELFYAML::Symbol &Sym : *Doc.Symbols) |
2003 | DotStrtab.add(S: ELFYAML::dropUniqueSuffix(S: Sym.Name)); |
2004 | DotStrtab.finalize(); |
2005 | |
2006 | // Add the dynamic symbol names to .dynstr section. |
2007 | if (Doc.DynamicSymbols) |
2008 | for (const ELFYAML::Symbol &Sym : *Doc.DynamicSymbols) |
2009 | DotDynstr.add(S: ELFYAML::dropUniqueSuffix(S: Sym.Name)); |
2010 | |
2011 | // SHT_GNU_verdef and SHT_GNU_verneed sections might also |
2012 | // add strings to .dynstr section. |
2013 | for (const ELFYAML::Chunk *Sec : Doc.getSections()) { |
2014 | if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Val: Sec)) { |
2015 | if (VerNeed->VerneedV) { |
2016 | for (const ELFYAML::VerneedEntry &VE : *VerNeed->VerneedV) { |
2017 | DotDynstr.add(S: VE.File); |
2018 | for (const ELFYAML::VernauxEntry &Aux : VE.AuxV) |
2019 | DotDynstr.add(S: Aux.Name); |
2020 | } |
2021 | } |
2022 | } else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Val: Sec)) { |
2023 | if (VerDef->Entries) |
2024 | for (const ELFYAML::VerdefEntry &E : *VerDef->Entries) |
2025 | for (StringRef Name : E.VerNames) |
2026 | DotDynstr.add(S: Name); |
2027 | } |
2028 | } |
2029 | |
2030 | DotDynstr.finalize(); |
2031 | |
2032 | // Don't finalize the section header string table a second time if it has |
2033 | // already been finalized due to being one of the symbol string tables. |
2034 | if (ShStrtabStrings != &DotStrtab && ShStrtabStrings != &DotDynstr) |
2035 | ShStrtabStrings->finalize(); |
2036 | } |
2037 | |
2038 | template <class ELFT> |
2039 | bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc, |
2040 | yaml::ErrorHandler EH, uint64_t MaxSize) { |
2041 | ELFState<ELFT> State(Doc, EH); |
2042 | if (State.HasError) |
2043 | return false; |
2044 | |
2045 | // Build the section index, which adds sections to the section header string |
2046 | // table first, so that we can finalize the section header string table. |
2047 | State.buildSectionIndex(); |
2048 | State.buildSymbolIndexes(); |
2049 | |
2050 | // Finalize section header string table and the .strtab and .dynstr sections. |
2051 | // We do this early because we want to finalize the string table builders |
2052 | // before writing the content of the sections that might want to use them. |
2053 | State.finalizeStrings(); |
2054 | |
2055 | if (State.HasError) |
2056 | return false; |
2057 | |
2058 | std::vector<Elf_Phdr> ; |
2059 | State.initProgramHeaders(PHeaders); |
2060 | |
2061 | // XXX: This offset is tightly coupled with the order that we write |
2062 | // things to `OS`. |
2063 | const size_t SectionContentBeginOffset = |
2064 | sizeof(Elf_Ehdr) + sizeof(Elf_Phdr) * Doc.ProgramHeaders.size(); |
2065 | // It is quite easy to accidentally create output with yaml2obj that is larger |
2066 | // than intended, for example, due to an issue in the YAML description. |
2067 | // We limit the maximum allowed output size, but also provide a command line |
2068 | // option to change this limitation. |
2069 | ContiguousBlobAccumulator CBA(SectionContentBeginOffset, MaxSize); |
2070 | |
2071 | std::vector<Elf_Shdr> ; |
2072 | State.initSectionHeaders(SHeaders, CBA); |
2073 | |
2074 | // Now we can decide segment offsets. |
2075 | State.setProgramHeaderLayout(PHeaders, SHeaders); |
2076 | |
2077 | bool ReachedLimit = CBA.getOffset() > MaxSize; |
2078 | if (Error E = CBA.takeLimitError()) { |
2079 | // We report a custom error message instead below. |
2080 | consumeError(Err: std::move(E)); |
2081 | ReachedLimit = true; |
2082 | } |
2083 | |
2084 | if (ReachedLimit) |
2085 | State.reportError( |
2086 | "the desired output size is greater than permitted. Use the " |
2087 | "--max-size option to change the limit" ); |
2088 | |
2089 | if (State.HasError) |
2090 | return false; |
2091 | |
2092 | State.writeELFHeader(OS); |
2093 | writeArrayData(OS, ArrayRef(PHeaders)); |
2094 | |
2095 | const ELFYAML::SectionHeaderTable &SHT = Doc.getSectionHeaderTable(); |
2096 | if (!SHT.NoHeaders.value_or(u: false)) |
2097 | CBA.updateDataAt(Pos: *SHT.Offset, Data: SHeaders.data(), |
2098 | Size: SHT.getNumHeaders(SectionsNum: SHeaders.size()) * sizeof(Elf_Shdr)); |
2099 | |
2100 | CBA.writeBlobToStream(Out&: OS); |
2101 | return true; |
2102 | } |
2103 | |
2104 | namespace llvm { |
2105 | namespace yaml { |
2106 | |
2107 | bool yaml2elf(llvm::ELFYAML::Object &Doc, raw_ostream &Out, ErrorHandler EH, |
2108 | uint64_t MaxSize) { |
2109 | bool IsLE = Doc.Header.Data == ELFYAML::ELF_ELFDATA(ELF::ELFDATA2LSB); |
2110 | bool Is64Bit = Doc.Header.Class == ELFYAML::ELF_ELFCLASS(ELF::ELFCLASS64); |
2111 | if (Is64Bit) { |
2112 | if (IsLE) |
2113 | return ELFState<object::ELF64LE>::writeELF(OS&: Out, Doc, EH, MaxSize); |
2114 | return ELFState<object::ELF64BE>::writeELF(OS&: Out, Doc, EH, MaxSize); |
2115 | } |
2116 | if (IsLE) |
2117 | return ELFState<object::ELF32LE>::writeELF(OS&: Out, Doc, EH, MaxSize); |
2118 | return ELFState<object::ELF32BE>::writeELF(OS&: Out, Doc, EH, MaxSize); |
2119 | } |
2120 | |
2121 | } // namespace yaml |
2122 | } // namespace llvm |
2123 | |