[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
This commit is contained in:
parent
1a18fe65d3
commit
016c2f5e32
|
@ -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 {
|
||||
|
|
|
@ -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");
|
||||
|
|
|
@ -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>;
|
||||
|
|
|
@ -408,6 +408,31 @@ private:
|
|||
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)
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue