diff options
Diffstat (limited to 'llvm/lib/ObjectYAML')
-rw-r--r-- | llvm/lib/ObjectYAML/COFFEmitter.cpp | 13 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp | 2 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/DWARFEmitter.cpp | 5 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/ELFEmitter.cpp | 559 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/ELFYAML.cpp | 254 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/MachOEmitter.cpp | 3 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/MinidumpYAML.cpp | 1 | ||||
-rw-r--r-- | llvm/lib/ObjectYAML/YAML.cpp | 12 |
8 files changed, 692 insertions, 157 deletions
diff --git a/llvm/lib/ObjectYAML/COFFEmitter.cpp b/llvm/lib/ObjectYAML/COFFEmitter.cpp index efcdc51e1670..ec3ec55011f9 100644 --- a/llvm/lib/ObjectYAML/COFFEmitter.cpp +++ b/llvm/lib/ObjectYAML/COFFEmitter.cpp @@ -260,9 +260,12 @@ static bool layoutCOFF(COFFParser &CP) { CurrentSectionDataOffset += S.Header.SizeOfRawData; if (!S.Relocations.empty()) { S.Header.PointerToRelocations = CurrentSectionDataOffset; - S.Header.NumberOfRelocations = S.Relocations.size(); - CurrentSectionDataOffset += - S.Header.NumberOfRelocations * COFF::RelocationSize; + if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) { + S.Header.NumberOfRelocations = 0xffff; + CurrentSectionDataOffset += COFF::RelocationSize; + } else + S.Header.NumberOfRelocations = S.Relocations.size(); + CurrentSectionDataOffset += S.Relocations.size() * COFF::RelocationSize; } } else { // Leave SizeOfRawData unaltered. For .bss sections in object files, it @@ -506,6 +509,10 @@ static bool writeCOFF(COFFParser &CP, raw_ostream &OS) { S.SectionData.writeAsBinary(OS); assert(S.Header.SizeOfRawData >= S.SectionData.binary_size()); OS.write_zeros(S.Header.SizeOfRawData - S.SectionData.binary_size()); + if (S.Header.Characteristics & COFF::IMAGE_SCN_LNK_NRELOC_OVFL) + OS << binary_le<uint32_t>(/*VirtualAddress=*/ S.Relocations.size() + 1) + << binary_le<uint32_t>(/*SymbolTableIndex=*/ 0) + << binary_le<uint16_t>(/*Type=*/ 0); for (const COFFYAML::Relocation &R : S.Relocations) { uint32_t SymbolTableIndex; if (R.SymbolTableIndex) { diff --git a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp index eeebb694589b..02f053bb0e0f 100644 --- a/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp +++ b/llvm/lib/ObjectYAML/CodeViewYAMLDebugSections.cpp @@ -421,7 +421,7 @@ std::shared_ptr<DebugSubsection> YAMLLinesSubsection::toCodeViewSubsection( for (const auto &LC : Lines.Blocks) { Result->createBlock(LC.FileName); if (Result->hasColumnInfo()) { - for (const auto &Item : zip(LC.Lines, LC.Columns)) { + for (auto Item : zip(LC.Lines, LC.Columns)) { auto &L = std::get<0>(Item); auto &C = std::get<1>(Item); uint32_t LE = L.LineStart + L.EndDelta; diff --git a/llvm/lib/ObjectYAML/DWARFEmitter.cpp b/llvm/lib/ObjectYAML/DWARFEmitter.cpp index 2ae66997cf59..b410fed16f09 100644 --- a/llvm/lib/ObjectYAML/DWARFEmitter.cpp +++ b/llvm/lib/ObjectYAML/DWARFEmitter.cpp @@ -314,7 +314,10 @@ public: DIEFixupVisitor(DWARFYAML::Data &DI) : DWARFYAML::Visitor(DI){}; private: - virtual void onStartCompileUnit(DWARFYAML::Unit &CU) { Length = 7; } + virtual void onStartCompileUnit(DWARFYAML::Unit &CU) { + // Size of the unit header, excluding the length field itself. + Length = CU.Version >= 5 ? 8 : 7; + } virtual void onEndCompileUnit(DWARFYAML::Unit &CU) { CU.Length.setLength(Length); diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp index e0faed256f6b..ee7d5f616a73 100644 --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -12,6 +12,7 @@ //===----------------------------------------------------------------------===// #include "llvm/ADT/ArrayRef.h" +#include "llvm/ADT/DenseMap.h" #include "llvm/ADT/StringSet.h" #include "llvm/BinaryFormat/ELF.h" #include "llvm/MC/StringTableBuilder.h" @@ -36,6 +37,16 @@ class ContiguousBlobAccumulator { SmallVector<char, 128> Buf; raw_svector_ostream OS; +public: + ContiguousBlobAccumulator(uint64_t InitialOffset_) + : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} + + template <class Integer> + raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { + Offset = padToAlignment(Align); + return OS; + } + /// \returns The new offset. uint64_t padToAlignment(unsigned Align) { if (Align == 0) @@ -46,14 +57,6 @@ class ContiguousBlobAccumulator { return AlignedOffset; // == CurrentOffset; } -public: - ContiguousBlobAccumulator(uint64_t InitialOffset_) - : InitialOffset(InitialOffset_), Buf(), OS(Buf) {} - template <class Integer> - raw_ostream &getOSAndAlignedOffset(Integer &Offset, unsigned Align) { - Offset = padToAlignment(Align); - return OS; - } void writeBlobToStream(raw_ostream &Out) { Out << OS.str(); } }; @@ -86,6 +89,15 @@ public: unsigned size() const { return Map.size(); } }; +namespace { +struct Fragment { + uint64_t Offset; + uint64_t Size; + uint32_t Type; + uint64_t AddrAlign; +}; +} // namespace + /// "Single point of truth" for the ELF file construction. /// TODO: This class still has a ways to go before it is truly a "single /// point of truth". @@ -98,6 +110,7 @@ template <class ELFT> class ELFState { typedef typename ELFT::Rela Elf_Rela; typedef typename ELFT::Relr Elf_Relr; typedef typename ELFT::Dyn Elf_Dyn; + typedef typename ELFT::uint uintX_t; enum class SymtabType { Static, Dynamic }; @@ -140,6 +153,11 @@ template <class ELFT> class ELFState { ELFYAML::Section *YAMLSec); void setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders, std::vector<Elf_Shdr> &SHeaders); + + std::vector<Fragment> + getPhdrFragments(const ELFYAML::ProgramHeader &Phdr, + ArrayRef<typename ELFT::Shdr> SHeaders); + void finalizeStrings(); void writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream &OS); void writeSectionContent(Elf_Shdr &SHeader, @@ -148,6 +166,9 @@ template <class ELFT> class ELFState { void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::RelocationSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RelrSection &Section, + ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::Group &Group, ContiguousBlobAccumulator &CBA); void writeSectionContent(Elf_Shdr &SHeader, @@ -177,6 +198,20 @@ template <class ELFT> class ELFState { void writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::AddrsigSection &Section, ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::NoteSection &Section, + ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::GnuHashSection &Section, + ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::LinkerOptionsSection &Section, + ContiguousBlobAccumulator &CBA); + void writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::DependentLibrariesSection &Section, + ContiguousBlobAccumulator &CBA); + + void writeFill(ELFYAML::Fill &Fill, ContiguousBlobAccumulator &CBA); ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH); @@ -199,31 +234,25 @@ template <class T> static void zero(T &Obj) { memset(&Obj, 0, sizeof(Obj)); } template <class ELFT> ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) : Doc(D), ErrHandler(EH) { + std::vector<ELFYAML::Section *> Sections = Doc.getSections(); StringSet<> DocSections; - for (std::unique_ptr<ELFYAML::Section> &D : Doc.Sections) { - if (!D->Name.empty()) - DocSections.insert(D->Name); - - // Some sections wants to link to .symtab by default. - // That means we want to create the symbol table for them. - if (D->Type == llvm::ELF::SHT_REL || D->Type == llvm::ELF::SHT_RELA) - if (!Doc.Symbols && D->Link.empty()) - Doc.Symbols.emplace(); - } + for (const ELFYAML::Section *Sec : Sections) + if (!Sec->Name.empty()) + DocSections.insert(Sec->Name); // Insert SHT_NULL section implicitly when it is not defined in YAML. - if (Doc.Sections.empty() || Doc.Sections.front()->Type != ELF::SHT_NULL) - Doc.Sections.insert( - Doc.Sections.begin(), + if (Sections.empty() || Sections.front()->Type != ELF::SHT_NULL) + Doc.Chunks.insert( + Doc.Chunks.begin(), std::make_unique<ELFYAML::Section>( - ELFYAML::Section::SectionKind::RawContent, /*IsImplicit=*/true)); + ELFYAML::Chunk::ChunkKind::RawContent, /*IsImplicit=*/true)); std::vector<StringRef> ImplicitSections; if (Doc.Symbols) ImplicitSections.push_back(".symtab"); ImplicitSections.insert(ImplicitSections.end(), {".strtab", ".shstrtab"}); - if (!Doc.DynamicSymbols.empty()) + if (Doc.DynamicSymbols) ImplicitSections.insert(ImplicitSections.end(), {".dynsym", ".dynstr"}); // Insert placeholders for implicit sections that are not @@ -232,10 +261,10 @@ ELFState<ELFT>::ELFState(ELFYAML::Object &D, yaml::ErrorHandler EH) if (DocSections.count(SecName)) continue; - std::unique_ptr<ELFYAML::Section> Sec = std::make_unique<ELFYAML::Section>( - ELFYAML::Section::SectionKind::RawContent, true /*IsImplicit*/); + std::unique_ptr<ELFYAML::Chunk> Sec = std::make_unique<ELFYAML::Section>( + ELFYAML::Chunk::ChunkKind::RawContent, true /*IsImplicit*/); Sec->Name = SecName; - Doc.Sections.push_back(std::move(Sec)); + Doc.Chunks.push_back(std::move(Sec)); } } @@ -273,7 +302,7 @@ void ELFState<ELFT>::writeELFHeader(ContiguousBlobAccumulator &CBA, raw_ostream Header.e_shoff = Doc.Header.SHOff ? typename ELFT::uint(*Doc.Header.SHOff) : SHOff; Header.e_shnum = - Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : Doc.Sections.size(); + Doc.Header.SHNum ? (uint16_t)*Doc.Header.SHNum : Doc.getSections().size(); Header.e_shstrndx = Doc.Header.SHStrNdx ? (uint16_t)*Doc.Header.SHStrNdx : SN2I.get(".shstrtab"); @@ -325,6 +354,20 @@ unsigned ELFState<ELFT>::toSymbolIndex(StringRef S, StringRef LocSec, } template <class ELFT> +static void overrideFields(ELFYAML::Section *From, typename ELFT::Shdr &To) { + if (!From) + return; + if (From->ShFlags) + To.sh_flags = *From->ShFlags; + if (From->ShName) + To.sh_name = *From->ShName; + if (From->ShOffset) + To.sh_offset = *From->ShOffset; + if (From->ShSize) + To.sh_size = *From->ShSize; +} + +template <class ELFT> bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header, StringRef SecName, ELFYAML::Section *YAMLSec) { @@ -345,16 +388,8 @@ bool ELFState<ELFT>::initImplicitHeader(ContiguousBlobAccumulator &CBA, else return false; - // Override the fields if requested. - if (YAMLSec) { - if (YAMLSec->ShName) - Header.sh_name = *YAMLSec->ShName; - if (YAMLSec->ShOffset) - Header.sh_offset = *YAMLSec->ShOffset; - if (YAMLSec->ShSize) - Header.sh_size = *YAMLSec->ShSize; - } - + // Override section fields if requested. + overrideFields<ELFT>(YAMLSec, Header); return true; } @@ -370,18 +405,25 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, ContiguousBlobAccumulator &CBA) { // Ensure SHN_UNDEF entry is present. An all-zero section header is a // valid SHN_UNDEF entry since SHT_NULL == 0. - SHeaders.resize(Doc.Sections.size()); + SHeaders.resize(Doc.getSections().size()); + + size_t SecNdx = -1; + for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) { + if (auto S = dyn_cast<ELFYAML::Fill>(D.get())) { + writeFill(*S, CBA); + continue; + } - for (size_t I = 0; I < Doc.Sections.size(); ++I) { - ELFYAML::Section *Sec = Doc.Sections[I].get(); - if (I == 0 && Sec->IsImplicit) + ++SecNdx; + ELFYAML::Section *Sec = cast<ELFYAML::Section>(D.get()); + if (SecNdx == 0 && Sec->IsImplicit) continue; // We have a few sections like string or symbol tables that are usually // added implicitly to the end. However, if they are explicitly specified // in the YAML, we need to write them here. This ensures the file offset // remains correct. - Elf_Shdr &SHeader = SHeaders[I]; + Elf_Shdr &SHeader = SHeaders[SecNdx]; if (initImplicitHeader(CBA, SHeader, Sec->Name, Sec->IsImplicit ? nullptr : Sec)) continue; @@ -400,7 +442,7 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, if (!Sec->Link.empty()) SHeader.sh_link = toSectionIndex(Sec->Link, Sec->Name); - if (I == 0) { + if (SecNdx == 0) { if (auto RawSec = dyn_cast<ELFYAML::RawContentSection>(Sec)) { // We do not write any content for special SHN_UNDEF section. if (RawSec->Size) @@ -416,6 +458,8 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::RelocationSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::RelrSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::Group>(Sec)) { writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::MipsABIFlags>(Sec)) { @@ -440,19 +484,20 @@ void ELFState<ELFT>::initSectionHeaders(std::vector<Elf_Shdr> &SHeaders, writeSectionContent(SHeader, *S, CBA); } else if (auto S = dyn_cast<ELFYAML::AddrsigSection>(Sec)) { writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::LinkerOptionsSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::NoteSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::GnuHashSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); + } else if (auto S = dyn_cast<ELFYAML::DependentLibrariesSection>(Sec)) { + writeSectionContent(SHeader, *S, CBA); } else { llvm_unreachable("Unknown section type"); } - // Override the fields if requested. - if (Sec) { - if (Sec->ShName) - SHeader.sh_name = *Sec->ShName; - if (Sec->ShOffset) - SHeader.sh_offset = *Sec->ShOffset; - if (Sec->ShSize) - SHeader.sh_size = *Sec->ShSize; - } + // Override section fields if requested. + overrideFields<ELFT>(Sec, SHeader); } } @@ -487,7 +532,7 @@ ELFState<ELFT>::toELFSymbols(ArrayRef<ELFYAML::Symbol> Symbols, Ret.resize(Symbols.size() + 1); size_t I = 0; - for (const auto &Sym : Symbols) { + for (const ELFYAML::Symbol &Sym : Symbols) { Elf_Sym &Symbol = Ret[++I]; // If NameIndex, which contains the name offset, is explicitly specified, we @@ -522,21 +567,24 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, ArrayRef<ELFYAML::Symbol> Symbols; if (IsStatic && Doc.Symbols) Symbols = *Doc.Symbols; - else if (!IsStatic) - Symbols = Doc.DynamicSymbols; + else if (!IsStatic && Doc.DynamicSymbols) + Symbols = *Doc.DynamicSymbols; ELFYAML::RawContentSection *RawSec = dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec); - if (RawSec && !Symbols.empty() && (RawSec->Content || RawSec->Size)) { - if (RawSec->Content) - reportError("cannot specify both `Content` and " + - (IsStatic ? Twine("`Symbols`") : Twine("`DynamicSymbols`")) + - " for symbol table section '" + RawSec->Name + "'"); - if (RawSec->Size) - reportError("cannot specify both `Size` and " + - (IsStatic ? Twine("`Symbols`") : Twine("`DynamicSymbols`")) + - " for symbol table section '" + RawSec->Name + "'"); - return; + if (RawSec && (RawSec->Content || RawSec->Size)) { + bool HasSymbolsDescription = + (IsStatic && Doc.Symbols) || (!IsStatic && Doc.DynamicSymbols); + if (HasSymbolsDescription) { + StringRef Property = (IsStatic ? "`Symbols`" : "`DynamicSymbols`"); + if (RawSec->Content) + reportError("cannot specify both `Content` and " + Property + + " for symbol table section '" + RawSec->Name + "'"); + if (RawSec->Size) + reportError("cannot specify both `Size` and " + Property + + " for symbol table section '" + RawSec->Name + "'"); + return; + } } zero(SHeader); @@ -636,22 +684,43 @@ template <class ELFT> void ELFState<ELFT>::reportError(const Twine &Msg) { } template <class ELFT> +std::vector<Fragment> +ELFState<ELFT>::getPhdrFragments(const ELFYAML::ProgramHeader &Phdr, + ArrayRef<typename ELFT::Shdr> SHeaders) { + DenseMap<StringRef, ELFYAML::Fill *> NameToFill; + for (const std::unique_ptr<ELFYAML::Chunk> &D : Doc.Chunks) + if (auto S = dyn_cast<ELFYAML::Fill>(D.get())) + NameToFill[S->Name] = S; + + std::vector<Fragment> Ret; + for (const ELFYAML::SectionName &SecName : Phdr.Sections) { + unsigned Index; + if (SN2I.lookup(SecName.Section, Index)) { + const typename ELFT::Shdr &H = SHeaders[Index]; + Ret.push_back({H.sh_offset, H.sh_size, H.sh_type, H.sh_addralign}); + continue; + } + + if (ELFYAML::Fill *Fill = NameToFill.lookup(SecName.Section)) { + Ret.push_back({Fill->ShOffset, Fill->Size, llvm::ELF::SHT_PROGBITS, + /*ShAddrAlign=*/1}); + continue; + } + + reportError("unknown section or fill referenced: '" + SecName.Section + + "' by program header"); + } + + return Ret; +} + +template <class ELFT> void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders, std::vector<Elf_Shdr> &SHeaders) { uint32_t PhdrIdx = 0; for (auto &YamlPhdr : Doc.ProgramHeaders) { Elf_Phdr &PHeader = PHeaders[PhdrIdx++]; - - std::vector<Elf_Shdr *> Sections; - for (const ELFYAML::SectionName &SecName : YamlPhdr.Sections) { - unsigned Index; - if (!SN2I.lookup(SecName.Section, Index)) { - reportError("unknown section referenced: '" + SecName.Section + - "' by program header"); - continue; - } - Sections.push_back(&SHeaders[Index]); - } + std::vector<Fragment> Fragments = getPhdrFragments(YamlPhdr, SHeaders); if (YamlPhdr.Offset) { PHeader.p_offset = *YamlPhdr.Offset; @@ -662,19 +731,19 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders, PHeader.p_offset = 0; // Find the minimum offset for the program header. - for (Elf_Shdr *SHeader : Sections) - PHeader.p_offset = std::min(PHeader.p_offset, SHeader->sh_offset); + for (const Fragment &F : Fragments) + PHeader.p_offset = std::min((uint64_t)PHeader.p_offset, F.Offset); } // Find the maximum offset of the end of a section in order to set p_filesz // and p_memsz. When setting p_filesz, trailing SHT_NOBITS sections are not // counted. uint64_t FileOffset = PHeader.p_offset, MemOffset = PHeader.p_offset; - for (Elf_Shdr *SHeader : Sections) { - uint64_t End = SHeader->sh_offset + SHeader->sh_size; + for (const Fragment &F : Fragments) { + uint64_t End = F.Offset + F.Size; MemOffset = std::max(MemOffset, End); - if (SHeader->sh_type != llvm::ELF::SHT_NOBITS) + if (F.Type != llvm::ELF::SHT_NOBITS) FileOffset = std::max(FileOffset, End); } @@ -691,8 +760,8 @@ void ELFState<ELFT>::setProgramHeaderLayout(std::vector<Elf_Phdr> &PHeaders, // sections so that by default the segment has a valid and sensible // alignment. PHeader.p_align = 1; - for (Elf_Shdr *SHeader : Sections) - PHeader.p_align = std::max(PHeader.p_align, SHeader->sh_addralign); + for (const Fragment &F : Fragments) + PHeader.p_align = std::max((uint64_t)PHeader.p_align, F.AddrAlign); } } } @@ -707,10 +776,6 @@ void ELFState<ELFT>::writeSectionContent( if (Section.EntSize) SHeader.sh_entsize = *Section.EntSize; - else if (Section.Type == llvm::ELF::SHT_RELR) - SHeader.sh_entsize = sizeof(Elf_Relr); - else - SHeader.sh_entsize = 0; if (Section.Info) SHeader.sh_info = *Section.Info; @@ -735,8 +800,9 @@ void ELFState<ELFT>::writeSectionContent( SHeader.sh_size = SHeader.sh_entsize * Section.Relocations.size(); // For relocation section set link to .symtab by default. - if (Section.Link.empty()) - SHeader.sh_link = SN2I.get(".symtab"); + unsigned Link = 0; + if (Section.Link.empty() && SN2I.lookup(".symtab", Link)) + SHeader.sh_link = Link; if (!Section.RelocatableSec.empty()) SHeader.sh_info = toSectionIndex(Section.RelocatableSec, Section.Name); @@ -764,6 +830,33 @@ void ELFState<ELFT>::writeSectionContent( } template <class ELFT> +void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::RelrSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + SHeader.sh_entsize = + Section.EntSize ? uint64_t(*Section.EntSize) : sizeof(Elf_Relr); + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.Entries) + return; + + for (llvm::yaml::Hex64 E : *Section.Entries) { + if (!ELFT::Is64Bits && E > UINT32_MAX) + reportError(Section.Name + ": the value is too large for 32-bits: 0x" + + Twine::utohexstr(E)); + support::endian::write<uintX_t>(OS, E, ELFT::TargetEndianness); + } + + SHeader.sh_size = sizeof(uintX_t) * Section.Entries->size(); +} + +template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::SymtabShndxSection &Shndx, ContiguousBlobAccumulator &CBA) { @@ -784,10 +877,16 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, assert(Section.Type == llvm::ELF::SHT_GROUP && "Section type is not SHT_GROUP"); + unsigned Link = 0; + if (Section.Link.empty() && SN2I.lookup(".symtab", Link)) + SHeader.sh_link = Link; + SHeader.sh_entsize = 4; SHeader.sh_size = SHeader.sh_entsize * Section.Members.size(); - SHeader.sh_info = - toSymbolIndex(Section.Signature, Section.Name, /*IsDynamic=*/false); + + if (Section.Signature) + SHeader.sh_info = + toSymbolIndex(*Section.Signature, Section.Name, /*IsDynamic=*/false); raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); @@ -819,7 +918,6 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::StackSizesSection &Section, ContiguousBlobAccumulator &CBA) { - using uintX_t = typename ELFT::uint; raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); @@ -835,6 +933,52 @@ void ELFState<ELFT>::writeSectionContent( } template <class ELFT> +void ELFState<ELFT>::writeSectionContent( + Elf_Shdr &SHeader, const ELFYAML::LinkerOptionsSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.Options) + return; + + for (const ELFYAML::LinkerOption &LO : *Section.Options) { + OS.write(LO.Key.data(), LO.Key.size()); + OS.write('\0'); + OS.write(LO.Value.data(), LO.Value.size()); + OS.write('\0'); + SHeader.sh_size += (LO.Key.size() + LO.Value.size() + 2); + } +} + +template <class ELFT> +void ELFState<ELFT>::writeSectionContent( + Elf_Shdr &SHeader, const ELFYAML::DependentLibrariesSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.Libs) + return; + + for (StringRef Lib : *Section.Libs) { + OS.write(Lib.data(), Lib.size()); + OS.write('\0'); + SHeader.sh_size += Lib.size() + 1; + } +} + +template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::HashSection &Section, ContiguousBlobAccumulator &CBA) { @@ -871,9 +1015,19 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + SHeader.sh_info = Section.Info; + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.Entries) + return; + uint64_t AuxCnt = 0; - for (size_t I = 0; I < Section.Entries.size(); ++I) { - const ELFYAML::VerdefEntry &E = Section.Entries[I]; + for (size_t I = 0; I < Section.Entries->size(); ++I) { + const ELFYAML::VerdefEntry &E = (*Section.Entries)[I]; Elf_Verdef VerDef; VerDef.vd_version = E.Version; @@ -882,7 +1036,7 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, VerDef.vd_hash = E.Hash; VerDef.vd_aux = sizeof(Elf_Verdef); VerDef.vd_cnt = E.VerNames.size(); - if (I == Section.Entries.size() - 1) + if (I == Section.Entries->size() - 1) VerDef.vd_next = 0; else VerDef.vd_next = @@ -900,9 +1054,8 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, } } - SHeader.sh_size = Section.Entries.size() * sizeof(Elf_Verdef) + + SHeader.sh_size = Section.Entries->size() * sizeof(Elf_Verdef) + AuxCnt * sizeof(Elf_Verdaux); - SHeader.sh_info = Section.Info; } template <class ELFT> @@ -913,15 +1066,24 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, typedef typename ELFT::Vernaux Elf_Vernaux; auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + SHeader.sh_info = Section.Info; + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + if (!Section.VerneedV) + return; uint64_t AuxCnt = 0; - for (size_t I = 0; I < Section.VerneedV.size(); ++I) { - const ELFYAML::VerneedEntry &VE = Section.VerneedV[I]; + for (size_t I = 0; I < Section.VerneedV->size(); ++I) { + const ELFYAML::VerneedEntry &VE = (*Section.VerneedV)[I]; Elf_Verneed VerNeed; VerNeed.vn_version = VE.Version; VerNeed.vn_file = DotDynstr.getOffset(VE.File); - if (I == Section.VerneedV.size() - 1) + if (I == Section.VerneedV->size() - 1) VerNeed.vn_next = 0; else VerNeed.vn_next = @@ -946,9 +1108,8 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, } } - SHeader.sh_size = Section.VerneedV.size() * sizeof(Elf_Verneed) + + SHeader.sh_size = Section.VerneedV->size() * sizeof(Elf_Verneed) + AuxCnt * sizeof(Elf_Vernaux); - SHeader.sh_info = Section.Info; } template <class ELFT> @@ -982,8 +1143,6 @@ template <class ELFT> void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, const ELFYAML::DynamicSection &Section, ContiguousBlobAccumulator &CBA) { - typedef typename ELFT::uint uintX_t; - assert(Section.Type == llvm::ELF::SHT_DYNAMIC && "Section type is not SHT_DYNAMIC"); @@ -1035,16 +1194,158 @@ void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, } } +template <class ELFT> +void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::NoteSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + uint64_t Offset = OS.tell(); + + if (Section.Content || Section.Size) { + SHeader.sh_size = writeContent(OS, Section.Content, Section.Size); + return; + } + + for (const ELFYAML::NoteEntry &NE : *Section.Notes) { + // Write name size. + if (NE.Name.empty()) + support::endian::write<uint32_t>(OS, 0, ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, NE.Name.size() + 1, + ELFT::TargetEndianness); + + // Write description size. + if (NE.Desc.binary_size() == 0) + support::endian::write<uint32_t>(OS, 0, ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, NE.Desc.binary_size(), + ELFT::TargetEndianness); + + // Write type. + support::endian::write<uint32_t>(OS, NE.Type, ELFT::TargetEndianness); + + // Write name, null terminator and padding. + if (!NE.Name.empty()) { + support::endian::write<uint8_t>(OS, arrayRefFromStringRef(NE.Name), + ELFT::TargetEndianness); + support::endian::write<uint8_t>(OS, 0, ELFT::TargetEndianness); + CBA.padToAlignment(4); + } + + // Write description and padding. + if (NE.Desc.binary_size() != 0) { + NE.Desc.writeAsBinary(OS); + CBA.padToAlignment(4); + } + } + + SHeader.sh_size = OS.tell() - Offset; +} + +template <class ELFT> +void ELFState<ELFT>::writeSectionContent(Elf_Shdr &SHeader, + const ELFYAML::GnuHashSection &Section, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = + CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + + unsigned Link = 0; + if (Section.Link.empty() && SN2I.lookup(".dynsym", Link)) + SHeader.sh_link = Link; + + if (Section.Content) { + SHeader.sh_size = writeContent(OS, Section.Content, None); + return; + } + + // We write the header first, starting with the hash buckets count. Normally + // it is the number of entries in HashBuckets, but the "NBuckets" property can + // be used to override this field, which is useful for producing broken + // objects. + if (Section.Header->NBuckets) + support::endian::write<uint32_t>(OS, *Section.Header->NBuckets, + ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, Section.HashBuckets->size(), + ELFT::TargetEndianness); + + // Write the index of the first symbol in the dynamic symbol table accessible + // via the hash table. + support::endian::write<uint32_t>(OS, Section.Header->SymNdx, + ELFT::TargetEndianness); + + // Write the number of words in the Bloom filter. As above, the "MaskWords" + // property can be used to set this field to any value. + if (Section.Header->MaskWords) + support::endian::write<uint32_t>(OS, *Section.Header->MaskWords, + ELFT::TargetEndianness); + else + support::endian::write<uint32_t>(OS, Section.BloomFilter->size(), + ELFT::TargetEndianness); + + // Write the shift constant used by the Bloom filter. + support::endian::write<uint32_t>(OS, Section.Header->Shift2, + ELFT::TargetEndianness); + + // We've finished writing the header. Now write the Bloom filter. + for (llvm::yaml::Hex64 Val : *Section.BloomFilter) + support::endian::write<typename ELFT::uint>(OS, Val, + ELFT::TargetEndianness); + + // Write an array of hash buckets. + for (llvm::yaml::Hex32 Val : *Section.HashBuckets) + support::endian::write<uint32_t>(OS, Val, ELFT::TargetEndianness); + + // Write an array of hash values. + for (llvm::yaml::Hex32 Val : *Section.HashValues) + support::endian::write<uint32_t>(OS, Val, ELFT::TargetEndianness); + + SHeader.sh_size = 16 /*Header size*/ + + Section.BloomFilter->size() * sizeof(typename ELFT::uint) + + Section.HashBuckets->size() * 4 + + Section.HashValues->size() * 4; +} + +template <class ELFT> +void ELFState<ELFT>::writeFill(ELFYAML::Fill &Fill, + ContiguousBlobAccumulator &CBA) { + raw_ostream &OS = CBA.getOSAndAlignedOffset(Fill.ShOffset, /*Align=*/1); + + size_t PatternSize = Fill.Pattern ? Fill.Pattern->binary_size() : 0; + if (!PatternSize) { + OS.write_zeros(Fill.Size); + return; + } + + // Fill the content with the specified pattern. + uint64_t Written = 0; + for (; Written + PatternSize <= Fill.Size; Written += PatternSize) + Fill.Pattern->writeAsBinary(OS); + Fill.Pattern->writeAsBinary(OS, Fill.Size - Written); +} + template <class ELFT> void ELFState<ELFT>::buildSectionIndex() { - for (unsigned I = 0, E = Doc.Sections.size(); I != E; ++I) { - StringRef Name = Doc.Sections[I]->Name; - if (Name.empty()) + size_t SecNdx = -1; + StringSet<> Seen; + for (size_t I = 0; I < Doc.Chunks.size(); ++I) { + const std::unique_ptr<ELFYAML::Chunk> &C = Doc.Chunks[I]; + bool IsSection = isa<ELFYAML::Section>(C.get()); + if (IsSection) + ++SecNdx; + + if (C->Name.empty()) + continue; + + if (!Seen.insert(C->Name).second) + reportError("repeated section/fill name: '" + C->Name + + "' at YAML section/fill number " + Twine(I)); + if (!IsSection || HasError) continue; - DotShStrtab.add(ELFYAML::dropUniqueSuffix(Name)); - if (!SN2I.addName(Name, I)) - reportError("repeated section name: '" + Name + - "' at YAML section number " + Twine(I)); + if (!SN2I.addName(C->Name, SecNdx)) + llvm_unreachable("buildSectionIndex() failed"); + DotShStrtab.add(ELFYAML::dropUniqueSuffix(C->Name)); } DotShStrtab.finalize(); @@ -1061,7 +1362,8 @@ template <class ELFT> void ELFState<ELFT>::buildSymbolIndexes() { if (Doc.Symbols) Build(*Doc.Symbols, SymN2I); - Build(Doc.DynamicSymbols, DynSymN2I); + if (Doc.DynamicSymbols) + Build(*Doc.DynamicSymbols, DynSymN2I); } template <class ELFT> void ELFState<ELFT>::finalizeStrings() { @@ -1072,22 +1374,26 @@ template <class ELFT> void ELFState<ELFT>::finalizeStrings() { DotStrtab.finalize(); // Add the dynamic symbol names to .dynstr section. - for (const ELFYAML::Symbol &Sym : Doc.DynamicSymbols) - DotDynstr.add(ELFYAML::dropUniqueSuffix(Sym.Name)); + if (Doc.DynamicSymbols) + for (const ELFYAML::Symbol &Sym : *Doc.DynamicSymbols) + DotDynstr.add(ELFYAML::dropUniqueSuffix(Sym.Name)); // SHT_GNU_verdef and SHT_GNU_verneed sections might also // add strings to .dynstr section. - for (const std::unique_ptr<ELFYAML::Section> &Sec : Doc.Sections) { - if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec.get())) { - for (const ELFYAML::VerneedEntry &VE : VerNeed->VerneedV) { - DotDynstr.add(VE.File); - for (const ELFYAML::VernauxEntry &Aux : VE.AuxV) - DotDynstr.add(Aux.Name); + for (const ELFYAML::Chunk *Sec : Doc.getSections()) { + if (auto VerNeed = dyn_cast<ELFYAML::VerneedSection>(Sec)) { + if (VerNeed->VerneedV) { + for (const ELFYAML::VerneedEntry &VE : *VerNeed->VerneedV) { + DotDynstr.add(VE.File); + for (const ELFYAML::VernauxEntry &Aux : VE.AuxV) + DotDynstr.add(Aux.Name); + } } - } else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec.get())) { - for (const ELFYAML::VerdefEntry &E : VerDef->Entries) - for (StringRef Name : E.VerNames) - DotDynstr.add(Name); + } else if (auto VerDef = dyn_cast<ELFYAML::VerdefSection>(Sec)) { + if (VerDef->Entries) + for (const ELFYAML::VerdefEntry &E : *VerDef->Entries) + for (StringRef Name : E.VerNames) + DotDynstr.add(Name); } } @@ -1105,6 +1411,9 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc, State.finalizeStrings(); State.buildSectionIndex(); + if (State.HasError) + return false; + State.buildSymbolIndexes(); std::vector<Elf_Phdr> PHeaders; @@ -1119,7 +1428,7 @@ bool ELFState<ELFT>::writeELF(raw_ostream &OS, ELFYAML::Object &Doc, std::vector<Elf_Shdr> SHeaders; State.initSectionHeaders(SHeaders, CBA); - // Now we can decide segment offsets + // Now we can decide segment offsets. State.setProgramHeaderLayout(PHeaders, SHeaders); if (State.HasError) diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp index 29585abe6e80..efa7ecb4728b 100644 --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -24,7 +24,7 @@ namespace llvm { -ELFYAML::Section::~Section() = default; +ELFYAML::Chunk::~Chunk() = default; namespace yaml { @@ -54,6 +54,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_PT>::enumeration( ECase(PT_GNU_EH_FRAME); ECase(PT_GNU_STACK); ECase(PT_GNU_RELRO); + ECase(PT_GNU_PROPERTY); #undef ECase IO.enumFallback<Hex32>(Value); } @@ -252,6 +253,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( ECase(ELFOSABI_HPUX); ECase(ELFOSABI_NETBSD); ECase(ELFOSABI_GNU); + ECase(ELFOSABI_LINUX); ECase(ELFOSABI_HURD); ECase(ELFOSABI_SOLARIS); ECase(ELFOSABI_AIX); @@ -273,6 +275,7 @@ void ScalarEnumerationTraits<ELFYAML::ELF_ELFOSABI>::enumeration( ECase(ELFOSABI_C6000_LINUX); ECase(ELFOSABI_STANDALONE); #undef ECase + IO.enumFallback<Hex8>(Value); } void ScalarBitSetTraits<ELFYAML::ELF_EF>::bitset(IO &IO, @@ -863,6 +866,24 @@ template <> struct SequenceElementTraits<StOtherPiece> { static const bool flow = true; }; +template <> struct ScalarTraits<ELFYAML::YAMLFlowString> { + static void output(const ELFYAML::YAMLFlowString &Val, void *, + raw_ostream &Out) { + Out << Val; + } + static StringRef input(StringRef Scalar, void *, + ELFYAML::YAMLFlowString &Val) { + Val = Scalar; + return {}; + } + static QuotingType mustQuote(StringRef S) { + return ScalarTraits<StringRef>::mustQuote(S); + } +}; +template <> struct SequenceElementTraits<ELFYAML::YAMLFlowString> { + static const bool flow = true; +}; + namespace { struct NormalizedOther { @@ -998,10 +1019,12 @@ static void commonSectionMapping(IO &IO, ELFYAML::Section &Section) { // are producing YAML, because yaml2obj sets appropriate values for them // automatically when they are not explicitly defined. assert(!IO.outputting() || - (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue())); + (!Section.ShOffset.hasValue() && !Section.ShSize.hasValue() && + !Section.ShName.hasValue() && !Section.ShFlags.hasValue())); IO.mapOptional("ShName", Section.ShName); IO.mapOptional("ShOffset", Section.ShOffset); IO.mapOptional("ShSize", Section.ShSize); + IO.mapOptional("ShFlags", Section.ShFlags); } static void sectionMapping(IO &IO, ELFYAML::DynamicSection &Section) { @@ -1032,6 +1055,22 @@ static void sectionMapping(IO &IO, ELFYAML::HashSection &Section) { IO.mapOptional("Size", Section.Size); } +static void sectionMapping(IO &IO, ELFYAML::NoteSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Size", Section.Size); + IO.mapOptional("Notes", Section.Notes); +} + + +static void sectionMapping(IO &IO, ELFYAML::GnuHashSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Content", Section.Content); + IO.mapOptional("Header", Section.Header); + IO.mapOptional("BloomFilter", Section.BloomFilter); + IO.mapOptional("HashBuckets", Section.HashBuckets); + IO.mapOptional("HashValues", Section.HashValues); +} static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Size", Section.Size, Hex64(0)); @@ -1040,7 +1079,8 @@ static void sectionMapping(IO &IO, ELFYAML::NoBitsSection &Section) { static void sectionMapping(IO &IO, ELFYAML::VerdefSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); - IO.mapRequired("Entries", Section.Entries); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); } static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { @@ -1051,7 +1091,8 @@ static void sectionMapping(IO &IO, ELFYAML::SymverSection &Section) { static void sectionMapping(IO &IO, ELFYAML::VerneedSection &Section) { commonSectionMapping(IO, Section); IO.mapRequired("Info", Section.Info); - IO.mapRequired("Dependencies", Section.VerneedV); + IO.mapOptional("Dependencies", Section.VerneedV); + IO.mapOptional("Content", Section.Content); } static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { @@ -1060,9 +1101,15 @@ static void sectionMapping(IO &IO, ELFYAML::RelocationSection &Section) { IO.mapOptional("Relocations", Section.Relocations); } +static void sectionMapping(IO &IO, ELFYAML::RelrSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Entries", Section.Entries); + IO.mapOptional("Content", Section.Content); +} + static void groupSectionMapping(IO &IO, ELFYAML::Group &Group) { commonSectionMapping(IO, Group); - IO.mapOptional("Info", Group.Signature, StringRef()); + IO.mapOptional("Info", Group.Signature); IO.mapRequired("Members", Group.Members); } @@ -1078,6 +1125,25 @@ static void sectionMapping(IO &IO, ELFYAML::AddrsigSection &Section) { IO.mapOptional("Symbols", Section.Symbols); } +static void fillMapping(IO &IO, ELFYAML::Fill &Fill) { + IO.mapOptional("Name", Fill.Name, StringRef()); + IO.mapOptional("Pattern", Fill.Pattern); + IO.mapRequired("Size", Fill.Size); +} + +static void sectionMapping(IO &IO, ELFYAML::LinkerOptionsSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Options", Section.Options); + IO.mapOptional("Content", Section.Content); +} + +static void sectionMapping(IO &IO, + ELFYAML::DependentLibrariesSection &Section) { + commonSectionMapping(IO, Section); + IO.mapOptional("Libraries", Section.Libs); + IO.mapOptional("Content", Section.Content); +} + void MappingTraits<ELFYAML::SectionOrType>::mapping( IO &IO, ELFYAML::SectionOrType §ionOrType) { IO.mapRequired("SectionOrType", sectionOrType.sectionNameOrType); @@ -1108,15 +1174,27 @@ static void sectionMapping(IO &IO, ELFYAML::MipsABIFlags &Section) { IO.mapOptional("Flags2", Section.Flags2, Hex32(0)); } -void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( - IO &IO, std::unique_ptr<ELFYAML::Section> &Section) { - ELFYAML::ELF_SHT sectionType; - if (IO.outputting()) - sectionType = Section->Type; - else - IO.mapRequired("Type", sectionType); +void MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::mapping( + IO &IO, std::unique_ptr<ELFYAML::Chunk> &Section) { + ELFYAML::ELF_SHT Type; + if (IO.outputting()) { + Type = cast<ELFYAML::Section>(Section.get())->Type; + } else { + // When the Type string does not have a "SHT_" prefix, we know it is not a + // description of a regular ELF output section. Currently, we have one + // special type named "Fill". See comments for Fill. + StringRef StrType; + IO.mapRequired("Type", StrType); + if (StrType == "Fill") { + Section.reset(new ELFYAML::Fill()); + fillMapping(IO, *cast<ELFYAML::Fill>(Section.get())); + return; + } + + IO.mapRequired("Type", Type); + } - switch (sectionType) { + switch (Type) { case ELF::SHT_DYNAMIC: if (!IO.outputting()) Section.reset(new ELFYAML::DynamicSection()); @@ -1128,6 +1206,11 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::RelocationSection()); sectionMapping(IO, *cast<ELFYAML::RelocationSection>(Section.get())); break; + case ELF::SHT_RELR: + if (!IO.outputting()) + Section.reset(new ELFYAML::RelrSection()); + sectionMapping(IO, *cast<ELFYAML::RelrSection>(Section.get())); + break; case ELF::SHT_GROUP: if (!IO.outputting()) Section.reset(new ELFYAML::Group()); @@ -1143,6 +1226,16 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::HashSection()); sectionMapping(IO, *cast<ELFYAML::HashSection>(Section.get())); break; + case ELF::SHT_NOTE: + if (!IO.outputting()) + Section.reset(new ELFYAML::NoteSection()); + sectionMapping(IO, *cast<ELFYAML::NoteSection>(Section.get())); + break; + case ELF::SHT_GNU_HASH: + if (!IO.outputting()) + Section.reset(new ELFYAML::GnuHashSection()); + sectionMapping(IO, *cast<ELFYAML::GnuHashSection>(Section.get())); + break; case ELF::SHT_MIPS_ABIFLAGS: if (!IO.outputting()) Section.reset(new ELFYAML::MipsABIFlags()); @@ -1173,6 +1266,17 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( Section.reset(new ELFYAML::AddrsigSection()); sectionMapping(IO, *cast<ELFYAML::AddrsigSection>(Section.get())); break; + case ELF::SHT_LLVM_LINKER_OPTIONS: + if (!IO.outputting()) + Section.reset(new ELFYAML::LinkerOptionsSection()); + sectionMapping(IO, *cast<ELFYAML::LinkerOptionsSection>(Section.get())); + break; + case ELF::SHT_LLVM_DEPENDENT_LIBRARIES: + if (!IO.outputting()) + Section.reset(new ELFYAML::DependentLibrariesSection()); + sectionMapping(IO, + *cast<ELFYAML::DependentLibrariesSection>(Section.get())); + break; default: if (!IO.outputting()) { StringRef Name; @@ -1192,17 +1296,18 @@ void MappingTraits<std::unique_ptr<ELFYAML::Section>>::mapping( } } -StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( - IO &io, std::unique_ptr<ELFYAML::Section> &Section) { - if (const auto *RawSection = - dyn_cast<ELFYAML::RawContentSection>(Section.get())) { +StringRef MappingTraits<std::unique_ptr<ELFYAML::Chunk>>::validate( + IO &io, std::unique_ptr<ELFYAML::Chunk> &C) { + if (const auto *RawSection = dyn_cast<ELFYAML::RawContentSection>(C.get())) { if (RawSection->Size && RawSection->Content && (uint64_t)(*RawSection->Size) < RawSection->Content->binary_size()) return "Section size must be greater than or equal to the content size"; + if (RawSection->Flags && RawSection->ShFlags) + return "ShFlags and Flags cannot be used together"; return {}; } - if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(Section.get())) { + if (const auto *SS = dyn_cast<ELFYAML::StackSizesSection>(C.get())) { if (!SS->Entries && !SS->Content && !SS->Size) return ".stack_sizes: one of Content, Entries and Size must be specified"; @@ -1222,7 +1327,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } - if (const auto *HS = dyn_cast<ELFYAML::HashSection>(Section.get())) { + if (const auto *HS = dyn_cast<ELFYAML::HashSection>(C.get())) { if (!HS->Content && !HS->Bucket && !HS->Chain && !HS->Size) return "one of \"Content\", \"Size\", \"Bucket\" or \"Chain\" must be " "specified"; @@ -1245,7 +1350,7 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } - if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(Section.get())) { + if (const auto *Sec = dyn_cast<ELFYAML::AddrsigSection>(C.get())) { if (!Sec->Symbols && !Sec->Content && !Sec->Size) return "one of \"Content\", \"Size\" or \"Symbols\" must be specified"; @@ -1270,6 +1375,89 @@ StringRef MappingTraits<std::unique_ptr<ELFYAML::Section>>::validate( return {}; } + if (const auto *NS = dyn_cast<ELFYAML::NoteSection>(C.get())) { + if (!NS->Content && !NS->Size && !NS->Notes) + return "one of \"Content\", \"Size\" or \"Notes\" must be " + "specified"; + + if (!NS->Content && !NS->Size) + return {}; + + if (NS->Size && NS->Content && + (uint64_t)*NS->Size < NS->Content->binary_size()) + return "\"Size\" must be greater than or equal to the content " + "size"; + + if (NS->Notes) + return "\"Notes\" cannot be used with \"Content\" or \"Size\""; + return {}; + } + + if (const auto *Sec = dyn_cast<ELFYAML::GnuHashSection>(C.get())) { + if (!Sec->Content && !Sec->Header && !Sec->BloomFilter && + !Sec->HashBuckets && !Sec->HashValues) + return "either \"Content\" or \"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashBuckets\" must be specified"; + + if (Sec->Header || Sec->BloomFilter || Sec->HashBuckets || + Sec->HashValues) { + if (!Sec->Header || !Sec->BloomFilter || !Sec->HashBuckets || + !Sec->HashValues) + return "\"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashValues\" must be used together"; + if (Sec->Content) + return "\"Header\", \"BloomFilter\", " + "\"HashBuckets\" and \"HashValues\" can't be used together with " + "\"Content\""; + return {}; + } + + // Only Content is specified. + return {}; + } + + if (const auto *Sec = dyn_cast<ELFYAML::LinkerOptionsSection>(C.get())) { + if (Sec->Options && Sec->Content) + return "\"Options\" and \"Content\" can't be used together"; + return {}; + } + + if (const auto *Sec = dyn_cast<ELFYAML::DependentLibrariesSection>(C.get())) { + if (Sec->Libs && Sec->Content) + return "SHT_LLVM_DEPENDENT_LIBRARIES: \"Libraries\" and \"Content\" " + "can't " + "be used together"; + return {}; + } + + if (const auto *F = dyn_cast<ELFYAML::Fill>(C.get())) { + if (!F->Pattern) + return {}; + if (F->Pattern->binary_size() != 0 && !F->Size) + return "\"Size\" can't be 0 when \"Pattern\" is not empty"; + return {}; + } + + if (const auto *VD = dyn_cast<ELFYAML::VerdefSection>(C.get())) { + if (VD->Entries && VD->Content) + return "SHT_GNU_verdef: \"Entries\" and \"Content\" can't be used " + "together"; + return {}; + } + + if (const auto *VD = dyn_cast<ELFYAML::VerneedSection>(C.get())) { + if (VD->VerneedV && VD->Content) + return "SHT_GNU_verneed: \"Dependencies\" and \"Content\" can't be used " + "together"; + return {}; + } + + if (const auto *RS = dyn_cast<ELFYAML::RelrSection>(C.get())) { + if (RS->Entries && RS->Content) + return "\"Entries\" and \"Content\" can't be used together"; + return {}; + } + return {}; } @@ -1305,6 +1493,15 @@ void MappingTraits<ELFYAML::StackSizeEntry>::mapping( IO.mapRequired("Size", E.Size); } +void MappingTraits<ELFYAML::GnuHashHeader>::mapping(IO &IO, + ELFYAML::GnuHashHeader &E) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapOptional("NBuckets", E.NBuckets); + IO.mapRequired("SymNdx", E.SymNdx); + IO.mapOptional("MaskWords", E.MaskWords); + IO.mapRequired("Shift2", E.Shift2); +} + void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, ELFYAML::DynamicEntry &Rel) { assert(IO.getContext() && "The IO context is not initialized"); @@ -1313,6 +1510,14 @@ void MappingTraits<ELFYAML::DynamicEntry>::mapping(IO &IO, IO.mapRequired("Value", Rel.Val); } +void MappingTraits<ELFYAML::NoteEntry>::mapping(IO &IO, ELFYAML::NoteEntry &N) { + assert(IO.getContext() && "The IO context is not initialized"); + + IO.mapOptional("Name", N.Name); + IO.mapOptional("Desc", N.Desc); + IO.mapRequired("Type", N.Type); +} + void MappingTraits<ELFYAML::VerdefEntry>::mapping(IO &IO, ELFYAML::VerdefEntry &E) { assert(IO.getContext() && "The IO context is not initialized"); @@ -1371,7 +1576,7 @@ void MappingTraits<ELFYAML::Object>::mapping(IO &IO, ELFYAML::Object &Object) { IO.mapTag("!ELF", true); IO.mapRequired("FileHeader", Object.Header); IO.mapOptional("ProgramHeaders", Object.ProgramHeaders); - IO.mapOptional("Sections", Object.Sections); + IO.mapOptional("Sections", Object.Chunks); IO.mapOptional("Symbols", Object.Symbols); IO.mapOptional("DynamicSymbols", Object.DynamicSymbols); IO.setContext(nullptr); @@ -1383,6 +1588,13 @@ void MappingTraits<ELFYAML::AddrsigSymbol>::mapping(IO &IO, ELFYAML::AddrsigSymb IO.mapOptional("Index", Sym.Index); } +void MappingTraits<ELFYAML::LinkerOption>::mapping(IO &IO, + ELFYAML::LinkerOption &Opt) { + assert(IO.getContext() && "The IO context is not initialized"); + IO.mapRequired("Name", Opt.Key); + IO.mapRequired("Value", Opt.Value); +} + LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_AFL_REG) LLVM_YAML_STRONG_TYPEDEF(uint8_t, MIPS_ABI_FP) LLVM_YAML_STRONG_TYPEDEF(uint32_t, MIPS_AFL_EXT) diff --git a/llvm/lib/ObjectYAML/MachOEmitter.cpp b/llvm/lib/ObjectYAML/MachOEmitter.cpp index b56f811ce67d..bda4aed885b4 100644 --- a/llvm/lib/ObjectYAML/MachOEmitter.cpp +++ b/llvm/lib/ObjectYAML/MachOEmitter.cpp @@ -494,7 +494,8 @@ void UniversalWriter::writeMachO(raw_ostream &OS) { writeFatArchs(OS); auto &FatFile = *ObjectFile.FatMachO; - assert(FatFile.FatArchs.size() == FatFile.Slices.size()); + assert(FatFile.FatArchs.size() >= FatFile.Slices.size() && + "Cannot write Slices if not decribed in FatArches"); for (size_t i = 0; i < FatFile.Slices.size(); i++) { ZeroToOffset(OS, FatFile.FatArchs[i].offset); MachOWriter Writer(FatFile.Slices[i]); diff --git a/llvm/lib/ObjectYAML/MinidumpYAML.cpp b/llvm/lib/ObjectYAML/MinidumpYAML.cpp index 21b2a4d78629..77ea42c41a4c 100644 --- a/llvm/lib/ObjectYAML/MinidumpYAML.cpp +++ b/llvm/lib/ObjectYAML/MinidumpYAML.cpp @@ -337,6 +337,7 @@ static void streamMapping(yaml::IO &IO, SystemInfoStream &Stream) { break; case ProcessorArchitecture::ARM: case ProcessorArchitecture::ARM64: + case ProcessorArchitecture::BP_ARM64: IO.mapOptional("CPU", Info.CPU.Arm); break; default: diff --git a/llvm/lib/ObjectYAML/YAML.cpp b/llvm/lib/ObjectYAML/YAML.cpp index 6eba16e36c2a..5dcb113d3395 100644 --- a/llvm/lib/ObjectYAML/YAML.cpp +++ b/llvm/lib/ObjectYAML/YAML.cpp @@ -37,15 +37,17 @@ StringRef yaml::ScalarTraits<yaml::BinaryRef>::input(StringRef Scalar, void *, return {}; } -void yaml::BinaryRef::writeAsBinary(raw_ostream &OS) const { +void yaml::BinaryRef::writeAsBinary(raw_ostream &OS, uint64_t N) const { if (!DataIsHexString) { - OS.write((const char *)Data.data(), Data.size()); + OS.write((const char *)Data.data(), std::min<uint64_t>(N, Data.size())); return; } - for (unsigned I = 0, N = Data.size(); I != N; I += 2) { - uint8_t Byte = llvm::hexDigitValue(Data[I]); + + for (uint64_t I = 0, E = std::min<uint64_t>(N, Data.size() / 2); I != E; + ++I) { + uint8_t Byte = llvm::hexDigitValue(Data[I * 2]); Byte <<= 4; - Byte |= llvm::hexDigitValue(Data[I + 1]); + Byte |= llvm::hexDigitValue(Data[I * 2 + 1]); OS.write(Byte); } } |