Index: llvm/include/llvm/ObjectYAML/ELFYAML.h =================================================================== --- llvm/include/llvm/ObjectYAML/ELFYAML.h +++ llvm/include/llvm/ObjectYAML/ELFYAML.h @@ -192,6 +192,9 @@ // This can be used to override the sh_size field. It does not affect the // content written. Optional ShSize; + + // This can be used to override the sh_flags field. + Optional ShFlags; }; // Fill is a block of data which is placed outside of sections. It is Index: llvm/lib/ObjectYAML/ELFEmitter.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFEmitter.cpp +++ llvm/lib/ObjectYAML/ELFEmitter.cpp @@ -349,6 +349,20 @@ return Index; } +template +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 bool ELFState::initImplicitHeader(ContiguousBlobAccumulator &CBA, Elf_Shdr &Header, StringRef SecName, @@ -370,16 +384,8 @@ 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(YAMLSec, Header); return true; } @@ -484,15 +490,8 @@ 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(Sec, SHeader); } } Index: llvm/lib/ObjectYAML/ELFYAML.cpp =================================================================== --- llvm/lib/ObjectYAML/ELFYAML.cpp +++ llvm/lib/ObjectYAML/ELFYAML.cpp @@ -1017,10 +1017,12 @@ // 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) { @@ -1283,11 +1285,12 @@ StringRef MappingTraits>::validate( IO &io, std::unique_ptr &C) { - if (const auto *RawSection = - dyn_cast(C.get())) { + if (const auto *RawSection = dyn_cast(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 {}; } Index: llvm/test/tools/yaml2obj/ELF/override-shflags.yaml =================================================================== --- /dev/null +++ llvm/test/tools/yaml2obj/ELF/override-shflags.yaml @@ -0,0 +1,90 @@ +## Check we are able to set custom sh_flags field +## for different sections. + +# RUN: yaml2obj --docnum=1 %s -o %t1 +# RUN: llvm-readobj --sections %t1 | FileCheck %s --check-prefix=UPDATE-FLAGS + +# UPDATE-FLAGS: Name: .symtab +# UPDATE-FLAGS-NEXT: Type: SHT_SYMTAB +# UPDATE-FLAGS-NEXT: Flags [ (0x1) + +# UPDATE-FLAGS: Name: .strtab +# UPDATE-FLAGS-NEXT: Type: SHT_STRTAB +# UPDATE-FLAGS-NEXT: Flags [ (0x2) + +# UPDATE-FLAGS: Name: .shstrtab +# UPDATE-FLAGS-NEXT: Type: SHT_STRTAB +# UPDATE-FLAGS-NEXT: Flags [ (0x3) + +# UPDATE-FLAGS: Name: .dynsym +# UPDATE-FLAGS-NEXT: Type: SHT_DYNSYM +# UPDATE-FLAGS-NEXT: Flags [ (0x4) + +# UPDATE-FLAGS: Name: .dynstr +# UPDATE-FLAGS-NEXT: Type: SHT_STRTAB +# UPDATE-FLAGS-NEXT: Flags [ (0x5) + +# UPDATE-FLAGS: Name: .regular.os +# UPDATE-FLAGS-NEXT: Type: SHT_PROGBITS +# UPDATE-FLAGS-NEXT: Flags [ (0xAB00000) + +# UPDATE-FLAGS: Name: .regular.proc +# UPDATE-FLAGS-NEXT: Type: SHT_PROGBITS +# UPDATE-FLAGS-NEXT: Flags [ (0xC0000000) + +# UPDATE-FLAGS: Name: .regular.all +# UPDATE-FLAGS-NEXT: Type: SHT_PROGBITS +# UPDATE-FLAGS-NEXT: Flags [ (0xFFFFFFFF) + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: +## Check we can override flags for implicit sections. + - Name: .symtab + Type: SHT_SYMTAB + ShFlags: 0x000000001 + - Name: .strtab + Type: SHT_STRTAB + ShFlags: 0x000000002 + - Name: .shstrtab + Type: SHT_STRTAB + ShFlags: 0x000000003 + - Name: .dynsym + Type: SHT_DYNSYM + ShFlags: 0x000000004 + - Name: .dynstr + Type: SHT_STRTAB + ShFlags: 0x000000005 +## Check we can override flags for regular sections. + - Name: .regular.os + Type: SHT_PROGBITS + ShFlags: 0x0AB00000 + - Name: .regular.proc + Type: SHT_PROGBITS + ShFlags: 0xC0000000 + - Name: .regular.all + Type: SHT_PROGBITS + ShFlags: 0xFFFFFFFF + +## ShFlags is used when we want to workaround the flag values validation. +## It does not make sense to allow both ShFlags and Flags in the document. + +# RUN: not yaml2obj --docnum=2 %s 2>&1 | FileCheck %s --check-prefix=ERR + +# ERR: error: ShFlags and Flags cannot be used together + +--- !ELF +FileHeader: + Class: ELFCLASS64 + Data: ELFDATA2LSB + Type: ET_REL + Machine: EM_X86_64 +Sections: + - Name: .symtab + Type: SHT_SYMTAB + Flags: [ SHF_ALLOC ] + ShFlags: 0x1