Index: llvm/include/llvm/ObjCopy/CommonConfig.h =================================================================== --- llvm/include/llvm/ObjCopy/CommonConfig.h +++ llvm/include/llvm/ObjCopy/CommonConfig.h @@ -69,7 +69,8 @@ SecContents = 1 << 10, SecShare = 1 << 11, SecExclude = 1 << 12, - LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecExclude) + SecLarge = 1 << 13, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecLarge) }; struct SectionRename { Index: llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp +++ llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp @@ -68,7 +68,8 @@ return !isDWOSection(Sec); } -static uint64_t getNewShfFlags(SectionFlag AllFlags) { +static Expected getNewShfFlags(SectionFlag AllFlags, + uint16_t EMachine) { uint64_t NewFlags = 0; if (AllFlags & SectionFlag::SecAlloc) NewFlags |= ELF::SHF_ALLOC; @@ -82,6 +83,13 @@ NewFlags |= ELF::SHF_STRINGS; if (AllFlags & SectionFlag::SecExclude) NewFlags |= ELF::SHF_EXCLUDE; + if (AllFlags & SectionFlag::SecLarge) { + if (EMachine != EM_X86_64) + return createStringError(errc::invalid_argument, + "section flag SHF_X86_64_LARGE can only be used " + "with x86_64 architecture"); + NewFlags |= ELF::SHF_X86_64_LARGE; + } return NewFlags; } @@ -93,7 +101,7 @@ (ELF::SHF_COMPRESSED | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER | ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS | ELF::SHF_INFO_LINK) & - ~ELF::SHF_EXCLUDE; + ~(ELF::SHF_EXCLUDE | ELF::SHF_X86_64_LARGE); return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); } @@ -105,8 +113,12 @@ Sec.Type = Type; } -static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) { - Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags)); +static Error setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags, + uint16_t EMachine) { + if (auto NewFlags = getNewShfFlags(Flags, EMachine); !NewFlags) + return NewFlags.takeError(); + else + Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, *NewFlags); // In GNU objcopy, certain flags promote SHT_NOBITS to SHT_PROGBITS. This rule // may promote more non-ALLOC sections than GNU objcopy, but it is fine as @@ -115,6 +127,8 @@ (!(Sec.Flags & ELF::SHF_ALLOC) || Flags & (SectionFlag::SecContents | SectionFlag::SecLoad))) setSectionType(Sec, ELF::SHT_PROGBITS); + + return Error::success(); } static ElfType getOutputElfType(const Binary &Bin) { @@ -688,7 +702,10 @@ const auto Iter = Config.SetSectionFlags.find(Sec.Name); if (Iter != Config.SetSectionFlags.end()) { const SectionFlagsUpdate &SFU = Iter->second; - setSectionFlagsAndType(Sec, SFU.NewFlags); + uint16_t EMachine = + Config.OutputArch ? Config.OutputArch->EMachine : Obj.Machine; + if (Error E = setSectionFlagsAndType(Sec, SFU.NewFlags, EMachine)) + return E; } auto It2 = Config.SetSectionType.find(Sec.Name); if (It2 != Config.SetSectionType.end()) @@ -705,8 +722,12 @@ if (Iter != Config.SectionsToRename.end()) { const SectionRename &SR = Iter->second; Sec.Name = std::string(SR.NewName); - if (SR.NewFlags) - setSectionFlagsAndType(Sec, *SR.NewFlags); + if (SR.NewFlags) { + uint16_t EMachine = + Config.OutputArch ? Config.OutputArch->EMachine : Obj.Machine; + if (Error E = setSectionFlagsAndType(Sec, *SR.NewFlags, EMachine)) + return E; + } RenamedSections.insert(&Sec); } else if (RelocSec && !(Sec.Flags & SHF_ALLOC)) // Postpone processing relocation sections which are not specified in Index: llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test +++ llvm/test/tools/llvm-objcopy/ELF/set-section-flags.test @@ -40,6 +40,9 @@ # RUN: llvm-objcopy --set-section-flags=.foo=share \ # RUN: --set-section-flags=.baz=share --set-section-flags=.rela.baz=share %t %t.share # RUN: llvm-readobj --sections %t.share | FileCheck %s --check-prefixes=CHECK,PROGBITS,WRITE +# RUN: llvm-objcopy --set-section-flags=.foo=large \ +# RUN: --set-section-flags=.baz=large --set-section-flags=.rela.baz=large %t %t.large +# RUN: llvm-readobj --sections %t.large | FileCheck %s --check-prefixes=CHECK,LARGE,PROGBITS,WRITE # Multiple flags: # RUN: llvm-objcopy --set-section-flags=.foo=alloc,readonly,strings \ @@ -102,6 +105,7 @@ # STRINGS-NEXT: SHF_STRINGS (0x20) # EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) +# LARGE-NEXT: SHF_X86_64_LARGE (0x10000000) # CHECK-NEXT: ] # CHECK: Name: .baz @@ -114,6 +118,7 @@ # STRINGS-NEXT: SHF_STRINGS (0x20) # EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) +# LARGE-NEXT: SHF_X86_64_LARGE (0x10000000) # CHECK-NEXT: ] # CHECK: Name: .rela.baz @@ -125,6 +130,7 @@ # STRINGS-NEXT: SHF_STRINGS (0x20) # EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) +# LARGE-NEXT: SHF_X86_64_LARGE (0x10000000) # CHECK-NEXT: ] # BAD-FORMAT: bad format for --set-section-flags: missing '=' Index: llvm/tools/llvm-objcopy/ObjcopyOptions.cpp =================================================================== --- llvm/tools/llvm-objcopy/ObjcopyOptions.cpp +++ llvm/tools/llvm-objcopy/ObjcopyOptions.cpp @@ -205,6 +205,7 @@ .CaseLower("contents", SectionFlag::SecContents) .CaseLower("share", SectionFlag::SecShare) .CaseLower("exclude", SectionFlag::SecExclude) + .CaseLower("large", SectionFlag::SecLarge) .Default(SectionFlag::SecNone); } @@ -218,7 +219,7 @@ errc::invalid_argument, "unrecognized section flag '%s'. Flags supported for GNU " "compatibility: alloc, load, noload, readonly, exclude, debug, " - "code, data, rom, share, contents, merge, strings", + "code, data, rom, share, contents, merge, strings, large", Flag.str().c_str()); ParsedFlags |= ParsedFlag; }