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 <akary...@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">; _______________________________________________ cfe-commits mailing list cfe-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits