[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