diff options
Diffstat (limited to 'llvm/tools/yaml2obj/yaml2elf.cpp')
-rw-r--r-- | llvm/tools/yaml2obj/yaml2elf.cpp | 94 |
1 files changed, 59 insertions, 35 deletions
diff --git a/llvm/tools/yaml2obj/yaml2elf.cpp b/llvm/tools/yaml2obj/yaml2elf.cpp index 8a53a1b2f48..a02ac8db2d0 100644 --- a/llvm/tools/yaml2obj/yaml2elf.cpp +++ b/llvm/tools/yaml2obj/yaml2elf.cpp @@ -358,13 +358,49 @@ static size_t findFirstNonGlobal(ArrayRef<ELFYAML::Symbol> Symbols) { return Symbols.size(); } +static uint64_t writeRawSectionData(raw_ostream &OS, + const ELFYAML::RawContentSection &RawSec) { + size_t ContentSize = 0; + if (RawSec.Content) { + RawSec.Content->writeAsBinary(OS); + ContentSize = RawSec.Content->binary_size(); + } + + if (!RawSec.Size) + return ContentSize; + + OS.write_zeros(*RawSec.Size - ContentSize); + return *RawSec.Size; +} + template <class ELFT> void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, SymtabType STType, ContiguousBlobAccumulator &CBA, ELFYAML::Section *YAMLSec) { - zero(SHeader); + bool IsStatic = STType == SymtabType::Static; + const auto &Symbols = IsStatic ? Doc.Symbols : Doc.DynamicSymbols; + + ELFYAML::RawContentSection *RawSec = + dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec); + if (RawSec && !Symbols.empty() && (RawSec->Content || RawSec->Size)) { + if (RawSec->Content) + WithColor::error() << "Cannot specify both `Content` and " + + (IsStatic ? Twine("`Symbols`") + : Twine("`DynamicSymbols`")) + + " for symbol table section '" + << RawSec->Name << "'.\n"; + if (RawSec->Size) + WithColor::error() << "Cannot specify both `Size` and " + + (IsStatic ? Twine("`Symbols`") + : Twine("`DynamicSymbols`")) + + " for symbol table section '" + << RawSec->Name << "'.\n"; + exit(1); + } + + zero(SHeader); SHeader.sh_name = DotShStrtab.getOffset(IsStatic ? ".symtab" : ".dynsym"); SHeader.sh_type = IsStatic ? ELF::SHT_SYMTAB : ELF::SHT_DYNSYM; @@ -382,13 +418,8 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, if (!IsStatic) SHeader.sh_flags |= ELF::SHF_ALLOC; - // One greater than symbol table index of the last local symbol. - const auto &Symbols = IsStatic ? Doc.Symbols : Doc.DynamicSymbols; - // If the symbol table section is explicitly described in the YAML // then we should set the fields requested. - ELFYAML::RawContentSection *RawSec = - dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec); SHeader.sh_info = RawSec ? (unsigned)RawSec->Info : findFirstNonGlobal(Symbols) + 1; SHeader.sh_entsize = (YAMLSec && YAMLSec->EntSize) @@ -397,26 +428,24 @@ void ELFState<ELFT>::initSymtabSectionHeader(Elf_Shdr &SHeader, SHeader.sh_addralign = YAMLSec ? (uint64_t)YAMLSec->AddressAlign : 8; SHeader.sh_addr = YAMLSec ? (uint64_t)YAMLSec->Address : 0; - if (RawSec && RawSec->Content.binary_size()) { - RawSec->Content.writeAsBinary( - CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign)); - SHeader.sh_size = RawSec->Size; - } else { - std::vector<Elf_Sym> Syms; - { - // Ensure STN_UNDEF is present - Elf_Sym Sym; - zero(Sym); - Syms.push_back(Sym); - } - - addSymbols(Symbols, Syms, IsStatic ? DotStrtab : DotDynstr); + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + if (RawSec && (RawSec->Content || RawSec->Size)) { + assert(Symbols.empty()); + SHeader.sh_size = writeRawSectionData(OS, *RawSec); + return; + } - writeArrayData( - CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign), - makeArrayRef(Syms)); - SHeader.sh_size = arrayDataSize(makeArrayRef(Syms)); + std::vector<Elf_Sym> Syms; + { + // Ensure STN_UNDEF is present + Elf_Sym Sym; + zero(Sym); + Syms.push_back(Sym); } + + addSymbols(Symbols, Syms, IsStatic ? DotStrtab : DotDynstr); + writeArrayData(OS, makeArrayRef(Syms)); + SHeader.sh_size = arrayDataSize(makeArrayRef(Syms)); } template <class ELFT> @@ -431,13 +460,12 @@ void ELFState<ELFT>::initStrtabSectionHeader(Elf_Shdr &SHeader, StringRef Name, ELFYAML::RawContentSection *RawSec = dyn_cast_or_null<ELFYAML::RawContentSection>(YAMLSec); - if (RawSec && RawSec->Content.binary_size()) { - RawSec->Content.writeAsBinary( - CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign)); - SHeader.sh_size = RawSec->Size; + + auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); + if (RawSec && (RawSec->Content || RawSec->Size)) { + SHeader.sh_size = writeRawSectionData(OS, *RawSec); } else { - STB.write( - CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign)); + STB.write(OS); SHeader.sh_size = STB.getSize(); } @@ -569,12 +597,9 @@ template <class ELFT> bool ELFState<ELFT>::writeSectionContent( Elf_Shdr &SHeader, const ELFYAML::RawContentSection &Section, ContiguousBlobAccumulator &CBA) { - assert(Section.Size >= Section.Content.binary_size() && - "Section size and section content are inconsistent"); raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); - Section.Content.writeAsBinary(OS); - OS.write_zeros(Section.Size - Section.Content.binary_size()); + SHeader.sh_size = writeRawSectionData(OS, Section); if (Section.EntSize) SHeader.sh_entsize = *Section.EntSize; @@ -582,7 +607,6 @@ bool ELFState<ELFT>::writeSectionContent( SHeader.sh_entsize = sizeof(Elf_Relr); else SHeader.sh_entsize = 0; - SHeader.sh_size = Section.Size; SHeader.sh_info = Section.Info; return true; } |