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