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