diff options
author | Jared Irwin <jrairwin@sympatico.ca> | 2022-02-06 12:36:12 -0500 |
---|---|---|
committer | Jez Ng <jezng@fb.com> | 2022-02-06 13:15:16 -0500 |
commit | 31626cc111c01a92325e36e15b012be0caab4f4c (patch) | |
tree | 517a22f5da22be9c8dbac820058acd0bb09a0b93 | |
parent | cecf11c31544ec17b16843297246e93618cd56cd (diff) | |
download | llvm-31626cc111c01a92325e36e15b012be0caab4f4c.zip llvm-31626cc111c01a92325e36e15b012be0caab4f4c.tar.gz llvm-31626cc111c01a92325e36e15b012be0caab4f4c.tar.bz2 |
[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
-rw-r--r-- | lld/MachO/Driver.cpp | 21 | ||||
-rw-r--r-- | lld/MachO/Options.td | 1 | ||||
-rw-r--r-- | lld/MachO/SyntheticSections.h | 1 | ||||
-rw-r--r-- | lld/test/MachO/lit.local.cfg | 7 | ||||
-rw-r--r-- | lld/test/MachO/pagezero.s | 37 |
5 files changed, 63 insertions, 4 deletions
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index bf5e97a..636c401 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 ab79aa7..1444225 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 12e422b..b871477 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 a45fbae..984c5e5 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 0000000..2924fd1 --- /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: |