diff --git a/llvm/include/llvm/ObjectYAML/ELFYAML.h b/llvm/include/llvm/ObjectYAML/ELFYAML.h --- a/llvm/include/llvm/ObjectYAML/ELFYAML.h +++ b/llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -171,6 +171,7 @@ struct StackSizesSection : Section { Optional Content; + Optional Size; Optional> Entries; StackSizesSection() : Section(SectionKind::StackSizes) {} diff --git a/llvm/lib/ObjectYAML/ELFEmitter.cpp b/llvm/lib/ObjectYAML/ELFEmitter.cpp --- a/llvm/lib/ObjectYAML/ELFEmitter.cpp +++ b/llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -440,19 +440,20 @@ return Symbols.size(); } -static uint64_t writeRawSectionData(raw_ostream &OS, - const ELFYAML::RawContentSection &RawSec) { +static uint64_t writeContent(raw_ostream &OS, + const Optional &Content, + const Optional &Size) { size_t ContentSize = 0; - if (RawSec.Content) { - RawSec.Content->writeAsBinary(OS); - ContentSize = RawSec.Content->binary_size(); + if (Content) { + Content->writeAsBinary(OS); + ContentSize = Content->binary_size(); } - if (!RawSec.Size) + if (!Size) return ContentSize; - OS.write_zeros(*RawSec.Size - ContentSize); - return *RawSec.Size; + OS.write_zeros(*Size - ContentSize); + return *Size; } template @@ -554,7 +555,7 @@ 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); + SHeader.sh_size = writeContent(OS, RawSec->Content, RawSec->Size); return; } @@ -579,7 +580,7 @@ auto &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); if (RawSec && (RawSec->Content || RawSec->Size)) { - SHeader.sh_size = writeRawSectionData(OS, *RawSec); + SHeader.sh_size = writeContent(OS, RawSec->Content, RawSec->Size); } else { STB.write(OS); SHeader.sh_size = STB.getSize(); @@ -675,7 +676,7 @@ ContiguousBlobAccumulator &CBA) { raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); - SHeader.sh_size = writeRawSectionData(OS, Section); + SHeader.sh_size = writeContent(OS, Section.Content, Section.Size); if (Section.EntSize) SHeader.sh_entsize = *Section.EntSize; @@ -795,9 +796,8 @@ raw_ostream &OS = CBA.getOSAndAlignedOffset(SHeader.sh_offset, SHeader.sh_addralign); - if (Section.Content) { - Section.Content->writeAsBinary(OS); - SHeader.sh_size = Section.Content->binary_size(); + if (Section.Content || Section.Size) { + SHeader.sh_size = writeContent(OS, Section.Content, Section.Size); return; } diff --git a/llvm/lib/ObjectYAML/ELFYAML.cpp b/llvm/lib/ObjectYAML/ELFYAML.cpp --- a/llvm/lib/ObjectYAML/ELFYAML.cpp +++ b/llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1020,6 +1020,7 @@ static void sectionMapping(IO &IO, ELFYAML::StackSizesSection &Section) { commonSectionMapping(IO, Section); IO.mapOptional("Content", Section.Content); + IO.mapOptional("Size", Section.Size); IO.mapOptional("Entries", Section.Entries); } @@ -1176,10 +1177,22 @@ } if (const auto *SS = dyn_cast(Section.get())) { - if (SS->Content && SS->Entries) + if (!SS->Entries && !SS->Content && !SS->Size) + return ".stack_sizes: one of Content, Entries and Size must be specified"; + + if (SS->Size && SS->Content && + (uint64_t)(*SS->Size) < SS->Content->binary_size()) + return ".stack_sizes: Size must be greater than or equal to the content " + "size"; + + // We accept Content, Size or both together when there are no Entries. + if (!SS->Entries) + return {}; + + if (SS->Size) + return ".stack_sizes: Size and Entries cannot be used together"; + if (SS->Content) return ".stack_sizes: Content and Entries cannot be used together"; - if (!SS->Content && !SS->Entries) - return ".stack_sizes: either Content or Entries tag must be specified"; return {}; } return {}; diff --git a/llvm/test/tools/yaml2obj/elf-stack-sizes.yaml b/llvm/test/tools/yaml2obj/elf-stack-sizes.yaml --- a/llvm/test/tools/yaml2obj/elf-stack-sizes.yaml +++ b/llvm/test/tools/yaml2obj/elf-stack-sizes.yaml @@ -212,11 +212,11 @@ - Address: 0x10 Size: 0x20 -## Check we must specify either "Content" or "Entries" tag when describing .stack_sizes. +## Check we must specify either "Content", "Entries" or "Size" tag when describing .stack_sizes. # RUN: not yaml2obj --docnum=9 %s 2>&1 | FileCheck %s --check-prefix=NO-TAGS -# NO-TAGS: error: .stack_sizes: either Content or Entries tag must be specified +# NO-TAGS: .stack_sizes: one of Content, Entries and Size must be specified --- !ELF FileHeader: @@ -227,3 +227,87 @@ Sections: - Name: .stack_sizes Type: SHT_PROGBITS + +## Check we can't use both "Size" and "Entries" tags at the same time. + +# RUN: not yaml2obj --docnum=10 %s 2>&1 | FileCheck %s --check-prefix=ENTRIES-AND-SIZE + +# ENTRIES-AND-SIZE: .stack_sizes: Size and Entries cannot be used together + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .stack_sizes + Type: SHT_PROGBITS + Size: 0x1 + Entries: + - Address: 0x10 + Size: 0x20 + +## Check we can use only "Size" to create .stack_sizes section. + +# RUN: yaml2obj --docnum=11 %s -o %t11 +# RUN: llvm-readobj --sections --section-data %t11 | FileCheck %s --check-prefix=SIZE + +# SIZE: Name: .stack_sizes +# SIZE: Size: +# SIZE-SAME: 17 +# SIZE: SectionData ( +# SIZE-NEXT: 0000: 00000000 00000000 00000000 00000000 | +# SIZE-NEXT: 0010: 00 | +# SIZE-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .stack_sizes + Type: SHT_PROGBITS + Size: 0x11 + +## Check we can use "Size" and "Content" together to create .stack_sizes section. + +# RUN: yaml2obj --docnum=12 %s -o %t12 +# RUN: llvm-readobj --sections --section-data %t12 | FileCheck %s --check-prefix=SIZE-CONTENT + +# SIZE-CONTENT: Name: .stack_sizes +# SIZE-CONTENT: Size: +# SIZE-CONTENT-SAME: 5 +# SIZE-CONTENT: SectionData ( +# SIZE-CONTENT-NEXT: 0000: 11223300 00 | +# SIZE-CONTENT-NEXT: ) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .stack_sizes + Type: SHT_PROGBITS + Size: 0x5 + Content: "112233" + +# RUN: not yaml2obj --docnum=13 %s 2>&1 | FileCheck %s --check-prefix=SIZE-CONTENT-ERR + +# SIZE-CONTENT-ERR: error: .stack_sizes: Size must be greater than or equal to the content size + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_EXEC + Machine: EM_X86_64 +Sections: + - Name: .stack_sizes + Type: SHT_PROGBITS + Size: 0x1 + Content: "1122"