[clang-tools-extra] [llvm-objcopy] Add --gap-fill and --pad-to options (PR #65515)
via cfe-commits
cfe-commits at lists.llvm.org
Fri Sep 8 14:57:03 PDT 2023
https://github.com/quic-akaryaki updated https://github.com/llvm/llvm-project/pull/65515:
>From 86d3cb57d89036700abf89fa31fe243bc9cb2c6c Mon Sep 17 00:00:00 2001
From: Alexey Karyakin <akaryaki at quicinc.com>
Date: Tue, 5 Sep 2023 15:46:34 -0700
Subject: [PATCH] [llvm-objcopy] Add --gap-fill and --pad-to options
`--gap-fill <value>` fills the gaps between sections with a specified
8-bit value, instead of zero.
`--pad-to <address>` pads the output binary up to the specified load
address, using the 8-bit value from `--gap-fill` or zero.
These options are only supported for ELF inputs and binary outputs.
---
llvm/docs/CommandGuide/llvm-objcopy.rst | 10 ++
llvm/include/llvm/ObjCopy/CommonConfig.h | 2 +
llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp | 2 +-
llvm/lib/ObjCopy/ELF/ELFObject.cpp | 31 +++-
llvm/lib/ObjCopy/ELF/ELFObject.h | 5 +-
.../llvm-objcopy/ELF/gap-fill-order.test | 34 ++++
.../test/tools/llvm-objcopy/ELF/gap-fill.test | 149 ++++++++++++++++++
llvm/test/tools/llvm-objcopy/ELF/pad-to.test | 84 ++++++++++
llvm/tools/llvm-objcopy/ObjcopyOptions.cpp | 25 +++
llvm/tools/llvm-objcopy/ObjcopyOpts.td | 12 ++
10 files changed, 350 insertions(+), 4 deletions(-)
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/gap-fill-order.test
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/gap-fill.test
create mode 100644 llvm/test/tools/llvm-objcopy/ELF/pad-to.test
diff --git a/llvm/docs/CommandGuide/llvm-objcopy.rst b/llvm/docs/CommandGuide/llvm-objcopy.rst
index 0233a4f7b2f045f..6e13cd94b92fdaf 100644
--- a/llvm/docs/CommandGuide/llvm-objcopy.rst
+++ b/llvm/docs/CommandGuide/llvm-objcopy.rst
@@ -324,6 +324,11 @@ them.
Extract the named partition from the output.
+.. option:: --gap-fill <value>
+
+ For binary outputs, fill the gaps between sections with ``<value>`` instead
+ of zero. The value must be an unsigned 8-bit integer.
+
.. option:: --globalize-symbol <symbol>
Mark any defined symbols named ``<symbol>`` as global symbols in the output.
@@ -411,6 +416,11 @@ them.
be the same as the value specified for :option:`--input-target` or the input
file's format if that option is also unspecified.
+.. option:: --pad-to <address>
+
+ For binary outputs, pad the output to the load address ``<address>`` using a value
+ of zero or the value specified by :option:`--gap-fill`.
+
.. option:: --prefix-alloc-sections <prefix>
Add ``<prefix>`` to the front of the names of all allocatable sections in the
diff --git a/llvm/include/llvm/ObjCopy/CommonConfig.h b/llvm/include/llvm/ObjCopy/CommonConfig.h
index e7ce1e6f2c54d75..ebfd404293400ea 100644
--- a/llvm/include/llvm/ObjCopy/CommonConfig.h
+++ b/llvm/include/llvm/ObjCopy/CommonConfig.h
@@ -214,6 +214,8 @@ struct CommonConfig {
// Cached gnu_debuglink's target CRC
uint32_t GnuDebugLinkCRC32;
std::optional<StringRef> ExtractPartition;
+ uint8_t GapFill = 0;
+ std::optional<uint64_t> PadTo;
StringRef SplitDWO;
StringRef SymbolsPrefix;
StringRef AllocSectionsPrefix;
diff --git a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
index 58cb9cb65679b71..37d2af2139e317f 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObjcopy.cpp
@@ -180,7 +180,7 @@ static std::unique_ptr<Writer> createWriter(const CommonConfig &Config,
ElfType OutputElfType) {
switch (Config.OutputFormat) {
case FileFormat::Binary:
- return std::make_unique<BinaryWriter>(Obj, Out);
+ return std::make_unique<BinaryWriter>(Obj, Out, Config);
case FileFormat::IHex:
return std::make_unique<IHexWriter>(Obj, Out);
default:
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.cpp b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
index 697afab2a617b47..770923688832729 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.cpp
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.cpp
@@ -2635,9 +2635,36 @@ template <class ELFT> Error ELFWriter<ELFT>::finalize() {
}
Error BinaryWriter::write() {
- for (const SectionBase &Sec : Obj.allocSections())
+ SmallVector<const SectionBase *, 30> LoadableSections;
+ for (const SectionBase &Sec : Obj.allocSections()) {
+ if ((Sec.Flags & SectionFlag::SecLoad) && Sec.Type != SHT_NOBITS)
+ LoadableSections.push_back(&Sec);
+ }
+
+ if (LoadableSections.empty())
+ return Error::success();
+
+ llvm::stable_sort(LoadableSections,
+ [](const SectionBase *LHS, const SectionBase *RHS) {
+ return LHS->Offset < RHS->Offset;
+ });
+
+ assert(LoadableSections.front()->Offset == 0);
+
+ for (unsigned i = 0; i != LoadableSections.size(); ++i) {
+ const SectionBase &Sec = *LoadableSections[i];
if (Error Err = Sec.accept(*SecWriter))
return Err;
+ if (GapFill == 0)
+ continue;
+ uint64_t PadOffset = (i < LoadableSections.size() - 1)
+ ? LoadableSections[i + 1]->Offset
+ : Buf->getBufferSize();
+ assert(PadOffset <= Buf->getBufferSize());
+ if (Sec.Offset + Sec.Size < PadOffset)
+ std::fill(Buf->getBufferStart() + Sec.Offset + Sec.Size,
+ Buf->getBufferStart() + PadOffset, GapFill);
+ }
// TODO: Implement direct writing to the output stream (without intermediate
// memory buffer Buf).
@@ -2663,7 +2690,7 @@ Error BinaryWriter::finalize() {
// file size. This might not be the same as the offset returned by
// layoutSections, because we want to truncate the last segment to the end of
// its last non-empty section, to match GNU objcopy's behaviour.
- TotalSize = 0;
+ TotalSize = PadTo && PadTo.value() > MinAddr ? PadTo.value() - MinAddr : 0;
for (SectionBase &Sec : Obj.allocSections())
if (Sec.Type != SHT_NOBITS && Sec.Size > 0) {
Sec.Offset = Sec.Addr - MinAddr;
diff --git a/llvm/lib/ObjCopy/ELF/ELFObject.h b/llvm/lib/ObjCopy/ELF/ELFObject.h
index 89a03b3fe0ee354..bf6fa32908e3dcf 100644
--- a/llvm/lib/ObjCopy/ELF/ELFObject.h
+++ b/llvm/lib/ObjCopy/ELF/ELFObject.h
@@ -357,6 +357,8 @@ template <class ELFT> class ELFWriter : public Writer {
class BinaryWriter : public Writer {
private:
+ const uint8_t GapFill;
+ const std::optional<uint64_t> PadTo;
std::unique_ptr<BinarySectionWriter> SecWriter;
uint64_t TotalSize = 0;
@@ -365,7 +367,8 @@ class BinaryWriter : public Writer {
~BinaryWriter() {}
Error finalize() override;
Error write() override;
- BinaryWriter(Object &Obj, raw_ostream &Out) : Writer(Obj, Out) {}
+ BinaryWriter(Object &Obj, raw_ostream &Out, const CommonConfig &Config)
+ : Writer(Obj, Out), GapFill(Config.GapFill), PadTo(Config.PadTo) {}
};
class IHexWriter : public Writer {
diff --git a/llvm/test/tools/llvm-objcopy/ELF/gap-fill-order.test b/llvm/test/tools/llvm-objcopy/ELF/gap-fill-order.test
new file mode 100644
index 000000000000000..4b0ecad5cd3bfa4
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/gap-fill-order.test
@@ -0,0 +1,34 @@
+# RUN: yaml2obj %s >%t
+
+# Test gap fill with all allocatable output sections
+# RUN: llvm-objcopy -O binary --gap-fill=0xe9 %t %t-filled
+# RUN: od -v -Ax -t x1 %t-filled | FileCheck --match-full-lines %s
+# CHECK: 000000 aa bb cc dd e9 e9 e9 e9 11 22 33 44
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS32
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_HEXAGON
+Sections:
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+ Address: 0x0104
+ AddressAlign: 0x0001
+ Size: 4
+ - Name: .section1
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+ Address: 0x0108
+ AddressAlign: 0x0001
+ Content: '11223344'
+ - Name: .section3
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_WRITE ]
+ Address: 0x0100
+ AddressAlign: 0x0001
+ Content: 'AABBCCDD'
+...
+
diff --git a/llvm/test/tools/llvm-objcopy/ELF/gap-fill.test b/llvm/test/tools/llvm-objcopy/ELF/gap-fill.test
new file mode 100644
index 000000000000000..4edeb3905060541
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/gap-fill.test
@@ -0,0 +1,149 @@
+# RUN: yaml2obj %s > %t
+
+## Verify section headers before we perform several testings.
+# RUN: llvm-readelf -S %t | FileCheck %s --check-prefix=ORG-SHDR
+# ORG-SHDR: Section Headers:
+# ORG-SHDR: [Nr] Name Type Address Off Size ES Flg Lk Inf Al
+# ORG-SHDR: [ 0] NULL 0000000000000000 000000 000000 00 0 0 0
+# ORG-SHDR: [ 1] .nogap PROGBITS 0000000000000102 000042 000006 00 A 0 0 1
+# ORG-SHDR: [ 2] .gap1 PROGBITS 0000000000000108 000048 000007 00 AX 0 0 1
+# ORG-SHDR: [ 3] .gap2 PROGBITS 0000000000000110 000050 000004 00 A 0 0 1
+# ORG-SHDR: [ 4] .nobit_tbss NOBITS 0000000000000180 000058 000018 00 WAT 0 0 8
+# ORG-SHDR: [ 5] .foo PROGBITS 0000000000000184 00005c 000004 00 WA 0 0 1
+# ORG-SHDR: [ 6] .nobit_bss NOBITS 000000000000018a 000060 000008 00 WA 0 0 1
+
+# RUN: not llvm-objcopy --gap-fill 1 %t 2>&1 | FileCheck %s --check-prefix=NOT-BINARY
+# NOT-BINARY: error: '--gap-fill' is only supported for binary output
+
+# RUN: not llvm-objcopy -O binary --gap-fill %t 2>&1 | FileCheck %s --check-prefix=EMPTY
+# EMPTY: no input file specified
+
+# RUN: not llvm-objcopy -O binary --gap-fill= %t 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
+# BAD-FORMAT: bad number for --gap-fill:
+
+# RUN: not llvm-objcopy -O binary --gap-fill=x %t 2>&1 | FileCheck %s --check-prefix=BAD-INPUT
+# BAD-INPUT: bad number for --gap-fill: x
+
+# RUN: not llvm-objcopy -O binary --gap-fill=0x1G %t 2>&1 | FileCheck %s --check-prefix=BAD-INPUT2
+# BAD-INPUT2: bad number for --gap-fill: 0x1G
+
+# RUN: not llvm-objcopy -O binary --gap-fill=0x1122 %t %t-val16 2>&1 | FileCheck %s --check-prefix=BAD-INPUT3
+# BAD-INPUT3: bad number for --gap-fill: 0x1122
+
+# Test no gap fill gap fill with all allocatable output sections
+# RUN: llvm-objcopy -O binary %t %t-default
+# RUN: od -v -Ax -t x1 %t-default | FileCheck %s --check-prefix=DEFAULT
+# DEFAULT: 000000 ee ff 11 22 33 44 aa bb cc dd fe dc ba 00 a1 b2
+# DEFAULT-NEXT: 000010 c3 d4 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000040 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000050 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000060 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000070 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000080 00 00 89 ab cd ef
+# DEFAULT-NEXT: 000086
+
+# Test gap fill with all allocatable output sections
+# RUN: llvm-objcopy -O binary --gap-fill=0xe9 %t %t-filled
+# RUN: od -v -Ax -t x1 %t-filled | FileCheck %s --check-prefix=FULL
+# FULL: 000000 ee ff 11 22 33 44 aa bb cc dd fe dc ba e9 a1 b2
+# FULL-NEXT: 000010 c3 d4 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000020 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000030 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000040 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000050 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000060 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000070 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FULL-NEXT: 000080 e9 e9 89 ab cd ef
+# FULL-NEXT: 000086
+
+# Test gap fill with the last section removed, should be truncated
+# RUN: llvm-objcopy -O binary --gap-fill=0xe9 --remove-section=.foo %t %t-filled
+# RUN: od -v -Ax -t x1 %t-filled | FileCheck %s --check-prefix=REMOVE-LAST-SECTION
+# REMOVE-LAST-SECTION: 000000 ee ff 11 22 33 44 aa bb cc dd fe dc ba e9 a1 b2
+# REMOVE-LAST-SECTION-NEXT: 000010 c3 d4
+# REMOVE-LAST-SECTION-NEXT: 000012
+
+# Test gap fill with the middle section removed, should be filled
+# RUN: llvm-objcopy -O binary --gap-fill=0xe9 --remove-section=.gap2 %t %t-filled
+# RUN: od -v -Ax -t x1 %t-filled | FileCheck %s --check-prefix=REMOVE-MIDDLE-SECTION
+# REMOVE-MIDDLE-SECTION: 000000 ee ff 11 22 33 44 aa bb cc dd fe dc ba e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000010 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000020 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000030 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000040 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000050 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000060 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000070 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-MIDDLE-SECTION-NEXT: 000080 e9 e9 89 ab cd ef
+# REMOVE-MIDDLE-SECTION-NEXT: 000086
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .space1
+ Type: Fill
+ Pattern: 'ABCD'
+ Size: 0x2
+ - Name: .nogap
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0102
+ AddressAlign: 0x0001
+ Size: 0x6
+ Content: 'EEFF11223344'
+ - Name: .gap1
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC, SHF_EXECINSTR ]
+ Address: 0x0108
+ AddressAlign: 0x0001
+ Content: 'AABBCCDDFEDCBA'
+ - Name: .space2
+ Type: Fill
+ Pattern: 'DC'
+ Size: 1
+ - Name: .gap2
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0110
+ AddressAlign: 0x0001
+ Content: 'A1B2C3D4'
+ - Name: .space3
+ Type: Fill
+ Pattern: 'FE'
+ Size: 0x1
+ - Name: .nobit_tbss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC, SHF_TLS ]
+ Address: 0x0180
+ AddressAlign: 0x0008
+ Size: 0x0018
+ - Name: .space4 # in the different segment
+ Type: Fill
+ Pattern: '01234567'
+ Size: 0x4
+ - Name: .foo
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x0184
+ AddressAlign: 0x0001
+ Content: '89ABCDEF'
+ - Name: .nobit_bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x018A
+ AddressAlign: 0x0001
+ Size: 0x0008
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0001
+ EntSize: 0x0001
+ Content: 4743433A
+
+...
diff --git a/llvm/test/tools/llvm-objcopy/ELF/pad-to.test b/llvm/test/tools/llvm-objcopy/ELF/pad-to.test
new file mode 100644
index 000000000000000..fb777ad750dbfe0
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/ELF/pad-to.test
@@ -0,0 +1,84 @@
+# RUN: yaml2obj %s > %t
+
+# baseline, no padding
+# RUN: llvm-objcopy -O binary %t %t.bin
+
+# RUN: not llvm-objcopy --pad-to=1 %t 2>&1 | FileCheck %s --check-prefix=NOT-BINARY
+# NOT-BINARY: error: '--pad-to' is only supported for binary output
+
+# RUN: not llvm-objcopy -O binary --pad-to= %t 2>&1 | FileCheck %s --check-prefix=BAD-FORMAT
+# BAD-FORMAT: bad address for --pad-to:
+
+# RUN: not llvm-objcopy -O binary --pad-to=x %t 2>&1 | FileCheck %s --check-prefix=BAD-INPUT
+# BAD-INPUT: bad address for --pad-to: x
+
+# RUN: not llvm-objcopy -O binary --pad-to=0x1G %t 2>&1 | FileCheck %s --check-prefix=BAD-INPUT2
+# BAD-INPUT2: bad address for --pad-to: 0x1G
+
+# RUN: not llvm-objcopy -O binary --pad-to=0x112233445566778899 %t 2>&1 | FileCheck %s --check-prefix=BAD-NUMBER
+# BAD-NUMBER: bad address for --pad-to: 0x112233445566778899
+
+# Pad to a address smaller than the binary size
+# RUN: llvm-objcopy -O binary --pad-to=0x20 %t %t-p1
+# RUN: cmp %t.bin %t-p1
+# RUN: llvm-objcopy -O binary --pad-to=0x200 %t %t-p2
+# RUN: cmp %t.bin %t-p2
+
+## Pad all allocatable sections to a valid address.
+# RUN: llvm-objcopy -O binary --pad-to=0x218 %t %t-pad-default
+# RUN: od -v -Ax -t x1 %t-pad-default | FileCheck %s --check-prefix=DEFAULT
+# DEFAULT: 000000 11 22 33 44 55 66 00 00 00 00 00 00 00 00 00 00
+# DEFAULT-NEXT: 000010 77 88 99 aa 00 00 00 00
+# DEFAULT-NEXT: 000018
+
+## Pad all allocatable sections to a valid address, using --gap-fill.
+# RUN: llvm-objcopy -O binary --pad-to=0x218 --gap-fill=0xe9 %t %t-pad-fill
+# RUN: od -v -Ax -t x1 %t-pad-fill | FileCheck %s --check-prefix=FILL
+# FILL: 000000 11 22 33 44 55 66 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# FILL-NEXT: 000010 77 88 99 aa e9 e9 e9 e9
+# FILL-NEXT: 000018
+
+# Test gap fill with a section removed
+# RUN: llvm-objcopy -O binary --pad-to=0x218 --gap-fill=0xe9 --remove-section=.section2 %t %t-filled
+# RUN: od -v -Ax -t x1 %t-filled | FileCheck %s --check-prefix=REMOVE-SECTION
+# REMOVE-SECTION: 000000 11 22 33 44 55 66 e9 e9 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-SECTION-NEXT: 000010 e9 e9 e9 e9 e9 e9 e9 e9
+# REMOVE-SECTION-NEXT: 000018
+
+--- !ELF
+FileHeader:
+ Class: ELFCLASS64
+ Data: ELFDATA2LSB
+ Type: ET_EXEC
+ Machine: EM_X86_64
+Sections:
+ - Name: .section1
+ Type: SHT_PROGBITS
+ Flags: [ SHF_ALLOC ]
+ Address: 0x0200
+ AddressAlign: 0x0001
+ Size: 0x6
+ Content: '112233445566'
+ - Name: .space
+ Type: Fill
+ Pattern: '01234567'
+ Size: 0x4
+ - Name: .section2
+ Type: SHT_PROGBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x0210
+ AddressAlign: 0x0001
+ Content: '778899aa'
+ - Name: .bss
+ Type: SHT_NOBITS
+ Flags: [ SHF_WRITE, SHF_ALLOC ]
+ Address: 0x0220
+ AddressAlign: 0x0001
+ Size: 0x0008
+ - Name: .comment
+ Type: SHT_PROGBITS
+ Flags: [ SHF_MERGE, SHF_STRINGS ]
+ AddressAlign: 0x0001
+ EntSize: 0x0001
+ Content: ''
+...
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
index d33adb0b6a3e478..b4104053e2b3f91 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
+++ b/llvm/tools/llvm-objcopy/ObjcopyOptions.cpp
@@ -738,6 +738,31 @@ objcopy::parseObjcopyOptions(ArrayRef<const char *> RawArgsArr,
if (auto Arg = InputArgs.getLastArg(OBJCOPY_extract_partition))
Config.ExtractPartition = Arg->getValue();
+ if (const auto *A = InputArgs.getLastArg(OBJCOPY_gap_fill)) {
+ if (Config.OutputFormat != FileFormat::Binary)
+ return createStringError(
+ errc::invalid_argument,
+ "'--gap-fill' is only supported for binary output");
+ ErrorOr<uint8_t> Val = getAsInteger<uint8_t>(A->getValue());
+ if (!Val)
+ return createStringError(Val.getError(), "bad number for --gap-fill: %s",
+ A->getValue());
+ Config.GapFill = Val.get();
+ } else
+ Config.GapFill = 0; // The value of zero is equivalent to no fill.
+
+ if (const auto *A = InputArgs.getLastArg(OBJCOPY_pad_to)) {
+ if (Config.OutputFormat != FileFormat::Binary)
+ return createStringError(
+ errc::invalid_argument,
+ "'--pad-to' is only supported for binary output");
+ ErrorOr<uint64_t> Addr = getAsInteger<uint64_t>(A->getValue());
+ if (!Addr)
+ return createStringError(Addr.getError(), "bad address for --pad-to: %s",
+ A->getValue());
+ Config.PadTo = *Addr;
+ }
+
for (auto *Arg : InputArgs.filtered(OBJCOPY_redefine_symbol)) {
if (!StringRef(Arg->getValue()).contains('='))
return createStringError(errc::invalid_argument,
diff --git a/llvm/tools/llvm-objcopy/ObjcopyOpts.td b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
index ea8828637222ac6..556f84e3154fe06 100644
--- a/llvm/tools/llvm-objcopy/ObjcopyOpts.td
+++ b/llvm/tools/llvm-objcopy/ObjcopyOpts.td
@@ -230,3 +230,15 @@ defm add_symbol
defm update_section
: Eq<"update-section", "Replace the contents of section <name> with contents from a file <file>">,
MetaVarName<"name=file">;
+
+defm gap_fill
+ : Eq<"gap-fill", "Fill the gaps between sections with <value> instead of zero. "
+ "<value> must be an unsigned 8-bit integer. "
+ "This option is only supported for ELF inputs and binary outputs.">,
+ MetaVarName<"value">;
+
+defm pad_to
+ : Eq<"pad-to", "Pad the output to the load address <address>, using a value "
+ "of zero or the value specified by :option:`--gap-fill`"
+ "This option is only supported for ELF inputs and binary outputs.">,
+ MetaVarName<"address">;
More information about the cfe-commits
mailing list