forked from OSchip/llvm-project
[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
This commit is contained in:
parent
76fa5d50f3
commit
f69eba0772
|
@ -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
|
||||
|
|
|
@ -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
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue