Index: llvm/docs/CommandGuide/llvm-objcopy.rst =================================================================== --- llvm/docs/CommandGuide/llvm-objcopy.rst +++ llvm/docs/CommandGuide/llvm-objcopy.rst @@ -418,6 +418,9 @@ - `load` = if the section has `SHT_NOBITS` type, mark it as a `SHT_PROGBITS` section. - `readonly` = if this flag is not specified, add the `SHF_WRITE` flag. + - `+exclude` = add the `SHF_EXCLUDE` flag. + - `-exclude` = remove the `SHF_EXCLUDE` flag. By default `llvm-objcopy` + preserves `SHF_EXCLUDE` flag for sections unless `-exclude` is specified. - `code` = add the `SHF_EXECINSTR` flag. - `merge` = add the `SHF_MERGE` flag. - `strings` = add the `SHF_STRINGS` flag. Index: llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-preserved.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-preserved.test +++ llvm/test/tools/llvm-objcopy/ELF/rename-section-flag-preserved.test @@ -2,29 +2,31 @@ # Single flags on a section with all flags: # RUN: llvm-objcopy --rename-section=.foo=.bar,alloc %t %t.alloc -# RUN: llvm-readobj --sections %t.alloc | FileCheck %s --check-prefixes=CHECK,ALLOC,WRITE +# RUN: llvm-readobj --sections %t.alloc | FileCheck %s --check-prefixes=CHECK,ALLOC,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,load %t %t.load -# RUN: llvm-readobj --sections %t.load | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.load | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,noload %t %t.noload -# RUN: llvm-readobj --sections %t.noload | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.noload | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,readonly %t %t.readonly -# RUN: llvm-readobj --sections %t.readonly | FileCheck %s --check-prefixes=CHECK +# RUN: llvm-readobj --sections %t.readonly | FileCheck %s --check-prefixes=CHECK,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,debug %t %t.debug -# RUN: llvm-readobj --sections %t.debug | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.debug | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,code %t %t.code -# RUN: llvm-readobj --sections %t.code | FileCheck %s --check-prefixes=CHECK,EXEC,WRITE +# RUN: llvm-readobj --sections %t.code | FileCheck %s --check-prefixes=CHECK,EXEC,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,data %t %t.data -# RUN: llvm-readobj --sections %t.data | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.data | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,rom %t %t.rom -# RUN: llvm-readobj --sections %t.rom | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.rom | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,contents %t %t.contents -# RUN: llvm-readobj --sections %t.contents | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.contents | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,merge %t %t.merge -# RUN: llvm-readobj --sections %t.merge | FileCheck %s --check-prefixes=CHECK,MERGE,WRITE +# RUN: llvm-readobj --sections %t.merge | FileCheck %s --check-prefixes=CHECK,MERGE,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,strings %t %t.strings -# RUN: llvm-readobj --sections %t.strings | FileCheck %s --check-prefixes=CHECK,STRINGS,WRITE +# RUN: llvm-readobj --sections %t.strings | FileCheck %s --check-prefixes=CHECK,STRINGS,WRITE,EXCLUDE # RUN: llvm-objcopy --rename-section=.foo=.bar,share %t %t.share -# RUN: llvm-readobj --sections %t.share | FileCheck %s --check-prefixes=CHECK,WRITE +# RUN: llvm-readobj --sections %t.share | FileCheck %s --check-prefixes=CHECK,WRITE,EXCLUDE +# RUN: llvm-objcopy --rename-section=.foo=.bar,-exclude %t %t.noexclude +# RUN: llvm-readobj --sections %t.noexclude | FileCheck %s --check-prefixes=CHECK,WRITE !ELF FileHeader: @@ -59,7 +61,7 @@ # CHECK-NEXT: Flags [ # ALLOC-NEXT: SHF_ALLOC (0x2) # CHECK-NEXT: SHF_COMPRESSED (0x800) -# CHECK-NEXT: SHF_EXCLUDE (0x80000000) +# EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # EXEC-NEXT: SHF_EXECINSTR (0x4) # CHECK-NEXT: SHF_GROUP (0x200) # CHECK-NEXT: SHF_INFO_LINK (0x40) @@ -69,5 +71,3 @@ # CHECK-NEXT: SHF_TLS (0x400) # WRITE-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] - -# BAD-FLAG: unrecognized section flag 'xyzzy' Index: llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test =================================================================== --- llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test +++ llvm/test/tools/llvm-objcopy/ELF/rename-section-flag.test @@ -13,6 +13,9 @@ # RUN: llvm-objcopy --rename-section=.foo=.bar,readonly \ # RUN: --rename-section=.baz=.blah,readonly %t %t.readonly # RUN: llvm-readobj --sections %t.readonly | FileCheck %s --check-prefixes=CHECK,PROGBITS +# RUN: llvm-objcopy --rename-section=.foo=.bar,+exclude \ +# RUN: --rename-section=.baz=.blah,+exclude %t %t.exclude +# RUN: llvm-readobj --sections %t.exclude | FileCheck %s --check-prefixes=CHECK,PROGBITS,EXCLUDE,WRITE # RUN: llvm-objcopy --rename-section=.foo=.bar,debug \ # RUN: --rename-section=.baz=.blah,debug %t %t.debug # RUN: llvm-readobj --sections %t.debug | FileCheck %s --check-prefixes=CHECK,PROGBITS,WRITE @@ -81,6 +84,7 @@ # EXEC-NEXT: SHF_EXECINSTR (0x4) # MERGE-NEXT: SHF_MERGE (0x10) # STRINGS-NEXT: SHF_STRINGS (0x20) +# EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] @@ -92,7 +96,8 @@ # EXEC-NEXT: SHF_EXECINSTR (0x4) # MERGE-NEXT: SHF_MERGE (0x10) # STRINGS-NEXT: SHF_STRINGS (0x20) +# EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] -# BAD-FLAG: unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings +# BAD-FLAG: unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, +exclude, -exclude, debug, code, data, rom, share, contents, merge, strings 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 @@ -13,6 +13,12 @@ # RUN: llvm-objcopy --set-section-flags=.foo=readonly \ # RUN: --set-section-flags=.baz=readonly --set-section-flags=.rela.baz=readonly %t %t.readonly # RUN: llvm-readobj --sections %t.readonly | FileCheck %s --check-prefixes=CHECK,PROGBITS +# RUN: llvm-objcopy --set-section-flags=.foo=+exclude \ +# RUN: --set-section-flags=.baz=+exclude --set-section-flags=.rela.baz=+exclude %t %t.exclude +# RUN: llvm-readobj --sections %t.exclude | FileCheck %s --check-prefixes=CHECK,PROGBITS,EXCLUDE,WRITE +# RUN: llvm-objcopy --set-section-flags=.foo=-exclude \ +# RUN: --set-section-flags=.baz=-exclude --set-section-flags=.rela.baz=-exclude %t.exclude %t.noexclude +# RUN: llvm-readobj --sections %t.noexclude | FileCheck %s --check-prefixes=CHECK,PROGBITS,WRITE # RUN: llvm-objcopy --set-section-flags=.foo=debug \ # RUN: --set-section-flags=.baz=debug --set-section-flags=.rela.baz=debug %t %t.debug # RUN: llvm-readobj --sections %t.debug | FileCheck %s --check-prefixes=CHECK,PROGBITS,WRITE @@ -51,6 +57,9 @@ # Invalid flags: # RUN: not llvm-objcopy --set-section-flags=.foo=xyzzy %t %t.xyzzy 2>&1 | FileCheck %s --check-prefix=BAD-FLAG +# Mutually exclusive flags: +# RUN: not llvm-objcopy --set-section-flags=.foo=+exclude,-exclude %t %t.exclusive 2>&1 | FileCheck %s --check-prefix=EXCLUSIVE-FLAGS + # Bad flag format: # RUN: not llvm-objcopy --set-section-flags=.foo %t %t2 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT @@ -93,6 +102,7 @@ # EXEC-NEXT: SHF_EXECINSTR (0x4) # MERGE-NEXT: SHF_MERGE (0x10) # STRINGS-NEXT: SHF_STRINGS (0x20) +# EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] @@ -104,6 +114,7 @@ # EXEC-NEXT: SHF_EXECINSTR (0x4) # MERGE-NEXT: SHF_MERGE (0x10) # STRINGS-NEXT: SHF_STRINGS (0x20) +# EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] @@ -114,10 +125,13 @@ # EXEC-NEXT: SHF_EXECINSTR (0x4) # MERGE-NEXT: SHF_MERGE (0x10) # STRINGS-NEXT: SHF_STRINGS (0x20) +# EXCLUDE-NEXT: SHF_EXCLUDE (0x80000000) # WRITE-NEXT: SHF_WRITE (0x1) # CHECK-NEXT: ] # BAD-FORMAT: bad format for --set-section-flags: missing '=' # MULTIPLE-SETS: --set-section-flags set multiple times for section '.foo' -# BAD-FLAG: unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, debug, code, data, rom, share, contents, merge, strings +# BAD-FLAG: unrecognized section flag 'xyzzy'. Flags supported for GNU compatibility: alloc, load, noload, readonly, +exclude, -exclude, debug, code, data, rom, share, contents, merge, strings + +# EXCLUSIVE-FLAGS: section flags '+exclude' and '-exclude' are mutually exclusive and cannot be used together Index: llvm/tools/llvm-objcopy/CopyConfig.h =================================================================== --- llvm/tools/llvm-objcopy/CopyConfig.h +++ llvm/tools/llvm-objcopy/CopyConfig.h @@ -69,7 +69,9 @@ SecStrings = 1 << 9, SecContents = 1 << 10, SecShare = 1 << 11, - LLVM_MARK_AS_BITMASK_ENUM(/* LargestValue = */ SecShare) + SecExclude = 1 << 12, + SecNoexclude = 1 << 13, + LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue=*/SecNoexclude) }; struct SectionRename { Index: llvm/tools/llvm-objcopy/CopyConfig.cpp =================================================================== --- llvm/tools/llvm-objcopy/CopyConfig.cpp +++ llvm/tools/llvm-objcopy/CopyConfig.cpp @@ -146,6 +146,8 @@ .CaseLower("strings", SectionFlag::SecStrings) .CaseLower("contents", SectionFlag::SecContents) .CaseLower("share", SectionFlag::SecShare) + .CaseLower("+exclude", SectionFlag::SecExclude) + .CaseLower("-exclude", SectionFlag::SecNoexclude) .Default(SectionFlag::SecNone); } @@ -158,12 +160,16 @@ return createStringError( errc::invalid_argument, "unrecognized section flag '%s'. Flags supported for GNU " - "compatibility: alloc, load, noload, readonly, debug, code, data, " - "rom, share, contents, merge, strings", + "compatibility: alloc, load, noload, readonly, +exclude, -exclude, " + "debug, code, data, rom, share, contents, merge, strings", Flag.str().c_str()); ParsedFlags |= ParsedFlag; } - + if ((ParsedFlags & SectionFlag::SecExclude) && + (ParsedFlags & SectionFlag::SecNoexclude)) + return createStringError(errc::invalid_argument, + "section flags '+exclude' and '-exclude' are " + "mutually exclusive and cannot be used together"); return ParsedFlags; } Index: llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp =================================================================== --- llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp +++ llvm/tools/llvm-objcopy/ELF/ELFObjcopy.cpp @@ -71,34 +71,30 @@ return !isDWOSection(Sec); } -uint64_t getNewShfFlags(SectionFlag AllFlags) { - uint64_t NewFlags = 0; - if (AllFlags & SectionFlag::SecAlloc) - NewFlags |= ELF::SHF_ALLOC; - if (!(AllFlags & SectionFlag::SecReadonly)) - NewFlags |= ELF::SHF_WRITE; - if (AllFlags & SectionFlag::SecCode) - NewFlags |= ELF::SHF_EXECINSTR; - if (AllFlags & SectionFlag::SecMerge) - NewFlags |= ELF::SHF_MERGE; - if (AllFlags & SectionFlag::SecStrings) - NewFlags |= ELF::SHF_STRINGS; - return NewFlags; -} - -static uint64_t getSectionFlagsPreserveMask(uint64_t OldFlags, - uint64_t NewFlags) { +static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) { // 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_EXCLUDE | ELF::SHF_GROUP | ELF::SHF_LINK_ORDER | ELF::SHF_MASKOS | ELF::SHF_MASKPROC | ELF::SHF_TLS | ELF::SHF_INFO_LINK; - return (OldFlags & PreserveMask) | (NewFlags & ~PreserveMask); -} + uint64_t NewFlags = Sec.Flags & PreserveMask; + if (Flags & SectionFlag::SecAlloc) + NewFlags |= ELF::SHF_ALLOC; + if (!(Flags & SectionFlag::SecReadonly)) + NewFlags |= ELF::SHF_WRITE; + if (Flags & SectionFlag::SecCode) + NewFlags |= ELF::SHF_EXECINSTR; + if (Flags & SectionFlag::SecMerge) + NewFlags |= ELF::SHF_MERGE; + if (Flags & SectionFlag::SecStrings) + NewFlags |= ELF::SHF_STRINGS; + if (Flags & SectionFlag::SecExclude) + NewFlags |= ELF::SHF_EXCLUDE; + if (Flags & SectionFlag::SecNoexclude) + NewFlags &= ~ELF::SHF_EXCLUDE; -static void setSectionFlagsAndType(SectionBase &Sec, SectionFlag Flags) { - Sec.Flags = getSectionFlagsPreserveMask(Sec.Flags, getNewShfFlags(Flags)); + 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