[llvm] e60a760 - [llvm-objcopy][MachO] Fix --add-section

Alexander Shaposhnikov via llvm-commits llvm-commits at lists.llvm.org
Thu Sep 24 01:51:34 PDT 2020


Author: Alexander Shaposhnikov
Date: 2020-09-24T01:51:10-07:00
New Revision: e60a760b7da970b6eeabc26faa9e065ec7cec1a8

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

LOG: [llvm-objcopy][MachO] Fix --add-section

This diff fixes --add-section functionality and simplifies the tests organization.

Test plan: make check-all

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

Added: 
    llvm/test/tools/llvm-objcopy/MachO/add-section-32.test
    llvm/test/tools/llvm-objcopy/MachO/add-section-64.test
    llvm/test/tools/llvm-objcopy/MachO/add-section-error.test

Modified: 
    llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
    llvm/tools/llvm-objcopy/MachO/Object.cpp
    llvm/tools/llvm-objcopy/MachO/Object.h

Removed: 
    llvm/test/tools/llvm-objcopy/MachO/add-section.test


################################################################################
diff  --git a/llvm/test/tools/llvm-objcopy/MachO/add-section-32.test b/llvm/test/tools/llvm-objcopy/MachO/add-section-32.test
new file mode 100644
index 000000000000..628d98519fcc
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/add-section-32.test
@@ -0,0 +1,114 @@
+## Show that llvm-objcopy adds a new section into a 32-bit object file if
+## --add-section is given.
+
+# RUN: yaml2obj %s -o %t
+# RUN: echo -n abcdefg > %t.data
+
+## Case 1: Add a new section into an existing segment.
+# RUN: llvm-objcopy --add-section __TEXT,__bar=%t.data %t %t.out1
+# RUN: llvm-readobj --sections --section-data %t.out1 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE1
+
+## Case 2: Add a new section into a nonexistent segment.
+# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t %t.out2
+# RUN: llvm-readobj --sections --section-data %t.out2 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE2
+
+## Case 3: Add a new section into an existing segment using /dev/null as an input.
+# RUN: llvm-objcopy --add-section __TEXT,__bar=/dev/null %t %t.out3
+# RUN: llvm-readobj --sections --section-data %t.out3 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE3
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACE
+  cputype:         0x00000007
+  cpusubtype:      0x00000003
+  filetype:        0x00000001
+  ncmds:           1
+  sizeofcmds:      124
+  flags:           0x00002000
+LoadCommands:
+  - cmd:             LC_SEGMENT
+    cmdsize:         124
+    segname:         __TEXT
+    vmaddr:          0
+    vmsize:          4
+    fileoff:         184
+    filesize:        4
+    maxprot:         7
+    initprot:        7
+    nsects:          1
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0000000000000000
+        content:         'AABBCCDD'
+        size:            4
+        offset:          184
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+
+# COMMON:         Index: 0
+# COMMON-NEXT:    Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
+# COMMON-NEXT:    Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# COMMON-NEXT:    Address: 0x0
+# COMMON-NEXT:    Size: 0x4
+# COMMON-NEXT:    Offset:
+# COMMON-NEXT:    Alignment: 0
+# COMMON-NEXT:    RelocationOffset: 0x0
+# COMMON-NEXT:    RelocationCount: 0
+# COMMON-NEXT:    Type: Regular (0x0)
+# COMMON-NEXT:    Attributes [ (0x800004)
+# COMMON-NEXT:      PureInstructions (0x800000)
+# COMMON-NEXT:      SomeInstructions (0x4)
+# COMMON-NEXT:    ]
+# COMMON-NEXT:    Reserved1: 0x0
+# COMMON-NEXT:    Reserved2: 0x0
+# COMMON-NEXT:    SectionData (
+# COMMON-NEXT:      0000: AABBCCDD                             |....|
+# COMMON-NEXT:    )
+
+# COMMON:         Index: 1
+# COMMON-NEXT:    Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00)
+
+# CASE1-NEXT:     Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# CASE1-NEXT:     Address: 0x4
+# CASE1-NEXT:     Size: 0x7
+# CASE1-NEXT:     Offset: 224
+
+# CASE2-NEXT:     Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00)
+# CASE2-NEXT:     Address: 0x98
+# CASE2-NEXT:     Size: 0x7
+# CASE2-NEXT:     Offset: 280
+
+# CASE3-NEXT:     Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# CASE3-NEXT:     Address: 0x4
+# CASE3-NEXT:     Size: 0x0
+# CASE3-NEXT:     Offset: 224
+
+# COMMON-NEXT:    Alignment: 0
+# COMMON-NEXT:    RelocationOffset: 0x0
+# COMMON-NEXT:    RelocationCount: 0
+# COMMON-NEXT:    Type: Regular (0x0)
+# COMMON-NEXT:    Attributes [ (0x0)
+# COMMON-NEXT:    ]
+# COMMON-NEXT:    Reserved1: 0x0
+# COMMON-NEXT:    Reserved2: 0x0
+
+# CASE1-NEXT:     SectionData (
+# CASE1-NEXT:       0000: 61626364 656667                      |abcdefg|
+# CASE1-NEXT:     )
+
+# CASE2-NEXT:     SectionData (
+# CASE2-NEXT:       0000: 61626364 656667                      |abcdefg|
+# CASE2-NEXT:     )
+
+# CASE3-NEXT:     SectionData (
+# CASE3-NEXT:     )

diff  --git a/llvm/test/tools/llvm-objcopy/MachO/add-section-64.test b/llvm/test/tools/llvm-objcopy/MachO/add-section-64.test
new file mode 100644
index 000000000000..998b7e838677
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/add-section-64.test
@@ -0,0 +1,119 @@
+## Show that llvm-objcopy adds a new section into a 64-bit object if
+## --add-section is given.
+
+# RUN: yaml2obj %s -o %t
+# RUN: echo -n abcdefg > %t.data
+
+## Case 1: Add a new section into an existing segment.
+# RUN: llvm-objcopy --add-section __TEXT,__bar=%t.data %t %t.out1
+# RUN: llvm-readobj --sections --section-data %t.out1 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE1
+
+## Case 2: Add a new section into a nonexistent segment.
+# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t %t.out2
+# RUN: llvm-readobj --sections --section-data %t.out2 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE2
+# RUN: llvm-readobj --sections --section-data %t.out2 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE2
+
+## Case 3: Add a new section into an existing segment using /dev/null as an input.
+# RUN: llvm-objcopy --add-section __TEXT,__bar=/dev/null %t %t.out3
+# RUN: llvm-readobj --sections --section-data %t.out3 \
+# RUN:   | FileCheck %s --check-prefixes=COMMON,CASE3
+
+--- !mach-o
+FileHeader:
+  magic:           0xFEEDFACF
+  cputype:         0x01000007
+  cpusubtype:      0x00000003
+  filetype:        0x00000001
+  ncmds:           1
+  sizeofcmds:      152
+  flags:           0x00002000
+  reserved:        0x00000000
+LoadCommands:
+  - cmd:             LC_SEGMENT_64
+    cmdsize:         152
+    segname:         __TEXT
+    vmaddr:          0
+    vmsize:          4
+    fileoff:         184
+    filesize:        4
+    maxprot:         7
+    initprot:        7
+    nsects:          1
+    flags:           0
+    Sections:
+      - sectname:        __text
+        segname:         __TEXT
+        addr:            0x0000000000000000
+        content:         'AABBCCDD'
+        size:            4
+        offset:          184
+        align:           0
+        reloff:          0x00000000
+        nreloc:          0
+        flags:           0x80000400
+        reserved1:       0x00000000
+        reserved2:       0x00000000
+        reserved3:       0x00000000
+
+# COMMON:         Index: 0
+# COMMON-NEXT:    Name: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
+# COMMON-NEXT:    Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# COMMON-NEXT:    Address: 0x0
+# COMMON-NEXT:    Size: 0x4
+# COMMON-NEXT:    Offset:
+# COMMON-NEXT:    Alignment: 0
+# COMMON-NEXT:    RelocationOffset: 0x0
+# COMMON-NEXT:    RelocationCount: 0
+# COMMON-NEXT:    Type: Regular (0x0)
+# COMMON-NEXT:    Attributes [ (0x800004)
+# COMMON-NEXT:      PureInstructions (0x800000)
+# COMMON-NEXT:      SomeInstructions (0x4)
+# COMMON-NEXT:    ]
+# COMMON-NEXT:    Reserved1: 0x0
+# COMMON-NEXT:    Reserved2: 0x0
+# COMMON-NEXT:    Reserved3: 0x0
+# COMMON-NEXT:    SectionData (
+# COMMON-NEXT:      0000: AABBCCDD                             |....|
+# COMMON-NEXT:    )
+
+# COMMON:         Index: 1
+# COMMON-NEXT:    Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00)
+
+# CASE1-NEXT:     Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# CASE1-NEXT:     Address: 0x4
+# CASE1-NEXT:     Size: 0x7
+# CASE1-NEXT:     Offset: 268
+
+# CASE2:          Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00)
+# CASE2-NEXT:     Address: 0xB8
+# CASE2-NEXT:     Size: 0x7
+# CASE2-NEXT:     Offset: 340
+
+# CASE3-NEXT:     Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
+# CASE3-NEXT:     Address: 0x4
+# CASE3-NEXT:     Size: 0x0
+# CASE3-NEXT:     Offset: 268
+
+# COMMON-NEXT:    Alignment: 0
+# COMMON-NEXT:    RelocationOffset: 0x0
+# COMMON-NEXT:    RelocationCount: 0
+# COMMON-NEXT:    Type: Regular (0x0)
+# COMMON-NEXT:    Attributes [ (0x0)
+# COMMON-NEXT:    ]
+# COMMON-NEXT:    Reserved1: 0x0
+# COMMON-NEXT:    Reserved2: 0x0
+# COMMON-NEXT:    Reserved3: 0x0
+
+# CASE1-NEXT:     SectionData (
+# CASE1-NEXT:       0000: 61626364 656667                      |abcdefg|
+# CASE1-NEXT:     )
+
+# CASE2-NEXT:     SectionData (
+# CASE2-NEXT:       0000: 61626364 656667                      |abcdefg|
+# CASE2-NEXT:     )
+
+# CASE3-NEXT:     SectionData (
+# CASE3-NEXT:     )

diff  --git a/llvm/test/tools/llvm-objcopy/MachO/add-section-error.test b/llvm/test/tools/llvm-objcopy/MachO/add-section-error.test
new file mode 100644
index 000000000000..a6847ec878bf
--- /dev/null
+++ b/llvm/test/tools/llvm-objcopy/MachO/add-section-error.test
@@ -0,0 +1,14 @@
+## Test --add-section error messages.
+
+# RUN: yaml2obj %p/Inputs/x86_64.yaml -o %t
+# RUN: echo -n abcdefg > %t.data
+
+## Error case 1: Nonexistent input file is specified by --add-section.
+# RUN: not llvm-objcopy --add-section __TEXT,__text=%t.missing %t %t.nonexistent-file 2>&1 \
+# RUN:   | FileCheck %s -DINPUT=%t -DSECTION_DATA_FILE=%t.missing --check-prefix=NONEXSITENT-FILE
+# NONEXSITENT-FILE: error: '[[INPUT]]': '[[SECTION_DATA_FILE]]': {{[Nn]}}o such file or directory
+
+## Error case 2: Too long segment name.
+# RUN: not llvm-objcopy --add-section __TOOOOOOOOO_LONG,__text=%t.data %t %t.too-long-seg-name 2>&1 \
+# RUN:   | FileCheck %s -DINPUT=%t --check-prefix=TOO-LONG-SEG-NAME
+# TOO-LONG-SEG-NAME: error: '[[INPUT]]': too long segment name: '__TOOOOOOOOO_LONG'

diff  --git a/llvm/test/tools/llvm-objcopy/MachO/add-section.test b/llvm/test/tools/llvm-objcopy/MachO/add-section.test
deleted file mode 100644
index 5919b54911a8..000000000000
--- a/llvm/test/tools/llvm-objcopy/MachO/add-section.test
+++ /dev/null
@@ -1,175 +0,0 @@
-## Show that llvm-objcopy adds a new section into the object if
-## --add-section is given.
-
-# RUN: yaml2obj --docnum=1 %s -o %t.64bit
-# RUN: yaml2obj --docnum=2 %s -o %t.32bit
-# RUN: echo -n abcdefg > %t.data
-
-## Error case 1: Nonexistent input file is specified by --add-section.
-# RUN: not llvm-objcopy --add-section __TEXT,__text=%t.missing %t.64bit %t.nonexistent-file 2>&1 \
-# RUN:   | FileCheck %s -DINPUT=%t.64bit -DSECTION_DATA_FILE=%t.missing --check-prefix=NONEXSITENT-FILE
-# NONEXSITENT-FILE: error: '[[INPUT]]': '[[SECTION_DATA_FILE]]': {{[Nn]}}o such file or directory
-
-## Error case 2: Too long segment name.
-# RUN: not llvm-objcopy --add-section __TOOOOOOOOO_LONG,__text=%t.data %t.64bit %t.too-long-seg-name 2>&1 \
-# RUN:   | FileCheck %s -DINPUT=%t.64bit --check-prefix=TOO-LONG-SEG-NAME
-# TOO-LONG-SEG-NAME: error: '[[INPUT]]': too long segment name: '__TOOOOOOOOO_LONG'
-
-## Case 1: Add a new section into an existing segment.
-# RUN: llvm-objcopy --add-section __TEXT,__text=%t.data %t.64bit %t.out1.64bit
-# RUN: llvm-objcopy --add-section __TEXT,__text=%t.data %t.32bit %t.out1.32bit
-# RUN: llvm-readobj --sections --section-data %t.out1.64bit \
-# RUN:   | FileCheck %s --check-prefixes=64BIT,COMMON,CASE1
-# RUN: llvm-readobj --sections --section-data %t.out1.32bit \
-# RUN:   | FileCheck %s --check-prefixes=32BIT,COMMON,CASE1
-
-## Case 2: Add a new section into a nonexistent segment.
-# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t.64bit %t.out2.64bit
-# RUN: llvm-objcopy --add-section __FOO,__bar=%t.data %t.32bit %t.out2.32bit
-# RUN: llvm-readobj --sections --section-data --macho-segment %t.out2.64bit \
-# RUN:   | FileCheck %s --check-prefixes=64BIT,COMMON,CASE2,CASE2-64BIT
-# RUN: llvm-readobj --sections --section-data --macho-segment %t.out2.32bit \
-# RUN:   | FileCheck %s --check-prefixes=32BIT,COMMON,CASE2,CASE2-32BIT
-
-## Case 3: Add a new section with /dev/null.
-# RUN: llvm-objcopy --add-section __TEXT,__text=/dev/null %t.64bit %t.devnull
-# RUN: llvm-readobj --sections --section-data %t.devnull \
-# RUN:   | FileCheck %s --check-prefixes=64BIT,COMMON,DEVNULL
-
-## 64-bit binary
---- !mach-o
-FileHeader:
-  magic:           0xFEEDFACF
-  cputype:         0x01000007
-  cpusubtype:      0x00000003
-  filetype:        0x00000001
-  ncmds:           1
-  sizeofcmds:      152
-  flags:           0x00002000
-  reserved:        0x00000000
-LoadCommands:
-  - cmd:             LC_SEGMENT_64
-    cmdsize:         152
-    segname:         ''
-    vmaddr:          0
-    vmsize:          4
-    fileoff:         184
-    filesize:        4
-    maxprot:         7
-    initprot:        7
-    nsects:          1
-    flags:           0
-    Sections:
-      - sectname:        __text
-        segname:         __TEXT
-        addr:            0x0000000000000000
-        content:         'AABBCCDD'
-        size:            4
-        offset:          184
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x80000400
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
-
-## 32-bit binary
---- !mach-o
-FileHeader:
-  magic:           0xFEEDFACE
-  cputype:         0x00000007
-  cpusubtype:      0x00000003
-  filetype:        0x00000001
-  ncmds:           1
-  sizeofcmds:      124
-  flags:           0x00002000
-LoadCommands:
-  - cmd:             LC_SEGMENT
-    cmdsize:         124
-    segname:         ''
-    vmaddr:          0
-    vmsize:          4
-    fileoff:         184
-    filesize:        4
-    maxprot:         7
-    initprot:        7
-    nsects:          1
-    flags:           0
-    Sections:
-      - sectname:        __text
-        segname:         __TEXT
-        addr:            0x0000000000000000
-        content:         'AABBCCDD'
-        size:            4
-        offset:          184
-        align:           0
-        reloff:          0x00000000
-        nreloc:          0
-        flags:           0x80000400
-        reserved1:       0x00000000
-        reserved2:       0x00000000
-        reserved3:       0x00000000
-
-# COMMON:       Index: 0
-# COMMON-NEXT:  __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
-# COMMON-NEXT:  Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
-# COMMON:       Index: 1
-# CASE1-NEXT:   __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
-# CASE1-NEXT:   Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
-# CASE2-NEXT:   Name: __bar (5F 5F 62 61 72 00 00 00 00 00 00 00 00 00 00 00)
-# CASE2-NEXT:   Segment: __FOO (5F 5F 46 4F 4F 00 00 00 00 00 00 00 00 00 00 00)
-# DEVNULL-NEXT: __text (5F 5F 74 65 78 74 00 00 00 00 00 00 00 00 00 00)
-# DEVNULL-NEXT: Segment: __TEXT (5F 5F 54 45 58 54 00 00 00 00 00 00 00 00 00 00)
-# COMMON-NEXT:  Address: 0x0
-# CASE1-NEXT:   Size: 0x7
-# CASE2-NEXT:   Size: 0x7
-# DEVNULL-NEXT: Size: 0x0
-# 64BIT-NEXT:   Offset: 340
-# 32BIT-NEXT:   Offset: 280
-# COMMON-NEXT:  Alignment: 0
-# COMMON-NEXT:  RelocationOffset: 0x0
-# COMMON-NEXT:  RelocationCount: 0
-# COMMON-NEXT:  Type: Regular (0x0)
-# COMMON-NEXT:  Attributes [ (0x0)
-# COMMON-NEXT:  ]
-# COMMON-NEXT:  Reserved1: 0x0
-# COMMON-NEXT:  Reserved2: 0x0
-# 64BIT-NEXT:   Reserved3: 0x0
-# COMMON-NEXT:  SectionData (
-# CASE1-NEXT:    0000: 61626364 656667                      |abcdefg|
-# CASE2-NEXT:    0000: 61626364 656667                      |abcdefg|
-# COMMON-NEXT:  )
-
-# CASE2:            Segment {
-# CASE2-64BIT-NEXT:   Cmd: LC_SEGMENT_64
-# CASE2-32BIT-NEXT:   Cmd: LC_SEGMENT{{$}}
-# CASE2-NEXT:         Name:
-# CASE2-64BIT-NEXT:   Size: 152
-# CASE2-32BIT-NEXT:   Size: 124
-# CASE2-NEXT:         vmaddr: 0x0
-# CASE2-NEXT:         vmsize: 0x4
-# CASE2-64BIT-NEXT:   fileoff: 336
-# CASE2-32BIT-NEXT:   fileoff: 276
-# CASE2-NEXT:         filesize: 4
-# CASE2-NEXT:         maxprot: rwx
-# CASE2-NEXT:         initprot: rwx
-# CASE2-NEXT:         nsects: 1
-# CASE2-NEXT:         flags: 0x0
-# CASE2-NEXT:       }
-# CASE2-NEXT:       Segment {
-# CASE2-64BIT-NEXT:   Cmd: LC_SEGMENT_64
-# CASE2-32BIT-NEXT:   Cmd: LC_SEGMENT{{$}}
-# CASE2-NEXT:         Name: __FOO
-# CASE2-64BIT-NEXT:   Size: 152
-# CASE2-32BIT-NEXT:   Size: 124
-# CASE2-NEXT:         vmaddr: 0x0
-# CASE2-NEXT:         vmsize: 0x7
-# CASE2-64BIT-NEXT:   fileoff: 340
-# CASE2-32BIT-NEXT:   fileoff: 280
-# CASE2-NEXT:         filesize: 7
-# CASE2-NEXT:         maxprot: ---
-# CASE2-NEXT:         initprot: ---
-# CASE2-NEXT:         nsects: 1
-# CASE2-NEXT:         flags: 0x0
-# CASE2-NEXT:       }

diff  --git a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
index fff3f01a60f4..e87487eb5f8f 100644
--- a/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/MachOObjcopy.cpp
@@ -259,7 +259,11 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) {
   for (LoadCommand &LC : Obj.LoadCommands) {
     Optional<StringRef> SegName = LC.getSegmentName();
     if (SegName && SegName == TargetSegName) {
+      uint64_t Addr = *LC.getSegmentVMAddr();
+      for (const std::unique_ptr<Section> &S : LC.Sections)
+        Addr = std::max(Addr, S->Addr + S->Size);
       LC.Sections.push_back(std::make_unique<Section>(Sec));
+      LC.Sections.back()->Addr = Addr;
       return Error::success();
     }
   }
@@ -268,6 +272,7 @@ static Error addSection(StringRef SecName, StringRef Filename, Object &Obj) {
   // Insert a new section into it.
   LoadCommand &NewSegment = Obj.addSegment(TargetSegName);
   NewSegment.Sections.push_back(std::make_unique<Section>(Sec));
+  NewSegment.Sections.back()->Addr = *NewSegment.getSegmentVMAddr();
   return Error::success();
 }
 

diff  --git a/llvm/tools/llvm-objcopy/MachO/Object.cpp b/llvm/tools/llvm-objcopy/MachO/Object.cpp
index 0359e2a3e924..6a89076bafcf 100644
--- a/llvm/tools/llvm-objcopy/MachO/Object.cpp
+++ b/llvm/tools/llvm-objcopy/MachO/Object.cpp
@@ -111,24 +111,53 @@ Error Object::removeSections(
   return Error::success();
 }
 
+uint64_t Object::nextAvailableSegmentAddress() const {
+  uint64_t HeaderSize =
+      is64Bit() ? sizeof(MachO::mach_header_64) : sizeof(MachO::mach_header);
+  uint64_t Addr = HeaderSize + Header.SizeOfCmds;
+  for (const LoadCommand &LC : LoadCommands) {
+    const MachO::macho_load_command &MLC = LC.MachOLoadCommand;
+    switch (MLC.load_command_data.cmd) {
+    case MachO::LC_SEGMENT:
+      Addr = std::max(Addr,
+                      static_cast<uint64_t>(MLC.segment_command_data.vmaddr) +
+                          MLC.segment_command_data.vmsize);
+      break;
+    case MachO::LC_SEGMENT_64:
+      Addr = std::max(Addr, MLC.segment_command_64_data.vmaddr +
+                                MLC.segment_command_64_data.vmsize);
+      break;
+    default:
+      continue;
+    }
+  }
+  return Addr;
+}
+
 template <typename SegmentType>
 static void constructSegment(SegmentType &Seg,
                              llvm::MachO::LoadCommandType CmdType,
-                             StringRef SegName) {
+                             StringRef SegName, uint64_t SegVMAddr) {
   assert(SegName.size() <= sizeof(Seg.segname) && "too long segment name");
   memset(&Seg, 0, sizeof(SegmentType));
   Seg.cmd = CmdType;
   strncpy(Seg.segname, SegName.data(), SegName.size());
+  Seg.maxprot |=
+      (MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE);
+  Seg.initprot |=
+      (MachO::VM_PROT_READ | MachO::VM_PROT_WRITE | MachO::VM_PROT_EXECUTE);
+  Seg.vmaddr = SegVMAddr;
 }
 
 LoadCommand &Object::addSegment(StringRef SegName) {
   LoadCommand LC;
+  const uint64_t SegVMAddr = nextAvailableSegmentAddress();
   if (is64Bit())
     constructSegment(LC.MachOLoadCommand.segment_command_64_data,
-                     MachO::LC_SEGMENT_64, SegName);
+                     MachO::LC_SEGMENT_64, SegName, SegVMAddr);
   else
     constructSegment(LC.MachOLoadCommand.segment_command_data,
-                     MachO::LC_SEGMENT, SegName);
+                     MachO::LC_SEGMENT, SegName, SegVMAddr);
 
   LoadCommands.push_back(std::move(LC));
   return LoadCommands.back();
@@ -152,6 +181,18 @@ Optional<StringRef> LoadCommand::getSegmentName() const {
   }
 }
 
+Optional<uint64_t> LoadCommand::getSegmentVMAddr() const {
+  const MachO::macho_load_command &MLC = MachOLoadCommand;
+  switch (MLC.load_command_data.cmd) {
+  case MachO::LC_SEGMENT:
+    return MLC.segment_command_data.vmaddr;
+  case MachO::LC_SEGMENT_64:
+    return MLC.segment_command_64_data.vmaddr;
+  default:
+    return None;
+  }
+}
+
 } // end namespace macho
 } // end namespace objcopy
 } // end namespace llvm

diff  --git a/llvm/tools/llvm-objcopy/MachO/Object.h b/llvm/tools/llvm-objcopy/MachO/Object.h
index 102aeedc292f..0a930ba19f8e 100644
--- a/llvm/tools/llvm-objcopy/MachO/Object.h
+++ b/llvm/tools/llvm-objcopy/MachO/Object.h
@@ -94,6 +94,9 @@ struct LoadCommand {
 
   // Returns the segment name if the load command is a segment command.
   Optional<StringRef> getSegmentName() const;
+
+  // Returns the segment vm address if the load command is a segment command.
+  Optional<uint64_t> getSegmentVMAddr() const;
 };
 
 // A symbol information. Fields which starts with "n_" are same as them in the
@@ -340,6 +343,8 @@ struct Object {
     return Header.Magic == MachO::MH_MAGIC_64 ||
            Header.Magic == MachO::MH_CIGAM_64;
   }
+
+  uint64_t nextAvailableSegmentAddress() const;
 };
 
 } // end namespace macho


        


More information about the llvm-commits mailing list