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