[llvm] f69eba0 - [llvm-objcopy][COFF] Add support for --set-section-flags
Sergey Dmitriev via llvm-commits
llvm-commits at lists.llvm.org
Fri Jan 24 07:13:13 PST 2020
Author: Sergey Dmitriev
Date: 2020-01-24T07:12:55-08:00
New Revision: f69eba07726a9fe084812aa224309d62c4bdd2e4
URL: https://github.com/llvm/llvm-project/commit/f69eba07726a9fe084812aa224309d62c4bdd2e4
DIFF: https://github.com/llvm/llvm-project/commit/f69eba07726a9fe084812aa224309d62c4bdd2e4.diff
LOG: [llvm-objcopy][COFF] Add support for --set-section-flags
Reviewers: jhenderson, MaskRay, alexshap, rupprecht, mstorsjo
Reviewed By: jhenderson
Subscribers: abrachet, llvm-commits
Tags: #llvm
Differential Revision: https://reviews.llvm.org/D73107
Added:
llvm/test/tools/llvm-objcopy/COFF/set-section-flags.test
Modified:
llvm/docs/CommandGuide/llvm-objcopy.rst
llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
Removed:
################################################################################
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index d5e9987df143..576921435fbd 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -130,6 +130,45 @@ multiple file formats.
Set the alignment of section ``<section>`` to `<align>``. Can be specified
multiple times to update multiple sections.
+.. option:: --set-section-flags <section>=<flag>[,<flag>,...]
+
+ Set section properties in the output of section ``<section>`` based on the
+ specified ``<flag>`` values. Can be specified multiple times to update multiple
+ sections.
+
+ Supported flag names are `alloc`, `load`, `noload`, `readonly`, `exclude`,
+ `debug`, `code`, `data`, `rom`, `share`, `contents`, `merge` and `strings`. Not
+ all flags are meaningful for all object file formats.
+
+ For ELF objects, the flags have the following effects:
+
+ - `alloc` = add the `SHF_ALLOC` flag.
+ - `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.
+ - `code` = add the `SHF_EXECINSTR` flag.
+ - `merge` = add the `SHF_MERGE` flag.
+ - `strings` = add the `SHF_STRINGS` flag.
+ - `contents` = if the section has `SHT_NOBITS` type, mark it as a `SHT_PROGBITS`
+ section.
+
+ For COFF objects, the flags have the following effects:
+
+ - `alloc` = add the `IMAGE_SCN_CNT_UNINITIALIZED_DATA` and `IMAGE_SCN_MEM_READ`
+ flags, unless the `load` flag is specified.
+ - `noload` = add the `IMAGE_SCN_LNK_REMOVE` and `IMAGE_SCN_MEM_READ` flags.
+ - `readonly` = if this flag is not specified, add the `IMAGE_SCN_MEM_WRITE`
+ flag.
+ - `exclude` = add the `IMAGE_SCN_LNK_REMOVE` and `IMAGE_SCN_MEM_READ` flags.
+ - `debug` = add the `IMAGE_SCN_CNT_INITIALIZED_DATA`,
+ `IMAGE_SCN_MEM_DISCARDABLE` and `IMAGE_SCN_MEM_READ` flags.
+ - `code` = add the `IMAGE_SCN_CNT_CODE`, `IMAGE_SCN_MEM_EXECUTE` and
+ `IMAGE_SCN_MEM_READ` flags.
+ - `data` = add the `IMAGE_SCN_CNT_INITIALIZED_DATA` and `IMAGE_SCN_MEM_READ`
+ flags.
+ - `share` = add the `IMAGE_SCN_MEM_SHARED` and `IMAGE_SCN_MEM_READ` flags.
+
.. option:: --strip-all-gnu
Remove all symbols, debug sections and relocations from the output. This option
@@ -399,28 +438,6 @@ them.
specified ``<flag>`` values. See :option:`--set-section-flags` for a list of
supported flags. Can be specified multiple times to rename multiple sections.
-.. option:: --set-section-flags <section>=<flag>[,<flag>,...]
-
- Set section properties in the output of section ``<section>`` based on the
- specified ``<flag>`` values. Can be specified multiple times to update multiple
- sections.
-
- Following is a list of supported flags and their effects:
-
- - `alloc` = add the `SHF_ALLOC` flag.
- - `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.
- - `code` = add the `SHF_EXECINSTR` flag.
- - `merge` = add the `SHF_MERGE` flag.
- - `strings` = add the `SHF_STRINGS` flag.
- - `contents` = if the section has `SHT_NOBITS` type, mark it as a `SHT_PROGBITS`
- section.
-
- The following flags are also accepted, but are ignored for GNU compatibility:
- `noload`, `debug`, `data`, `rom`, `share`.
-
.. option:: --set-start-addr <addr>
Set the start address of the output to ``<addr>``. Overrides any previously
diff --git a/llvm/test/tools/llvm-objcopy/COFF/set-section-flags.test b/llvm/test/tools/llvm-objcopy/COFF/set-section-flags.test
new file mode 100644
index 000000000000..37bd3d5f1325
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/COFF/set-section-flags.test
@@ -0,0 +1,82 @@
+# RUN: yaml2obj %s -o %t
+
+## Single flag 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,UNINITDATA,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=load %t %t.load
+# RUN: llvm-readobj --sections %t.load | FileCheck %s --check-prefixes=CHECK,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=noload %t %t.noload
+# RUN: llvm-readobj --sections %t.noload | FileCheck %s --check-prefixes=CHECK,READ,WRITE,REMOVE
+# RUN: llvm-objcopy --set-section-flags=.foo=readonly %t %t.readonly
+# RUN: llvm-readobj --sections %t.readonly | FileCheck %s --check-prefixes=CHECK,READ
+# RUN: llvm-objcopy --set-section-flags=.foo=exclude %t %t.exclude
+# RUN: llvm-readobj --sections %t.exclude | FileCheck %s --check-prefixes=CHECK,READ,WRITE,REMOVE
+# RUN: llvm-objcopy --set-section-flags=.foo=debug %t %t.debug
+# RUN: llvm-readobj --sections %t.debug | FileCheck %s --check-prefixes=CHECK,INITDATA,DISCARDABLE,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=code %t %t.code
+# RUN: llvm-readobj --sections %t.code | FileCheck %s --check-prefixes=CHECK,CODE,EXECUTE,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=data %t %t.data
+# RUN: llvm-readobj --sections %t.data | FileCheck %s --check-prefixes=CHECK,INITDATA,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=rom %t %t.rom
+# RUN: llvm-readobj --sections %t.rom | FileCheck %s --check-prefixes=CHECK,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=contents %t %t.contents
+# RUN: llvm-readobj --sections %t.contents | FileCheck %s --check-prefixes=CHECK,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=merge %t %t.merge
+# RUN: llvm-readobj --sections %t.merge | FileCheck %s --check-prefixes=CHECK,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=strings %t %t.strings
+# RUN: llvm-readobj --sections %t.strings | FileCheck %s --check-prefixes=CHECK,READ,WRITE
+# RUN: llvm-objcopy --set-section-flags=.foo=share %t %t.share
+# RUN: llvm-readobj --sections %t.share | FileCheck %s --check-prefixes=CHECK,READ,SHARED,WRITE
+
+## Multiple flags:
+# RUN: llvm-objcopy --set-section-flags=.foo=alloc,readonly,share %t %t.alloc_ro_share
+# RUN: llvm-readobj --sections %t.alloc_ro_share | FileCheck %s --check-prefixes=CHECK,UNINITDATA,READ,SHARED
+# 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,CODE,UNINITDATA,EXECUTE,READ,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
+
+## Upper-case flags:
+# RUN: llvm-objcopy --set-section-flags=.foo=ALLOC,LOAD,NOLOAD,READONLY,DEBUG,CODE,DATA,ROM,CONTENTS,MERGE,STRINGS,SHARE %t %t.upper
+# RUN: llvm-readobj --sections %t.upper | FileCheck %s --check-prefixes=CHECK,CODE,INITDATA,REMOVE,DISCARDABLE,EXECUTE,READ,SHARED
+
+## Mixed-case flags:
+# RUN: llvm-objcopy --set-section-flags=.foo=aLlOc,LoAd,NoLoad,rEAdONly,Debug,codE,DaTa,rOm,CoNtEnTs,mErGe,sTRINGs,SharE %t %t.mixed
+# RUN: llvm-readobj --sections %t.mixed | FileCheck %s --check-prefixes=CHECK,CODE,INITDATA,REMOVE,DISCARDABLE,EXECUTE,READ,SHARED
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .foo
+ Characteristics: [ ]
+ Alignment: 4
+symbols:
+...
+
+# CHECK: Name: .foo
+# CHECK: Characteristics [
+# CHECK-NEXT: IMAGE_SCN_ALIGN_4BYTES
+# CODE-NEXT: IMAGE_SCN_CNT_CODE
+# INITDATA-NEXT: IMAGE_SCN_CNT_INITIALIZED_DATA
+# UNINITDATA-NEXT: IMAGE_SCN_CNT_UNINITIALIZED_DATA
+# REMOVE-NEXT: IMAGE_SCN_LNK_REMOVE
+# DISCARDABLE-NEXT: IMAGE_SCN_MEM_DISCARDABLE
+# EXECUTE-NEXT: IMAGE_SCN_MEM_EXECUTE
+# READ-NEXT: IMAGE_SCN_MEM_READ
+# SHARED-NEXT: IMAGE_SCN_MEM_SHARED
+# WRITE-NEXT: IMAGE_SCN_MEM_WRITE
+# 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, exclude, debug, code, data, rom, share, contents, merge, strings
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
index b172fae527eb..0a3c40874251 100644
--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
@@ -89,6 +89,43 @@ static void addGnuDebugLink(Object &Obj, StringRef DebugLinkFile) {
IMAGE_SCN_MEM_DISCARDABLE);
}
+static void setSectionFlags(Section &Sec, SectionFlag AllFlags) {
+ // Need to preserve alignment flags.
+ const uint32_t PreserveMask =
+ IMAGE_SCN_ALIGN_1BYTES | IMAGE_SCN_ALIGN_2BYTES | IMAGE_SCN_ALIGN_4BYTES |
+ IMAGE_SCN_ALIGN_8BYTES | IMAGE_SCN_ALIGN_16BYTES |
+ IMAGE_SCN_ALIGN_32BYTES | IMAGE_SCN_ALIGN_64BYTES |
+ IMAGE_SCN_ALIGN_128BYTES | IMAGE_SCN_ALIGN_256BYTES |
+ IMAGE_SCN_ALIGN_512BYTES | IMAGE_SCN_ALIGN_1024BYTES |
+ IMAGE_SCN_ALIGN_2048BYTES | IMAGE_SCN_ALIGN_4096BYTES |
+ IMAGE_SCN_ALIGN_8192BYTES;
+
+ // Setup new section characteristics based on the flags provided in command
+ // line.
+ uint32_t NewCharacteristics =
+ (Sec.Header.Characteristics & PreserveMask) | IMAGE_SCN_MEM_READ;
+
+ if ((AllFlags & SectionFlag::SecAlloc) && !(AllFlags & SectionFlag::SecLoad))
+ NewCharacteristics |= IMAGE_SCN_CNT_UNINITIALIZED_DATA;
+ if (AllFlags & SectionFlag::SecNoload)
+ NewCharacteristics |= IMAGE_SCN_LNK_REMOVE;
+ if (!(AllFlags & SectionFlag::SecReadonly))
+ NewCharacteristics |= IMAGE_SCN_MEM_WRITE;
+ if (AllFlags & SectionFlag::SecDebug)
+ NewCharacteristics |=
+ IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE;
+ if (AllFlags & SectionFlag::SecCode)
+ NewCharacteristics |= IMAGE_SCN_CNT_CODE | IMAGE_SCN_MEM_EXECUTE;
+ if (AllFlags & SectionFlag::SecData)
+ NewCharacteristics |= IMAGE_SCN_CNT_INITIALIZED_DATA;
+ if (AllFlags & SectionFlag::SecShare)
+ NewCharacteristics |= IMAGE_SCN_MEM_SHARED;
+ if (AllFlags & SectionFlag::SecExclude)
+ NewCharacteristics |= IMAGE_SCN_LNK_REMOVE;
+
+ Sec.Header.Characteristics = NewCharacteristics;
+}
+
static Error handleArgs(const CopyConfig &Config, Object &Obj) {
// Perform the actual section removals.
Obj.removeSections([&Config](const Section &Sec) {
@@ -178,6 +215,13 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
return false;
});
+ if (!Config.SetSectionFlags.empty())
+ for (Section &Sec : Obj.getMutableSections()) {
+ const auto It = Config.SetSectionFlags.find(Sec.Name);
+ if (It != Config.SetSectionFlags.end())
+ setSectionFlags(Sec, It->second.NewFlags);
+ }
+
for (const auto &Flag : Config.AddSection) {
StringRef SecName, FileName;
std::tie(SecName, FileName) = Flag.split("=");
@@ -205,10 +249,10 @@ static Error handleArgs(const CopyConfig &Config, Object &Obj) {
!Config.SymbolsToGlobalize.empty() || !Config.SymbolsToKeep.empty() ||
!Config.SymbolsToLocalize.empty() || !Config.SymbolsToWeaken.empty() ||
!Config.SymbolsToKeepGlobal.empty() || !Config.SectionsToRename.empty() ||
- !Config.SetSectionAlignment.empty() || !Config.SetSectionFlags.empty() ||
- Config.ExtractDWO || Config.KeepFileSymbols || Config.LocalizeHidden ||
- Config.PreserveDates || Config.StripDWO || Config.StripNonAlloc ||
- Config.StripSections || Config.Weaken || Config.DecompressDebugSections ||
+ !Config.SetSectionAlignment.empty() || Config.ExtractDWO ||
+ Config.KeepFileSymbols || Config.LocalizeHidden || Config.PreserveDates ||
+ Config.StripDWO || Config.StripNonAlloc || Config.StripSections ||
+ Config.Weaken || Config.DecompressDebugSections ||
Config.DiscardMode == DiscardType::Locals ||
!Config.SymbolsToAdd.empty() || Config.EntryExpr) {
return createStringError(llvm::errc::invalid_argument,
More information about the llvm-commits
mailing list