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,18 +83,26 @@ 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; } -static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, - uint64_t NewFlags) { +static uint64_t getSectionFlagsPreserveMask( + uint64_t OldFlags, uint64_t NewFlags, uint16_t EMachine) { // Preserve some flags which should not be dropped when setting flags. // Also, preserve anything OS/processor dependant. const uint64_t PreserveMask = (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 & + ~(EMachine == EM_X86_64 ? ELF::SHF_X86_64_LARGE : 0UL); return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); } @@ -105,8 +114,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) { + Expected NewFlags = getNewShfFlags(Flags, EMachine); + if (!NewFlags) + return NewFlags.takeError(); + Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, *NewFlags, EMachine); // 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 +128,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 +703,8 @@ const auto Iter = Config.SetSectionFlags.find(Sec.Name); if (Iter != Config.SetSectionFlags.end()) { const SectionFlagsUpdate &SFU = Iter->second; - setSectionFlagsAndType(Sec, SFU.NewFlags); + if (Error E = setSectionFlagsAndType(Sec, SFU.NewFlags, Obj.Machine)) + return E; } auto It2 = Config.SetSectionType.find(Sec.Name); if (It2 != Config.SetSectionType.end()) @@ -705,8 +721,10 @@ 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) { + if (Error E = setSectionFlagsAndType(Sec, *SR.NewFlags, Obj.Machine)) + 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/rename-section-flag-osproc-mask.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test +++ llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-osproc-mask.test @@ -1,10 +1,14 @@ -# Test that cpu/processor-specific SHF_* flags are preserved. +# Test that cpu/processor-specific SHF_* flags are preserved, +# except SHF_X86_64_LARGE on x86_64 (which is controlled with the +# "large" flag). # ===== x86_64 ===== # RUN: yaml2obj --docnum=1 %s -o %t-x86_64.o # RUN: llvm-objcopy --rename-section=.foo=.bar,alloc %t-x86_64.o # RUN: llvm-readobj --sections %t-x86_64.o | FileCheck %s --check-prefix=X86_64 +# RUN: llvm-objcopy --rename-section=.bar=.quz,alloc,large %t-x86_64.o +# RUN: llvm-readobj --sections %t-x86_64.o | FileCheck %s --check-prefix=X86_64-LARGE --- !ELF FileHeader: @@ -22,8 +26,14 @@ # X86_64-NEXT: Flags [ # X86_64-NEXT: SHF_ALLOC (0x2) # X86_64-NEXT: SHF_WRITE (0x1) -# X86_64-NEXT: SHF_X86_64_LARGE (0x10000000) # X86_64-NEXT: ] +# X86_64-LARGE: Name: .quz +# X86_64-LARGE-NEXT: Type: SHT_PROGBITS +# X86_64-LARGE-NEXT: Flags [ +# X86_64-LARGE-NEXT: SHF_ALLOC (0x2) +# X86_64-LARGE-NEXT: SHF_WRITE (0x1) +# X86_64-LARGE-NEXT: SHF_X86_64_LARGE (0x10000000) +# X86_64-LARGE-NEXT: ] # ===== hex ===== 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,12 @@ # 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 +# RUN: llvm-objcopy --set-section-flags=.foo=data \ +# RUN: --set-section-flags=.baz=data --set-section-flags=.rela.baz=data %t %t.no-large +# RUN: llvm-readobj --sections %t.no-large | FileCheck %s --check-prefixes=CHECK,PROGBITS,WRITE # Multiple flags: # RUN: llvm-objcopy --set-section-flags=.foo=alloc,readonly,strings \ @@ -102,6 +108,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 +121,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 +133,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; }