[llvm] 016c2f5 - [lld-macho] Support -dyld_env
Vy Nguyen via llvm-commits
llvm-commits at lists.llvm.org
Tue Sep 20 07:17:25 PDT 2022
Author: Vy Nguyen
Date: 2022-09-20T10:16:45-04:00
New Revision: 016c2f5e3233e67f48c2a511962101876ef0b94c
URL: https://github.com/llvm/llvm-project/commit/016c2f5e3233e67f48c2a511962101876ef0b94c
DIFF: https://github.com/llvm/llvm-project/commit/016c2f5e3233e67f48c2a511962101876ef0b94c.diff
LOG: [lld-macho] Support -dyld_env
This arg is undocumented but from looking at the code + experiment, it's used to add additional DYLD_ENVIRONMENT load commands to the output.
Differential Revision: https://reviews.llvm.org/D134058
Added:
lld/test/MachO/dyld-env.s
Modified:
lld/MachO/Config.h
lld/MachO/Driver.cpp
lld/MachO/Options.td
lld/MachO/Writer.cpp
llvm/include/llvm/BinaryFormat/MachO.h
Removed:
################################################################################
diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h
index c6e8b2582bd7d..620206f307d6f 100644
--- a/lld/MachO/Config.h
+++ b/lld/MachO/Config.h
@@ -206,6 +206,8 @@ struct Configuration {
llvm::StringRef osoPrefix;
+ std::vector<llvm::StringRef> dyldEnvs;
+
llvm::MachO::Architecture arch() const { return platformInfo.target.Arch; }
llvm::MachO::PlatformType platform() const {
diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp
index 6bec1086f915d..f13649a911d92 100644
--- a/lld/MachO/Driver.cpp
+++ b/lld/MachO/Driver.cpp
@@ -1437,6 +1437,17 @@ bool macho::link(ArrayRef<const char *> argsArr, llvm::raw_ostream &stdoutOS,
addFile(arg->getValue(), LoadType::CommandLine, /*isLazy=*/false,
/*isExplicit=*/false, /*isBundleLoader=*/true);
}
+ for (auto *arg : args.filtered(OPT_dyld_env)) {
+ StringRef envPair(arg->getValue());
+ if (!envPair.contains('='))
+ error("-dyld_env's argument is malformed. Expected "
+ "-dyld_env <ENV_VAR>=<VALUE>, got `" +
+ envPair + "`");
+ config->dyldEnvs.push_back(envPair);
+ }
+ if (!config->dyldEnvs.empty() && config->outputType != MH_EXECUTE)
+ error("-dyld_env can only be used when creating executable output");
+
if (const Arg *arg = args.getLastArg(OPT_umbrella)) {
if (config->outputType != MH_DYLIB)
warn("-umbrella used, but not creating dylib");
diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td
index 6af993a430cb6..e12626c17e29d 100644
--- a/lld/MachO/Options.td
+++ b/lld/MachO/Options.td
@@ -984,6 +984,10 @@ def objc_stubs_fast : Flag<["-"], "objc_stubs_fast">,
def objc_stubs_small : Flag<["-"], "objc_stubs_small">,
HelpText<"Produce smaller stubs for Objective-C method calls with more jumps.">,
Group<grp_rare>;
+def dyld_env : Separate<["-"], "dyld_env">,
+ MetaVarName<"<dyld_env_var>">,
+ HelpText<"Specifies a LC_DYLD_ENVIRONMENT variable value pair.">,
+ Group<grp_rare>;
def grp_deprecated : OptionGroup<"deprecated">, HelpText<"DEPRECATED">;
@@ -1212,10 +1216,6 @@ def debug_snapshot : Flag<["-"], "debug_snapshot">,
Group<grp_undocumented>;
def demangle : Flag<["-"], "demangle">,
HelpText<"Demangle symbol names in diagnostics">;
-def dyld_env : Flag<["-"], "dyld_env">,
- HelpText<"This option is undocumented in ld64">,
- Flags<[HelpHidden]>,
- Group<grp_undocumented>;
def encryptable : Flag<["-"], "encryptable">,
HelpText<"Generate the LC_ENCRYPTION_INFO load command">,
Group<grp_undocumented>;
diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp
index a8ae554a6246f..d0207bbf500e3 100644
--- a/lld/MachO/Writer.cpp
+++ b/lld/MachO/Writer.cpp
@@ -408,6 +408,31 @@ class LCRPath final : public LoadCommand {
StringRef path;
};
+class LCDyldEnv final : public LoadCommand {
+public:
+ explicit LCDyldEnv(StringRef name) : name(name) {}
+
+ uint32_t getSize() const override {
+ return alignTo(sizeof(dyld_env_command) + name.size() + 1,
+ target->wordSize);
+ }
+
+ void writeTo(uint8_t *buf) const override {
+ auto *c = reinterpret_cast<dyld_env_command *>(buf);
+ buf += sizeof(dyld_env_command);
+
+ c->cmd = LC_DYLD_ENVIRONMENT;
+ c->cmdsize = getSize();
+ c->name = sizeof(dyld_env_command);
+
+ memcpy(buf, name.data(), name.size());
+ buf[name.size()] = '\0';
+ }
+
+private:
+ StringRef name;
+};
+
class LCMinVersion final : public LoadCommand {
public:
explicit LCMinVersion(const PlatformInfo &platformInfo)
@@ -822,6 +847,9 @@ template <class LP> void Writer::createLoadCommands() {
make<LCDylib>(LC_REEXPORT_DYLIB, dylibFile->installName));
}
+ for (const auto &dyldEnv : config->dyldEnvs)
+ in.header->addLoadCommand(make<LCDyldEnv>(dyldEnv));
+
if (functionStartsSection)
in.header->addLoadCommand(make<LCFunctionStarts>(functionStartsSection));
if (dataInCodeSection)
diff --git a/lld/test/MachO/dyld-env.s b/lld/test/MachO/dyld-env.s
new file mode 100644
index 0000000000000..f86320ce26c35
--- /dev/null
+++ b/lld/test/MachO/dyld-env.s
@@ -0,0 +1,41 @@
+# REQUIRES: x86
+
+# RUN: rm -rf %t && mkdir %t
+
+# RUN: llvm-mc -filetype obj -triple x86_64-apple-darwin %s -o %t/main.o
+
+# RUN: %lld -lSystem -dyld_env DYLD_FRAMEWORK_PATH=./Foo.framework %t/main.o -o %t/one_dyld_env.out
+# RUN: llvm-otool -l %t/one_dyld_env.out | FileCheck %s --check-prefix=ONE-ENV
+
+# RUN: %lld -lSystem -dyld_env DYLD_FRAMEWORK_PATH=./Foo.framework \
+# RUN: -dyld_env DYLD_FRAMEWORK_PATH=./Bar.framework \
+# RUN: %t/main.o -o %t/two_dyld_envs.out
+# RUN: llvm-otool -l %t/two_dyld_envs.out | FileCheck %s --check-prefix=TWO-ENV
+
+# RUN: not %lld -lSystem -dyld_env DYLD_FRAMEWORK_PATH,./Foo %t/main.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=MALFORMED
+
+# RUN: not %lld -dylib -lSystem -dyld_env DYLD_FRAMEWORK_PATH=./Foo %t/main.o -o /dev/null 2>&1 | FileCheck %s --check-prefix=DYLIB
+
+# ONE-ENV: Load command 11
+# ONE-ENV-NEXT: cmd LC_DYLD_ENVIRONMENT
+# ONE-ENV-NEXT: cmdsize 48
+# ONE-ENV-NEXT: name DYLD_FRAMEWORK_PATH=./Foo.framework (offset 12)
+
+# TWO-ENV: Load command 11
+# TWO-ENV-NEXT: cmd LC_DYLD_ENVIRONMENT
+# TWO-ENV-NEXT: cmdsize 48
+# TWO-ENV-NEXT: name DYLD_FRAMEWORK_PATH=./Foo.framework (offset 12)
+# TWO-ENV-NEXT: Load command 12
+# TWO-ENV-NEXT: cmd LC_DYLD_ENVIRONMENT
+# TWO-ENV-NEXT: cmdsize 48
+# TWO-ENV-NEXT: name DYLD_FRAMEWORK_PATH=./Bar.framework (offset 12)
+
+# MALFORMED: error: -dyld_env's argument is malformed. Expected -dyld_env <ENV_VAR>=<VALUE>, got `DYLD_FRAMEWORK_PATH,./Foo`
+
+# DYLIB: error: -dyld_env can only be used when creating executable output
+
+.section __TEXT,__text
+
+.global _main
+_main:
+ ret
diff --git a/llvm/include/llvm/BinaryFormat/MachO.h b/llvm/include/llvm/BinaryFormat/MachO.h
index 4616daf30d448..6205cd82067d4 100644
--- a/llvm/include/llvm/BinaryFormat/MachO.h
+++ b/llvm/include/llvm/BinaryFormat/MachO.h
@@ -869,6 +869,12 @@ struct build_version_command {
uint32_t ntools; // number of tool entries following this
};
+struct dyld_env_command {
+ uint32_t cmd;
+ uint32_t cmdsize;
+ uint32_t name;
+};
+
struct dyld_info_command {
uint32_t cmd;
uint32_t cmdsize;
More information about the llvm-commits
mailing list