[llvm] r352505 - [llvm-objcopy] Implement --set-section-flags.
Jordan Rupprecht via llvm-commits
llvm-commits at lists.llvm.org
Tue Jan 29 07:05:38 PST 2019
Author: rupprecht
Date: Tue Jan 29 07:05:38 2019
New Revision: 352505
URL: http://llvm.org/viewvc/llvm-project?rev=352505&view=rev
Log:
[llvm-objcopy] Implement --set-section-flags.
Summary:
--set-section-flags is used to change the section flags (e.g. SHF_ALLOC) for given sections. The flags allowed are the same from the existing --rename-section=.old=.new[,flags] feature.
Additionally, make sure that --set-section-flag cannot be used with --rename-section (either the source or destination), since --rename-section accepts flags. This avoids ambiguity for something like "--rename-section=.foo=.bar,alloc --set-section-flag=.bar,code".
Reviewers: jhenderson, jakehehrlich, alexshap, espindola
Reviewed By: jhenderson, jakehehrlich
Subscribers: llvm-commits, emaste, arichardson
Differential Revision: https://reviews.llvm.org/D57198
Added:
llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test
llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-multiple.test
llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags.test
Modified:
llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp
llvm/trunk/tools/llvm-objcopy/CopyConfig.h
llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td
Added: llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test?rev=352505&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-and-rename.test Tue Jan 29 07:05:38 2019
@@ -0,0 +1,14 @@
+# RUN: yaml2obj %s > %t
+
+# RUN: not llvm-objcopy --rename-section=.foo=.bar --set-section-flags=.foo=alloc %t %t.2 2>&1 | FileCheck %s --check-prefix=SET-FOO
+# RUN: not llvm-objcopy --rename-section=.foo=.bar --set-section-flags=.bar=alloc %t %t.2 2>&1 | FileCheck %s --check-prefix=SET-BAR
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+
+# SET-FOO: --set-section-flags=.foo conflicts with --rename-section=.foo=.bar.
+# SET-BAR: --set-section-flags=.bar conflicts with --rename-section=.foo=.bar.
Added: llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-multiple.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-multiple.test?rev=352505&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-multiple.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags-multiple.test Tue Jan 29 07:05:38 2019
@@ -0,0 +1,32 @@
+# RUN: yaml2obj %s > %t
+
+# RUN: llvm-objcopy --set-section-flags=.foo=alloc --set-section-flags=.bar=code %t %t.2
+# RUN: llvm-readobj --sections %t.2 | FileCheck %s --check-prefixes=CHECK,ALLOC,WRITE
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .foo
+ Type: SHT_PROGBITS
+ Flags: [ ]
+ - Name: .bar
+ Type: SHT_PROGBITS
+ Flags: [ ]
+
+# CHECK: Name: .foo
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_ALLOC (0x2)
+# CHECK-NEXT: SHF_WRITE (0x1)
+# CHECK-NEXT: ]
+
+# CHECK: Name: .bar
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# CHECK-NEXT: SHF_EXECINSTR (0x4)
+# CHECK-NEXT: SHF_WRITE (0x1)
+# CHECK-NEXT: ]
Added: llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags.test
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags.test?rev=352505&view=auto
==============================================================================
--- llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags.test (added)
+++ llvm/trunk/test/tools/llvm-objcopy/ELF/set-section-flags.test Tue Jan 29 07:05:38 2019
@@ -0,0 +1,68 @@
+# RUN: yaml2obj %s > %t
+
+# Single flags on a section with no flags:
+# RUN: llvm-objcopy --set-section-flags=.foo=alloc %t %t.alloc
+# RUN: llvm-readobj --sections %t.alloc | FileCheck %s --check-prefixes=CHECK,ALLOC,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=load %t %t.load
+# RUN: llvm-readobj --sections %t.load | FileCheck %s --check-prefixes=CHECK,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=noload %t %t.noload
+# RUN: llvm-readobj --sections %t.noload | FileCheck %s --check-prefixes=CHECK,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=readonly %t %t.readonly
+# RUN: llvm-readobj --sections %t.readonly | FileCheck %s --check-prefixes=CHECK
+# RUN: llvm-objcopy --set-section-flags=.foo=debug %t %t.debug
+# RUN: llvm-readobj --sections %t.debug | FileCheck %s --check-prefixes=CHECK,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=code %t %t.code
+# RUN: llvm-readobj --sections %t.code | FileCheck %s --check-prefixes=CHECK,EXEC,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=data %t %t.data
+# RUN: llvm-readobj --sections %t.data | FileCheck %s --check-prefixes=CHECK,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=rom %t %t.rom
+# RUN: llvm-readobj --sections %t.rom | FileCheck %s --check-prefixes=CHECK,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=contents %t %t.contents
+# RUN: llvm-readobj --sections %t.contents | FileCheck %s --check-prefixes=CHECK,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=merge %t %t.merge
+# RUN: llvm-readobj --sections %t.merge | FileCheck %s --check-prefixes=CHECK,MERGE,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=strings %t %t.strings
+# RUN: llvm-readobj --sections %t.strings | FileCheck %s --check-prefixes=CHECK,STRINGS,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=share %t %t.share
+# RUN: llvm-readobj --sections %t.share | FileCheck %s --check-prefixes=CHECK,WRITE
+
+# Multiple flags:
+# RUN: llvm-objcopy --set-section-flags=.foo=alloc,readonly,strings %t %t.alloc_ro_strings
+# RUN: llvm-readobj --sections %t.alloc_ro_strings | FileCheck %s --check-prefixes=CHECK,ALLOC,STRINGS
+# RUN: llvm-objcopy --set-section-flags=.foo=alloc,code %t %t.alloc_code
+# RUN: llvm-readobj --sections %t.alloc_code | FileCheck %s --check-prefixes=CHECK,ALLOC,EXEC,WRITE
+
+# Invalid flags:
+# RUN: not llvm-objcopy --set-section-flags=.foo=xyzzy %t %t.xyzzy 2>&1 | FileCheck %s --check-prefix=BAD-FLAG
+
+# Bad flag format:
+# RUN: not llvm-objcopy --set-section-flags=.foo %t %t2 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
+
+# Setting flags for the same section multiple times:
+# RUN: not llvm-objcopy --set-section-flags=.foo=alloc --set-section-flags=.foo=load %t %t2 2>&1 | FileCheck %s --check-prefix=MULTIPLE-SETS
+
+!ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_REL
+ Machine: EM_X86_64
+Sections:
+ - Name: .foo
+ Type: SHT_PROGBITS
+ Flags: [ ]
+
+# CHECK: Name: .foo
+# CHECK-NEXT: Type: SHT_PROGBITS
+# CHECK-NEXT: Flags [
+# ALLOC-NEXT: SHF_ALLOC (0x2)
+# EXEC-NEXT: SHF_EXECINSTR (0x4)
+# MERGE-NEXT: SHF_MERGE (0x10)
+# STRINGS-NEXT: SHF_STRINGS (0x20)
+# 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.
Modified: llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp?rev=352505&r1=352504&r2=352505&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/COFF/COFFObjcopy.cpp Tue Jan 29 07:05:38 2019
@@ -177,10 +177,10 @@ static Error handleArgs(const CopyConfig
!Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() ||
!Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
!Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
- !Config.SymbolsToRename.empty() || Config.ExtractDWO ||
- Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates ||
- Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
- Config.Weaken || Config.DecompressDebugSections) {
+ !Config.SetSectionFlags.empty() || !Config.SymbolsToRename.empty() ||
+ Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden ||
+ Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
+ Config.StripSections || Config.Weaken || Config.DecompressDebugSections) {
return createStringError(llvm::errc::invalid_argument,
"Option not supported by llvm-objcopy for COFF");
}
Modified: llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp?rev=352505&r1=352504&r2=352505&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/CopyConfig.cpp Tue Jan 29 07:05:38 2019
@@ -128,6 +128,32 @@ static SectionFlag parseSectionRenameFla
.Default(SectionFlag::SecNone);
}
+static uint64_t parseSectionFlagSet(ArrayRef<StringRef> SectionFlags) {
+ SectionFlag ParsedFlags = SectionFlag::SecNone;
+ for (StringRef Flag : SectionFlags) {
+ SectionFlag ParsedFlag = parseSectionRenameFlag(Flag);
+ if (ParsedFlag == SectionFlag::SecNone)
+ error("Unrecognized section flag '" + Flag +
+ "'. Flags supported for GNU compatibility: alloc, load, noload, "
+ "readonly, debug, code, data, rom, share, contents, merge, "
+ "strings.");
+ ParsedFlags |= ParsedFlag;
+ }
+
+ uint64_t NewFlags = 0;
+ if (ParsedFlags & SectionFlag::SecAlloc)
+ NewFlags |= ELF::SHF_ALLOC;
+ if (!(ParsedFlags & SectionFlag::SecReadonly))
+ NewFlags |= ELF::SHF_WRITE;
+ if (ParsedFlags & SectionFlag::SecCode)
+ NewFlags |= ELF::SHF_EXECINSTR;
+ if (ParsedFlags & SectionFlag::SecMerge)
+ NewFlags |= ELF::SHF_MERGE;
+ if (ParsedFlags & SectionFlag::SecStrings)
+ NewFlags |= ELF::SHF_STRINGS;
+ return NewFlags;
+}
+
static SectionRename parseRenameSectionValue(StringRef FlagValue) {
if (!FlagValue.contains('='))
error("Bad format for --rename-section: missing '='");
@@ -142,34 +168,29 @@ static SectionRename parseRenameSectionV
Old2New.second.split(NameAndFlags, ',');
SR.NewName = NameAndFlags[0];
- if (NameAndFlags.size() > 1) {
- SectionFlag Flags = SectionFlag::SecNone;
- for (size_t I = 1, Size = NameAndFlags.size(); I < Size; ++I) {
- SectionFlag Flag = parseSectionRenameFlag(NameAndFlags[I]);
- if (Flag == SectionFlag::SecNone)
- error("Unrecognized section flag '" + NameAndFlags[I] +
- "'. Flags supported for GNU compatibility: alloc, load, noload, "
- "readonly, debug, code, data, rom, share, contents, merge, "
- "strings.");
- Flags |= Flag;
- }
-
- SR.NewFlags = 0;
- if (Flags & SectionFlag::SecAlloc)
- *SR.NewFlags |= ELF::SHF_ALLOC;
- if (!(Flags & SectionFlag::SecReadonly))
- *SR.NewFlags |= ELF::SHF_WRITE;
- if (Flags & SectionFlag::SecCode)
- *SR.NewFlags |= ELF::SHF_EXECINSTR;
- if (Flags & SectionFlag::SecMerge)
- *SR.NewFlags |= ELF::SHF_MERGE;
- if (Flags & SectionFlag::SecStrings)
- *SR.NewFlags |= ELF::SHF_STRINGS;
- }
+ if (NameAndFlags.size() > 1)
+ SR.NewFlags = parseSectionFlagSet(makeArrayRef(NameAndFlags).drop_front());
return SR;
}
+static SectionFlagsUpdate parseSetSectionFlagValue(StringRef FlagValue) {
+ if (!StringRef(FlagValue).contains('='))
+ error("Bad format for --set-section-flags: missing '='");
+
+ // Initial split: ".foo" = "f1,f2,..."
+ auto Section2Flags = StringRef(FlagValue).split('=');
+ SectionFlagsUpdate SFU;
+ SFU.Name = Section2Flags.first;
+
+ // Flags split: "f1" "f2" ...
+ SmallVector<StringRef, 6> SectionFlags;
+ Section2Flags.second.split(SectionFlags, ',');
+ SFU.NewFlags = parseSectionFlagSet(SectionFlags);
+
+ return SFU;
+}
+
static const StringMap<MachineInfo> ArchMap{
// Name, {EMachine, 64bit, LittleEndian}
{"aarch64", {ELF::EM_AARCH64, true, true}},
@@ -327,6 +348,24 @@ DriverConfig parseObjcopyOptions(ArrayRe
if (!Config.SectionsToRename.try_emplace(SR.OriginalName, SR).second)
error("Multiple renames of section " + SR.OriginalName);
}
+ for (auto Arg : InputArgs.filtered(OBJCOPY_set_section_flags)) {
+ SectionFlagsUpdate SFU = parseSetSectionFlagValue(Arg->getValue());
+ if (!Config.SetSectionFlags.try_emplace(SFU.Name, SFU).second)
+ error("--set-section-flags set multiple times for section " + SFU.Name);
+ }
+ // Prohibit combinations of --set-section-flags when the section name is used
+ // by --rename-section, either as a source or a destination.
+ for (const auto &E : Config.SectionsToRename) {
+ const SectionRename &SR = E.second;
+ if (Config.SetSectionFlags.count(SR.OriginalName))
+ error("--set-section-flags=" + SR.OriginalName +
+ " conflicts with --rename-section=" + SR.OriginalName + "=" +
+ SR.NewName);
+ if (Config.SetSectionFlags.count(SR.NewName))
+ error("--set-section-flags=" + SR.NewName +
+ " conflicts with --rename-section=" + SR.OriginalName + "=" +
+ SR.NewName);
+ }
for (auto Arg : InputArgs.filtered(OBJCOPY_remove_section))
Config.ToRemove.push_back(Arg->getValue());
Modified: llvm/trunk/tools/llvm-objcopy/CopyConfig.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/CopyConfig.h?rev=352505&r1=352504&r2=352505&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/CopyConfig.h (original)
+++ llvm/trunk/tools/llvm-objcopy/CopyConfig.h Tue Jan 29 07:05:38 2019
@@ -37,6 +37,11 @@ struct SectionRename {
Optional<uint64_t> NewFlags;
};
+struct SectionFlagsUpdate {
+ StringRef Name;
+ uint64_t NewFlags;
+};
+
// Configuration for copying/stripping a single file.
struct CopyConfig {
// Main input/output options
@@ -73,6 +78,7 @@ struct CopyConfig {
// Map options
StringMap<SectionRename> SectionsToRename;
+ StringMap<SectionFlagsUpdate> SetSectionFlags;
StringMap<StringRef> SymbolsToRename;
// Boolean options
Modified: llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp?rev=352505&r1=352504&r2=352505&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp (original)
+++ llvm/trunk/tools/llvm-objcopy/ELF/ELFObjcopy.cpp Tue Jan 29 07:05:38 2019
@@ -70,6 +70,17 @@ static bool onlyKeepDWOPred(const Object
return !isDWOSection(Sec);
}
+static uint64_t setSectionFlagsPreserveMask(uint64_t OldFlags,
+ uint64_t NewFlags) {
+ // 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);
+}
+
static ElfType getOutputElfType(const Binary &Bin) {
// Infer output ELF type from the input ELF object
if (isa<ELFObjectFile<ELF32LE>>(Bin))
@@ -484,16 +495,19 @@ static void handleArgs(const CopyConfig
if (Iter != Config.SectionsToRename.end()) {
const SectionRename &SR = Iter->second;
Sec.Name = SR.NewName;
- if (SR.NewFlags.hasValue()) {
- // 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;
- Sec.Flags = (Sec.Flags & PreserveMask) |
- (SR.NewFlags.getValue() & ~PreserveMask);
- }
+ if (SR.NewFlags.hasValue())
+ Sec.Flags =
+ setSectionFlagsPreserveMask(Sec.Flags, SR.NewFlags.getValue());
+ }
+ }
+ }
+
+ if (!Config.SetSectionFlags.empty()) {
+ for (auto &Sec : Obj.sections()) {
+ const auto Iter = Config.SetSectionFlags.find(Sec.Name);
+ if (Iter != Config.SetSectionFlags.end()) {
+ const SectionFlagsUpdate &SFU = Iter->second;
+ Sec.Flags = setSectionFlagsPreserveMask(Sec.Flags, SFU.NewFlags);
}
}
}
Modified: llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td?rev=352505&r1=352504&r2=352505&view=diff
==============================================================================
--- llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td (original)
+++ llvm/trunk/tools/llvm-objcopy/ObjcopyOpts.td Tue Jan 29 07:05:38 2019
@@ -86,6 +86,13 @@ defm add_section
"Make a section named <section> with the contents of <file>.">,
MetaVarName<"section=file">;
+defm set_section_flags
+ : Eq<"set-section-flags",
+ "Set section flags for a given section. Flags supported for GNU "
+ "compatibility: alloc, load, noload, readonly, debug, code, data, "
+ "rom, share, contents, merge, strings.">,
+ MetaVarName<"section=flag1[,flag2,...]">;
+
def strip_all
: Flag<["-", "--"], "strip-all">,
HelpText<
More information about the llvm-commits
mailing list