[lld] 31626cc - [lld-macho] Add -pagezero_size

Jez Ng via llvm-commits llvm-commits at lists.llvm.org
Sun Feb 6 10:15:39 PST 2022


Author: Jared Irwin
Date: 2022-02-06T13:15:16-05:00
New Revision: 31626cc111c01a92325e36e15b012be0caab4f4c

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

LOG: [lld-macho] Add -pagezero_size

Adds `-pagezero_size`. `-pagezero_size` commonly used for kernel development.
`-pagezero_size` changes the `__PAGEZERO` size, removing that segment if it is set to zero.

One of the four flags from {D118570}
Now with error messages and tests.

Differential Revision: https://reviews.llvm.org/D118724

Added: 
    lld/test/MachO/pagezero.s

Modified: 
    lld/MachO/Driver.cpp
    lld/MachO/Options.td
    lld/MachO/SyntheticSections.h
    lld/test/MachO/lit.local.cfg

Removed: 
    


################################################################################
diff  --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index bf5e97a6314bd..636c4016dd6cb 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1129,6 +1129,27 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
   if (errorCount())
     return false;
 
+  if (args.hasArg(OPT_pagezero_size)) {
+    uint64_t pagezeroSize = args::getHex(args, OPT_pagezero_size, 0);
+
+    // ld64 does something really weird. It attempts to realign the value to the
+    // page size, but assumes the the page size is 4K. This doesn't work with
+    // most of Apple's ARM64 devices, which use a page size of 16K. This means
+    // that it will first 4K align it by rounding down, then round up to 16K.
+    // This probably only happened because no one using this arg with anything
+    // other then 0, so no one checked if it did what is what it says it does.
+
+    // So we are not copying this weird behavior and doing the it in a logical
+    // way, by always rounding down to page size.
+    if (!isAligned(Align(target->getPageSize()), pagezeroSize)) {
+      pagezeroSize -= pagezeroSize % target->getPageSize();
+      warn("__PAGEZERO size is not page aligned, rounding down to 0x" +
+           Twine::utohexstr(pagezeroSize));
+    }
+
+    target->pageZeroSize = pagezeroSize;
+  }
+
   config->osoPrefix = args.getLastArgValue(OPT_oso_prefix);
   if (!config->osoPrefix.empty()) {
     // Expand special characters, such as ".", "..", or  "~", if present.

diff  --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index ab79aa7d86701..144422511fb99 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -444,7 +444,6 @@ def no_pie : Flag<["-"], "no_pie">,
 def pagezero_size : Separate<["-"], "pagezero_size">,
     MetaVarName<"<size>">,
     HelpText<"Size of unreadable segment at address zero is hex <size> (default is 4KB on 32-bit and 4GB on 64-bit)">,
-    Flags<[HelpHidden]>,
     Group<grp_main>;
 def stack_size : Separate<["-"], "stack_size">,
     MetaVarName<"<size>">,

diff  --git a/lld/MachO/SyntheticSections.h b/lld/MachO/SyntheticSections.h
index 12e422b5c5d86..b871477331c8d 100644
--- a/lld/MachO/SyntheticSections.h
+++ b/lld/MachO/SyntheticSections.h
@@ -105,6 +105,7 @@ class PageZeroSection final : public SyntheticSection {
 public:
   PageZeroSection();
   bool isHidden() const override { return true; }
+  bool isNeeded() const override { return target->pageZeroSize != 0; }
   uint64_t getSize() const override { return target->pageZeroSize; }
   uint64_t getFileSize() const override { return 0; }
   void writeTo(uint8_t *buf) const override {}

diff  --git a/lld/test/MachO/lit.local.cfg b/lld/test/MachO/lit.local.cfg
index a45fbaee7f6e0..984c5e5fc4f61 100644
--- a/lld/test/MachO/lit.local.cfg
+++ b/lld/test/MachO/lit.local.cfg
@@ -10,9 +10,10 @@ import os
 # flag will append to the set of library roots. As such, we define a separate
 # alias for each platform.
 
-config.substitutions.append(('%lld-watchos',
-    'ld64.lld -fatal_warnings -arch arm64_32 -platform_version watchos 7.0 8.0 -syslibroot ' +
-    os.path.join(config.test_source_root, "MachO", "Inputs", "WatchOS.sdk")))
+lld_watchos = ('ld64.lld -arch arm64_32 -platform_version watchos 7.0 8.0 -syslibroot ' +
+    os.path.join(config.test_source_root, "MachO", "Inputs", "WatchOS.sdk"))
+config.substitutions.append(('%lld-watchos', lld_watchos + ' -fatal_warnings'))
+config.substitutions.append(('%no_fatal_warnings_lld-watchos', lld_watchos))
 
 # Since most of our tests are written around x86_64, we give this platform the
 # shortest substitution of "%lld".

diff  --git a/lld/test/MachO/pagezero.s b/lld/test/MachO/pagezero.s
new file mode 100644
index 0000000000000..2924fd1ddae70
--- /dev/null
+++ b/lld/test/MachO/pagezero.s
@@ -0,0 +1,37 @@
+# REQUIRES: x86, aarch64
+# RUN: rm -rf %t; mkdir %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/x86_64.o
+# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-darwin %s -o %t/arm64_32.o
+
+# RUN: %lld -lSystem -arch x86_64 -o %t/x86_64 %t/x86_64.o -pagezero_size 100000
+# RUN: llvm-readobj --macho-segment %t/x86_64 | FileCheck %s -D#VMSIZE=0x100000 -D#SIZE=72
+
+# RUN: %lld-watchos -lSystem -arch arm64_32 -o %t/arm64_32 %t/arm64_32.o -pagezero_size 100000
+# RUN: llvm-readobj --macho-segment %t/arm64_32 | FileCheck %s -D#VMSIZE=0x100000 -D#SIZE=56
+
+# RUN: %lld -lSystem -arch x86_64 -o %t/zero %t/x86_64.o -pagezero_size 0
+# RUN: llvm-readobj --macho-segment %t/zero | FileCheck %s --check-prefix=CHECK-ZERO -D#VMSIZE=0x1000 -D#SIZE=152
+
+# RUN: %no_fatal_warnings_lld -lSystem -arch x86_64 -o %t/x86_64-misalign %t/x86_64.o -pagezero_size 1001 2>&1 | FileCheck %s --check-prefix=LINK -D#SIZE=0x1000
+# RUN: llvm-readobj --macho-segment %t/x86_64-misalign | FileCheck %s -D#VMSIZE=0x1000 -D#SIZE=72
+
+# RUN: %no_fatal_warnings_lld-watchos -lSystem -arch arm64_32 -o %t/arm64_32-misalign-4K %t/arm64_32.o -pagezero_size 1001 2>&1 | FileCheck %s --check-prefix=LINK -D#SIZE=0x0
+# RUN: llvm-readobj --macho-segment %t/arm64_32-misalign-4K | FileCheck %s --check-prefix=CHECK-ZERO -D#VMSIZE=0x4000 -D#SIZE=124
+
+# RUN: %no_fatal_warnings_lld-watchos -lSystem -arch arm64_32 -o %t/arm64_32-misalign-16K %t/arm64_32.o -pagezero_size 4001 2>&1 | FileCheck %s --check-prefix=LINK -D#SIZE=0x4000
+# RUN: llvm-readobj --macho-segment %t/arm64_32-misalign-16K | FileCheck %s -D#VMSIZE=0x4000 -D#SIZE=56
+
+# LINK: warning: __PAGEZERO size is not page aligned, rounding down to 0x[[#%x,SIZE]]
+
+# CHECK:        Name: __PAGEZERO
+# CHECK-NEXT:   Size: [[#%d,SIZE]]
+# CHECK-NEXT:   vmaddr: 0x0
+# CHECK-NEXT:   vmsize: 0x[[#%x,VMSIZE]]
+
+# CHECK-ZERO:        Name: __TEXT
+# CHECK-ZERO-NEXT:   Size: [[#%d,SIZE]]
+# CHECK-ZERO-NEXT:   vmaddr: 0x0
+# CHECK-ZERO-NEXT:   vmsize: 0x[[#%x,VMSIZE]]
+
+.globl _main
+_main:


        


More information about the llvm-commits mailing list