[llvm] 85381e6 - [llvm-objcopy][COFF] Implement --update-section
Alex Brachet via llvm-commits
llvm-commits at lists.llvm.org
Thu Feb 3 13:31:16 PST 2022
Author: Alex Brachet
Date: 2022-02-03T21:30:42Z
New Revision: 85381e67a9571f6ba27fc7f448b523f6ec2eb312
URL: https://github.com/llvm/llvm-project/commit/85381e67a9571f6ba27fc7f448b523f6ec2eb312
DIFF: https://github.com/llvm/llvm-project/commit/85381e67a9571f6ba27fc7f448b523f6ec2eb312.diff
LOG: [llvm-objcopy][COFF] Implement --update-section
Reviewed By: jhenderson, MaskRay
Differential Revision: https://reviews.llvm.org/D118189
Added:
llvm/test/tools/llvm-objcopy/COFF/update-section.test
Modified:
llvm/test/tools/llvm-objcopy/ELF/update-section.test
llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
llvm/tools/llvm-objcopy/COFF/Object.h
llvm/tools/llvm-objcopy/ELF/Object.cpp
Removed:
################################################################################
diff --git a/llvm/test/tools/llvm-objcopy/COFF/update-section.test b/llvm/test/tools/llvm-objcopy/COFF/update-section.test
new file mode 100644
index 0000000000000..6ea742d8819ee
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/COFF/update-section.test
@@ -0,0 +1,72 @@
+# RUN: echo -n AAAB > %t.
diff
+# RUN: echo -n AAA > %t.smaller
+# RUN: echo -n AAAAA > %t.larger
+
+# RUN: yaml2obj %s -o %t
+
+# RUN: llvm-objcopy --update-section=.text=%t.
diff %t - | llvm-readobj -S -x .text - | FileCheck %s
+# CHECK: Section {
+# CHECK-NEXT: Number: 1
+# CHECK-NEXT: Name: .text
+# CHECK-NOT: }
+# CHECK: RawDataSize: 4
+# CHECK: Hex dump of section '.text':
+# CHECK-NEXT: 0x00000000 41414142 AAAB
+
+# RUN: llvm-objcopy --update-section=.text=%t.smaller %t - | llvm-readobj -S -x .text - | FileCheck %s --check-prefix=SMALLER
+# SMALLER: Section {
+# SMALLER-NEXT: Number: 1
+# SMALLER-NEXT: Name: .text
+# SMALLER-NOT: }
+# SMALLER: RawDataSize: 3
+# SMALLER: Hex dump of section '.text':
+# SMALLER-NEXT: 0x00000000 414141 AAA
+
+# RUN: llvm-objcopy --update-section=.text=%t.
diff --update-section=.other=%t.
diff %t - | \
+# RUN: llvm-readobj -S -x .text -x .other - | FileCheck %s --check-prefix=MULTIPLE
+# MULTIPLE: Section {
+# MULTIPLE-NEXT: Number: 1
+# MULTIPLE-NEXT: Name: .text
+# MULTIPLE-NOT: }
+# MULTIPLE: RawDataSize: 4
+# MULTIPLE: Section {
+# MULTIPLE-NEXT: Number: 2
+# MULTIPLE-NEXT: Name: .other
+# MULTIPLE-NOT: }
+# MULTIPLE: RawDataSize: 4
+# MULTIPLE: Hex dump of section '.text':
+# MULTIPLE-NEXT: 0x00000000 41414142 AAAB
+# MULTIPLE: Hex dump of section '.other':
+# MULTIPLE-NEXT: 0x00000000 41414142 AAAB
+
+# RUN: not llvm-objcopy --update-section=.text=%t.larger %t /dev/null 2>&1 | FileCheck %s --check-prefix=TOO-LARGE
+# TOO-LARGE: error: {{.*}}new section cannot be larger than previous section
+
+# RUN: not llvm-objcopy --update-section=.bss=%t.
diff %t /dev/null 2>&1 | FileCheck %s --check-prefix=NO-CONTENTS
+# NO-CONTENTS: error: {{.*}}section '.bss' cannot be updated because it does not have contents
+
+# RUN: not llvm-objcopy --update-section=.text=%t.noexist %t /dev/null 2>&1 | \
+# RUN: FileCheck %s --check-prefix=NOENT -DENOENT=%errc_ENOENT
+# NOENT: error: {{.*}}: [[ENOENT]]
+
+# RUN: not llvm-objcopy --update-section=.noexist=%t.
diff %t /dev/null 2>&1 | FileCheck %s --check-prefix=NO-SECTION
+# NO-SECTION: error: {{.*}}could not find section with name '.noexist'
+
+--- !COFF
+header:
+ Machine: IMAGE_FILE_MACHINE_AMD64
+ Characteristics: [ ]
+sections:
+ - Name: .text
+ Characteristics: [ ]
+ Alignment: 4
+ SectionData: '41414141'
+ - Name: .other
+ Characteristics: [ ]
+ Alignment: 4
+ SectionData: '42424242'
+ - Name: .bss
+ Characteristics: [ IMAGE_SCN_CNT_UNINITIALIZED_DATA ]
+ SizeOfRawData: 0
+symbols:
+...
diff --git a/llvm/test/tools/llvm-objcopy/ELF/update-section.test b/llvm/test/tools/llvm-objcopy/ELF/update-section.test
index 9364573e9d8bd..8805b2b71090b 100644
--- a/llvm/test/tools/llvm-objcopy/ELF/update-section.test
+++ b/llvm/test/tools/llvm-objcopy/ELF/update-section.test
@@ -170,8 +170,8 @@ ProgramHeaders:
# ADD-UPDATE: )
# ERR-NO-SECTION: error: {{.*}}section '.nosection' not found
-# ERR-NOBITS-TYPE: error: {{.*}}section '.nobits_type' can't be updated because it does not have contents
-# ERR-NULL-TYPE: error: {{.*}}section '.null_type' can't be updated because it does not have contents
+# ERR-NOBITS-TYPE: error: {{.*}}section '.nobits_type' cannot be updated because it does not have contents
+# ERR-NULL-TYPE: error: {{.*}}section '.null_type' cannot be updated because it does not have contents
# ERR-LARGER: error: {{.*}}cannot fit data of size 9 into section '.in_segment' with size 8 that is part of a segment
# MISSING-EQ: error: bad format for --update-section: missing '='
diff --git a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
index e0039cd3a675f..e93d2775665dd 100644
--- a/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/COFF/COFFObjcopy.cpp
@@ -253,6 +253,35 @@ static Error handleArgs(const CommonConfig &Config,
Characteristics);
}
+ for (StringRef Flag : Config.UpdateSection) {
+ StringRef SecName, FileName;
+ std::tie(SecName, FileName) = Flag.split('=');
+
+ auto BufOrErr = MemoryBuffer::getFile(FileName);
+ if (!BufOrErr)
+ return createFileError(FileName, errorCodeToError(BufOrErr.getError()));
+ auto Buf = std::move(*BufOrErr);
+
+ auto It = llvm::find_if(Obj.getMutableSections(), [SecName](auto &Sec) {
+ return Sec.Name == SecName;
+ });
+ if (It == Obj.getMutableSections().end())
+ return createStringError(errc::invalid_argument,
+ "could not find section with name '%s'",
+ SecName.str().c_str());
+ size_t ContentSize = It->getContents().size();
+ if (!ContentSize)
+ return createStringError(
+ errc::invalid_argument,
+ "section '%s' cannot be updated because it does not have contents",
+ SecName.str().c_str());
+ if (ContentSize < Buf->getBufferSize())
+ return createStringError(
+ errc::invalid_argument,
+ "new section cannot be larger than previous section");
+ It->setOwnedContents({Buf->getBufferStart(), Buf->getBufferEnd()});
+ }
+
if (!Config.AddGnuDebugLink.empty())
if (Error E = addGnuDebugLink(Obj, Config.AddGnuDebugLink))
return E;
diff --git a/llvm/tools/llvm-objcopy/COFF/Object.h b/llvm/tools/llvm-objcopy/COFF/Object.h
index 0e854b58cbdba..4a478cda8c151 100644
--- a/llvm/tools/llvm-objcopy/COFF/Object.h
+++ b/llvm/tools/llvm-objcopy/COFF/Object.h
@@ -54,6 +54,7 @@ struct Section {
void setOwnedContents(std::vector<uint8_t> &&Data) {
ContentsRef = ArrayRef<uint8_t>();
OwnedContents = std::move(Data);
+ Header.SizeOfRawData = OwnedContents.size();
}
void clearContents() {
diff --git a/llvm/tools/llvm-objcopy/ELF/Object.cpp b/llvm/tools/llvm-objcopy/ELF/Object.cpp
index 659e12bf0306d..3b4152a74a4af 100644
--- a/llvm/tools/llvm-objcopy/ELF/Object.cpp
+++ b/llvm/tools/llvm-objcopy/ELF/Object.cpp
@@ -2156,7 +2156,7 @@ Error Object::updateSection(StringRef Name, ArrayRef<uint8_t> Data) {
if (!OldSec->hasContents())
return createStringError(
errc::invalid_argument,
- "section '%s' can't be updated because it does not have contents",
+ "section '%s' cannot be updated because it does not have contents",
Name.str().c_str());
if (Data.size() > OldSec->Size && OldSec->ParentSegment)
More information about the llvm-commits
mailing list