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