[lld] r212030 - MachO: calculate segment offsets in final MachO files properly.

Tim Northover tnorthover at apple.com
Mon Jun 30 02:49:30 PDT 2014


Author: tnorthover
Date: Mon Jun 30 04:49:30 2014
New Revision: 212030

URL: http://llvm.org/viewvc/llvm-project?rev=212030&view=rev
Log:
MachO: calculate segment offsets in final MachO files properly.

Because of how we were calculating fileOffset and fileSize for segments, most
ended up at a single offset in a finalised MachO file. This meant the data
often didn't even get written in the final object, let alone where it would be
useful.

Added:
    lld/trunk/test/mach-o/exe-offsets.yaml
Modified:
    lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp

Modified: lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp?rev=212030&r1=212029&r2=212030&view=diff
==============================================================================
--- lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp (original)
+++ lld/trunk/lib/ReaderWriter/MachO/MachONormalizedFileBinaryWriter.cpp Mon Jun 30 04:49:30 2014
@@ -142,6 +142,7 @@ private:
 
   struct SegExtraInfo {
     uint32_t                    fileOffset;
+    uint32_t                    fileSize;
     std::vector<const Section*> sections;
   };
   typedef std::map<const Segment*, SegExtraInfo> SegMap;
@@ -423,23 +424,32 @@ void MachOFileLayout::buildFileOffsets()
   DEBUG_WITH_TYPE("MachOFileLayout",
                   llvm::dbgs() << "buildFileOffsets()\n");
   for (const Segment &sg : _file.segments) {
-    // FIXME: 4096 should be inferred from segments in normalized file.
-    _segInfo[&sg].fileOffset = llvm::RoundUpToAlignment(fileOffset, 4096);
+    _segInfo[&sg].fileOffset = fileOffset;
     if ((_seg1addr == INT64_MAX) && sg.access)
       _seg1addr = sg.address;
     DEBUG_WITH_TYPE("MachOFileLayout",
                   llvm::dbgs() << "  segment=" << sg.name
                   << ", fileOffset=" << _segInfo[&sg].fileOffset << "\n");
+
+    uint32_t segFileSize = 0;
     for (const Section *s : _segInfo[&sg].sections) {
-      fileOffset = s->address - sg.address + _segInfo[&sg].fileOffset;
-      _sectInfo[s].fileOffset = fileOffset;
+      uint32_t sectOffset = s->address - sg.address;
+      uint32_t sectFileSize =
+          s->type == llvm::MachO::S_ZEROFILL ? 0 : s->content.size();
+      segFileSize = std::max(segFileSize, sectOffset + sectFileSize);
+
+      _sectInfo[s].fileOffset = _segInfo[&sg].fileOffset + sectOffset;
       DEBUG_WITH_TYPE("MachOFileLayout",
                   llvm::dbgs() << "    section=" << s->sectionName
                   << ", fileOffset=" << fileOffset << "\n");
     }
+
+    // FIXME: 4096 should be inferred from segments in normalized file.
+    _segInfo[&sg].fileSize = llvm::RoundUpToAlignment(segFileSize, 4096);
+    fileOffset = llvm::RoundUpToAlignment(fileOffset + segFileSize, 4096);
     _addressOfLinkEdit = sg.address + sg.size;
   }
-  _startOfLinkEdit = llvm::RoundUpToAlignment(fileOffset, 4096);
+  _startOfLinkEdit = fileOffset;
 }
 
 
@@ -537,7 +547,7 @@ std::error_code MachOFileLayout::writeSe
     cmd->vmaddr   = seg.address;
     cmd->vmsize   = seg.size;
     cmd->fileoff  = segInfo.fileOffset;
-    cmd->filesize = seg.access ? seg.size : Hex64(0);
+    cmd->filesize = segInfo.fileSize;
     cmd->maxprot  = seg.access;
     cmd->initprot = seg.access;
     cmd->nsects   = segInfo.sections.size();

Added: lld/trunk/test/mach-o/exe-offsets.yaml
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/mach-o/exe-offsets.yaml?rev=212030&view=auto
==============================================================================
--- lld/trunk/test/mach-o/exe-offsets.yaml (added)
+++ lld/trunk/test/mach-o/exe-offsets.yaml Mon Jun 30 04:49:30 2014
@@ -0,0 +1,44 @@
+# RUN: lld -flavor darwin -arch x86_64 %s -o %t -e start
+# RUN: llvm-readobj -sections %t | FileCheck %s
+
+# Make sure data gets put at offset
+
+--- !native
+defined-atoms:
+   - name:            start
+     scope:           global
+     content:         [ 90 ]
+
+   - name:            _s1
+     type:            data
+     content:         [ 31, 32, 33, 34 ]
+
+   - name:            _s2
+     type:            zero-fill
+     size:            8192
+
+   - name:            _s3
+     type:            zero-fill
+     size:            100
+
+   - name:            _s4
+     type:            data
+     content:         [ 01 ]
+
+# CHECK-LABEL: Section {
+# CHECK:     Name: __text
+# CHECK:     Segment: __TEXT
+# CHECK:     Size: 0x1
+# CHECK:     Offset: 0
+
+# CHECK-LABEL: Section {
+# CHECK:     Name: __data
+# CHECK:     Segment: __DATA
+# CHECK:     Size: 0x5
+# CHECK:     Offset: 4096
+
+# CHECK-LABEL: Section {
+# CHECK:     Name: ___bss
+# CHECK:     Segment: __DATA
+# CHECK:     Size: 0x0
+# CHECK:     Offset: 4101





More information about the llvm-commits mailing list