[llvm] f147f59 - [llvm-objcopy][MachO] Skip sections with zero offset

Alexander Shaposhnikov via llvm-commits llvm-commits at lists.llvm.org
Fri Nov 6 13:29:57 PST 2020


Author: Alexander Shaposhnikov
Date: 2020-11-06T13:29:43-08:00
New Revision: f147f59cd377a6be68e5ca5c343eb11df8e7ee6f

URL: https://github.com/llvm/llvm-project/commit/f147f59cd377a6be68e5ca5c343eb11df8e7ee6f
DIFF: https://github.com/llvm/llvm-project/commit/f147f59cd377a6be68e5ca5c343eb11df8e7ee6f.diff

LOG: [llvm-objcopy][MachO] Skip sections with zero offset

Some binaries can contain regular sections with zero offset and zero size.
This diff makes llvm-objcopy's handling of such sections consistent with
cctools's strip (which doesn't modify them),
previously the tool would allocate file space for them.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D90796

Added: 
    llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test

Modified: 
    llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
    llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
    llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
    llvm/tools/llvm-objcopy/MachO/Object.h

Removed: 
    


################################################################################
diff  --git a/llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test b/llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test
new file mode 100644
index 000000000000..3d14c34ec741
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/zero-offset-section.test
@@ -0,0 +1,43 @@
+## This test verifies that a regular (non-zero-fill) section with zero offset 
+## and zero size is not modifed, this behavior is consistent with cctools' strip.
+
+# RUN: yaml2obj %s -o %t
+# RUN: llvm-objcopy %t %t.copy
+# RUN: cmp %t %t.copy
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACE
+  cputype:         0x00000007
+  cpusubtype:      0x00000003
+  filetype:        0x00000001
+  ncmds:           1
+  sizeofcmds:      124
+  flags:           0x00002000
+LoadCommands:
+  - cmd:             LC_SEGMENT
+    cmdsize:         124
+    segname:         __DATA
+    vmaddr:          4096
+    vmsize:          0
+    fileoff:         152
+    filesize:        0
+    maxprot:         7
+    initprot:        7
+    nsects:          1
+    flags:           0
+    Sections:
+      - sectname:        __broken
+        segname:         __DATA
+        addr:            0x0000000000001000
+        size:            0
+        offset:          0x00000000
+        align:           2
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x00000000
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+        content:         ''
+...

diff  --git a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
index 947636ac985b..ea01e8519a5c 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOLayoutBuilder.cpp
@@ -148,7 +148,7 @@ uint64_t MachOLayoutBuilder::layoutSegments() {
              "Section's address cannot be smaller than Segment's one");
       uint32_t SectOffset = Sec->Addr - SegmentVmAddr;
       if (IsObjectFile) {
-        if (Sec->isVirtualSection()) {
+        if (!Sec->hasValidOffset()) {
           Sec->Offset = 0;
         } else {
           uint64_t PaddingSize =
@@ -158,7 +158,7 @@ uint64_t MachOLayoutBuilder::layoutSegments() {
           SegFileSize += PaddingSize + Sec->Size;
         }
       } else {
-        if (Sec->isVirtualSection()) {
+        if (!Sec->hasValidOffset()) {
           Sec->Offset = 0;
         } else {
           Sec->Offset = SegOffset + SectOffset;

diff  --git a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
index 6e6975c35139..548a85bd497e 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOReader.cpp
@@ -35,7 +35,7 @@ Section constructSectionCommon(SectionType Sec, uint32_t Index) {
   S.Index = Index;
   S.Addr = Sec.addr;
   S.Size = Sec.size;
-  S.Offset = Sec.offset;
+  S.OriginalOffset = Sec.offset;
   S.Align = Sec.align;
   S.RelOff = Sec.reloff;
   S.NReloc = Sec.nreloc;

diff  --git a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
index 78e03c818fd0..56dd08df3b09 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOWriter.cpp
@@ -121,8 +121,10 @@ size_t MachOWriter::totalSize() const {
   // Otherwise, use the last section / reloction.
   for (const LoadCommand &LC : O.LoadCommands)
     for (const std::unique_ptr<Section> &S : LC.Sections) {
-      if (S->isVirtualSection()) {
-        assert((S->Offset == 0) && "Zero-fill section's offset must be zero");
+      if (!S->hasValidOffset()) {
+        assert((S->Offset == 0) && "Skipped section's offset must be zero");
+        assert((S->isVirtualSection() || S->Size == 0) &&
+               "Non-zero-fill sections with zero offset must have zero size");
         continue;
       }
       assert((S->Offset != 0) &&
@@ -246,8 +248,12 @@ void MachOWriter::writeSectionInLoadCommand(const Section &Sec, uint8_t *&Out) {
 void MachOWriter::writeSections() {
   for (const LoadCommand &LC : O.LoadCommands)
     for (const std::unique_ptr<Section> &Sec : LC.Sections) {
-      if (Sec->isVirtualSection())
+      if (!Sec->hasValidOffset()) {
+        assert((Sec->Offset == 0) && "Skipped section's offset must be zero");
+        assert((Sec->isVirtualSection() || Sec->Size == 0) &&
+               "Non-zero-fill sections with zero offset must have zero size");
         continue;
+      }
 
       assert(Sec->Offset && "Section offset can not be zero");
       assert((Sec->Size == Sec->Content.size()) && "Incorrect section size");

diff  --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h
index 0a930ba19f8e..a743e125c0cd 100644
--- a/llvm/tools/llvm-objcopy/MachO/Object.h
+++ b/llvm/tools/llvm-objcopy/MachO/Object.h
@@ -44,6 +44,8 @@ struct Section {
   std::string CanonicalName;
   uint64_t Addr = 0;
   uint64_t Size = 0;
+  // Offset in the input file.
+  Optional<uint32_t> OriginalOffset;
   uint32_t Offset = 0;
   uint32_t Align = 0;
   uint32_t RelOff = 0;
@@ -73,6 +75,10 @@ struct Section {
             getType() == MachO::S_GB_ZEROFILL ||
             getType() == MachO::S_THREAD_LOCAL_ZEROFILL);
   }
+
+  bool hasValidOffset() const {
+    return !(isVirtualSection() || (OriginalOffset && *OriginalOffset == 0));
+  }
 };
 
 struct LoadCommand {


        


More information about the llvm-commits mailing list