[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
This commit is contained in:
parent
cecf11c315
commit
31626cc111
|
|
@ -1129,6 +1129,27 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
|
||||||
if (errorCount())
|
if (errorCount())
|
||||||
return false;
|
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);
|
config->osoPrefix = args.getLastArgValue(OPT_oso_prefix);
|
||||||
if (!config->osoPrefix.empty()) {
|
if (!config->osoPrefix.empty()) {
|
||||||
// Expand special characters, such as ".", "..", or "~", if present.
|
// Expand special characters, such as ".", "..", or "~", if present.
|
||||||
|
|
|
||||||
|
|
@ -444,7 +444,6 @@ def no_pie : Flag<["-"], "no_pie">,
|
||||||
def pagezero_size : Separate<["-"], "pagezero_size">,
|
def pagezero_size : Separate<["-"], "pagezero_size">,
|
||||||
MetaVarName<"<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)">,
|
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>;
|
Group<grp_main>;
|
||||||
def stack_size : Separate<["-"], "stack_size">,
|
def stack_size : Separate<["-"], "stack_size">,
|
||||||
MetaVarName<"<size>">,
|
MetaVarName<"<size>">,
|
||||||
|
|
|
||||||
|
|
@ -105,6 +105,7 @@ class PageZeroSection final : public SyntheticSection {
|
||||||
public:
|
public:
|
||||||
PageZeroSection();
|
PageZeroSection();
|
||||||
bool isHidden() const override { return true; }
|
bool isHidden() const override { return true; }
|
||||||
|
bool isNeeded() const override { return target->pageZeroSize != 0; }
|
||||||
uint64_t getSize() const override { return target->pageZeroSize; }
|
uint64_t getSize() const override { return target->pageZeroSize; }
|
||||||
uint64_t getFileSize() const override { return 0; }
|
uint64_t getFileSize() const override { return 0; }
|
||||||
void writeTo(uint8_t *buf) const override {}
|
void writeTo(uint8_t *buf) const override {}
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,10 @@ import os
|
||||||
# flag will append to the set of library roots. As such, we define a separate
|
# flag will append to the set of library roots. As such, we define a separate
|
||||||
# alias for each platform.
|
# alias for each platform.
|
||||||
|
|
||||||
config.substitutions.append(('%lld-watchos',
|
lld_watchos = ('ld64.lld -arch arm64_32 -platform_version watchos 7.0 8.0 -syslibroot ' +
|
||||||
'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"))
|
||||||
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
|
# Since most of our tests are written around x86_64, we give this platform the
|
||||||
# shortest substitution of "%lld".
|
# shortest substitution of "%lld".
|
||||||
|
|
|
||||||
|
|
@ -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:
|
||||||
Loading…
Reference in New Issue