[lld] ab9c21b - [lld-macho] Support LC_ENCRYPTION_INFO
Jez Ng via llvm-commits
llvm-commits at lists.llvm.org
Wed Apr 21 10:40:58 PDT 2021
Author: Jez Ng
Date: 2021-04-21T13:39:56-04:00
New Revision: ab9c21bbab38cd8e3abdc2226a02d67b3327207c
URL: https://github.com/llvm/llvm-project/commit/ab9c21bbab38cd8e3abdc2226a02d67b3327207c
DIFF: https://github.com/llvm/llvm-project/commit/ab9c21bbab38cd8e3abdc2226a02d67b3327207c.diff
LOG: [lld-macho] Support LC_ENCRYPTION_INFO
This load command records a range spanning from the end of the load
commands to the end of the `__TEXT` segment. Presumably the kernel will encrypt
all this data.
Reviewed By: #lld-macho, thakis
Differential Revision: https://reviews.llvm.org/D100973
Added:
lld/test/MachO/encryption-info.s
Modified:
lld/MachO/Config.h
lld/MachO/Driver.cpp
lld/MachO/Options.td
lld/MachO/SyntheticSections.cpp
lld/MachO/Target.h
lld/MachO/Writer.cpp
Removed:
################################################################################
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index def14abc5b51f..280bf8ecd87ab 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -90,6 +90,7 @@ struct Configuration {
bool adhocCodesign = false;
bool emitFunctionStarts = false;
bool emitBitcodeBundle = false;
+ bool emitEncryptionInfo = false;
bool timeTraceEnabled = false;
uint32_t headerPad;
uint32_t dylibCompatibilityVersion = 0;
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 32d70495cf874..88937d726451a 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -963,6 +963,12 @@ bool macho::link(ArrayRef<const char *> argsArr, bool canExitEarly,
config->emitFunctionStarts = !args.hasArg(OPT_no_function_starts);
config->emitBitcodeBundle = args.hasArg(OPT_bitcode_bundle);
+ std::array<PlatformKind, 3> encryptablePlatforms{
+ PlatformKind::iOS, PlatformKind::watchOS, PlatformKind::tvOS};
+ config->emitEncryptionInfo = args.hasFlag(
+ OPT_encryptable, OPT_no_encryption,
+ is_contained(encryptablePlatforms, config->platformInfo.target.Platform));
+
#ifndef HAVE_LIBXAR
if (config->emitBitcodeBundle)
error("-bitcode_bundle unsupported because LLD wasn't built with libxar");
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 822e74eadf8a8..66d1ed90f5616 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -1158,8 +1158,10 @@ def dyld_env : Flag<["-"], "dyld_env">,
Flags<[HelpHidden]>,
Group<grp_undocumented>;
def encryptable : Flag<["-"], "encryptable">,
- HelpText<"This option is undocumented in ld64">,
- Flags<[HelpHidden]>,
+ HelpText<"Generate the LC_ENCRYPTION_INFO load command">,
+ Group<grp_undocumented>;
+def no_encryption : Flag<["-"], "no_encryption">,
+ HelpText<"Do not generate the LC_ENCRYPTION_INFO load command">,
Group<grp_undocumented>;
def executable_path : Flag<["-"], "executable_path">,
HelpText<"This option is undocumented in ld64">,
@@ -1253,10 +1255,6 @@ def no_dtrace_dof : Flag<["-"], "no_dtrace_dof">,
HelpText<"This option is undocumented in ld64">,
Flags<[HelpHidden]>,
Group<grp_undocumented>;
-def no_encryption : Flag<["-"], "no_encryption">,
- HelpText<"This option is undocumented in ld64">,
- Flags<[HelpHidden]>,
- Group<grp_undocumented>;
def no_new_main : Flag<["-"], "no_new_main">,
HelpText<"This option is undocumented in ld64">,
Flags<[HelpHidden]>,
diff --git a/lld/MachO/SyntheticSections.cpp b/lld/MachO/SyntheticSections.cpp
index afa6777f8ecc2..6d7515d2de837 100644
--- a/lld/MachO/SyntheticSections.cpp
+++ b/lld/MachO/SyntheticSections.cpp
@@ -85,7 +85,13 @@ template <class LP> MachHeaderSection *macho::makeMachHeaderSection() {
}
template <class LP> uint64_t MachHeaderSectionImpl<LP>::getSize() const {
- return sizeof(typename LP::mach_header) + sizeOfCmds + config->headerPad;
+ uint64_t size =
+ sizeof(typename LP::mach_header) + sizeOfCmds + config->headerPad;
+ // If we are emitting an encryptable binary, our load commands must have a
+ // separate (non-encrypted) page to themselves.
+ if (config->emitEncryptionInfo)
+ size = alignTo(size, target->getPageSize());
+ return size;
}
static uint32_t cpuSubtype() {
diff --git a/lld/MachO/Target.h b/lld/MachO/Target.h
index c9747e9b62f23..b34206a3d2810 100644
--- a/lld/MachO/Target.h
+++ b/lld/MachO/Target.h
@@ -86,9 +86,12 @@ struct LP64 {
using nlist = structs::nlist_64;
using segment_command = llvm::MachO::segment_command_64;
using section = llvm::MachO::section_64;
+ using encryption_info_command = llvm::MachO::encryption_info_command_64;
static constexpr uint32_t magic = llvm::MachO::MH_MAGIC_64;
static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT_64;
+ static constexpr uint32_t encryptionInfoLCType =
+ llvm::MachO::LC_ENCRYPTION_INFO_64;
static constexpr uint64_t pageZeroSize = 1ull << 32;
static constexpr size_t wordSize = 8;
@@ -99,9 +102,12 @@ struct ILP32 {
using nlist = structs::nlist;
using segment_command = llvm::MachO::segment_command;
using section = llvm::MachO::section;
+ using encryption_info_command = llvm::MachO::encryption_info_command;
static constexpr uint32_t magic = llvm::MachO::MH_MAGIC;
static constexpr uint32_t segmentLCType = llvm::MachO::LC_SEGMENT;
+ static constexpr uint32_t encryptionInfoLCType =
+ llvm::MachO::LC_ENCRYPTION_INFO;
static constexpr uint64_t pageZeroSize = 1ull << 12;
static constexpr size_t wordSize = 4;
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index 7cd3de863913e..1c745758effce 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -471,6 +471,29 @@ class LCUuid : public LoadCommand {
mutable uint8_t *uuidBuf;
};
+template <class LP> class LCEncryptionInfo : public LoadCommand {
+public:
+ LCEncryptionInfo() {}
+
+ uint32_t getSize() const override {
+ return sizeof(typename LP::encryption_info_command);
+ }
+
+ void writeTo(uint8_t *buf) const override {
+ using EncryptionInfo = typename LP::encryption_info_command;
+ auto *c = reinterpret_cast<EncryptionInfo *>(buf);
+ buf += sizeof(EncryptionInfo);
+ c->cmd = LP::encryptionInfoLCType;
+ c->cmdsize = getSize();
+ c->cryptoff = in.header->getSize();
+ auto it = find_if(outputSegments, [](const OutputSegment *seg) {
+ return seg->name == segment_names::text;
+ });
+ assert(it != outputSegments.end());
+ c->cryptsize = (*it)->fileSize - c->cryptoff;
+ }
+};
+
class LCCodeSignature : public LoadCommand {
public:
LCCodeSignature(CodeSignatureSection *section) : section(section) {}
@@ -621,6 +644,8 @@ template <class LP> void Writer::createLoadCommands() {
make<LCDysymtab>(symtabSection, indirectSymtabSection));
if (functionStartsSection)
in.header->addLoadCommand(make<LCFunctionStarts>(functionStartsSection));
+ if (config->emitEncryptionInfo)
+ in.header->addLoadCommand(make<LCEncryptionInfo<LP>>());
for (StringRef path : config->runtimePaths)
in.header->addLoadCommand(make<LCRPath>(path));
diff --git a/lld/test/MachO/encryption-info.s b/lld/test/MachO/encryption-info.s
new file mode 100644
index 0000000000000..df7e604ea381e
--- /dev/null
+++ b/lld/test/MachO/encryption-info.s
@@ -0,0 +1,35 @@
+# REQUIRES: x86
+# RUN: rm -rf %t; mkdir -p %t
+# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t/test.o
+# RUN: llvm-mc -filetype=obj -triple=arm64_32-apple-watchos %s -o %t/watchos-test.o
+
+# RUN: %lld -lSystem -o %t/test %t/test.o
+# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s --check-prefix=NO-ENCRYPTION -DSUFFIX=_64
+
+# RUN: %lld -lSystem -encryptable -o %t/test %t/test.o
+# RUN: llvm-objdump --macho --all-headers %t/test | FileCheck %s --check-prefix=ENCRYPTION -DSUFFIX=_64 -D#PAGE_SIZE=4096
+
+# RUN: %lld-watchos -lSystem -o %t/watchos-test %t/watchos-test.o
+# RUN: llvm-objdump --macho --all-headers %t/watchos-test | FileCheck %s --check-prefix=ENCRYPTION -DSUFFIX= -D#PAGE_SIZE=16384
+
+# RUN: %lld-watchos -lSystem -no_encryption -o %t/watchos-test %t/watchos-test.o
+# RUN: llvm-objdump --macho --all-headers %t/watchos-test | FileCheck %s --check-prefix=NO-ENCRYPTION -DSUFFIX=
+
+# ENCRYPTION: segname __TEXT
+# ENCRYPTION-NEXT: vmaddr
+# ENCRYPTION-NEXT: vmsize
+# ENCRYPTION-NEXT: fileoff 0
+# ENCRYPTION-NEXT: filesize [[#TEXT_SIZE:]]
+
+# ENCRYPTION: cmd LC_ENCRYPTION_INFO[[SUFFIX]]{{$}}
+# ENCRYPTION-NEXT: cmdsize
+# ENCRYPTION-NEXT: cryptoff [[#PAGE_SIZE]]
+# ENCRYPTION-NEXT: cryptsize [[#TEXT_SIZE - PAGE_SIZE]]
+# ENCRYPTION-NEXT: cryptid 0
+
+# NO-ENCRYPTION-NOT: LC_ENCRYPTION_INFO[[SUFFIX]]{{$}}
+
+.globl _main
+.p2align 2
+_main:
+ ret
More information about the llvm-commits
mailing list