diff --git a/lld/MachO/Config.h b/lld/MachO/Config.h --- a/lld/MachO/Config.h +++ b/lld/MachO/Config.h @@ -41,6 +41,7 @@ llvm::MachO::HeaderFileType outputType; std::vector librarySearchPaths; std::vector frameworkSearchPaths; + std::vector runtimePaths; llvm::DenseMap priorities; }; diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -499,6 +499,7 @@ args.getLastArgValue(OPT_install_name, config->outputFile); config->headerPad = args::getHex(args, OPT_headerpad, /*Default=*/32); config->outputType = args.hasArg(OPT_dylib) ? MH_DYLIB : MH_EXECUTE; + config->runtimePaths = args::getStrings(args, OPT_rpath); std::vector roots; for (const Arg *arg : args.filtered(OPT_syslibroot)) @@ -569,6 +570,8 @@ case OPT_L: case OPT_headerpad: case OPT_install_name: + case OPT_rpath: + case OPT_sub_library: case OPT_Z: case OPT_arch: case OPT_syslibroot: diff --git a/lld/MachO/Options.td b/lld/MachO/Options.td --- a/lld/MachO/Options.td +++ b/lld/MachO/Options.td @@ -410,7 +410,6 @@ def rpath : Separate<["-"], "rpath">, MetaVarName<"">, HelpText<"Add to dyld search list for dylibs with load path prefix `@rpath/'">, - Flags<[HelpHidden]>, Group; def commons : Separate<["-"], "commons">, MetaVarName<"">, diff --git a/lld/MachO/Writer.cpp b/lld/MachO/Writer.cpp --- a/lld/MachO/Writer.cpp +++ b/lld/MachO/Writer.cpp @@ -247,6 +247,30 @@ // different location. const StringRef path = "/usr/lib/dyld"; }; + +class LCRPath : public LoadCommand { +public: + LCRPath(StringRef path) : path(path) {} + + uint32_t getSize() const override { + return alignTo(sizeof(rpath_command) + path.size() + 1, WordSize); + } + + void writeTo(uint8_t *buf) const override { + auto *c = reinterpret_cast(buf); + buf += sizeof(rpath_command); + + c->cmd = LC_RPATH; + c->cmdsize = getSize(); + c->path = sizeof(rpath_command); + + memcpy(buf, path.data(), path.size()); + buf[path.size()] = '\0'; + } + +private: + StringRef path; +}; } // namespace void Writer::scanRelocations() { @@ -268,6 +292,8 @@ make(in.binding, lazyBindingSection, exportSection)); in.header->addLoadCommand(make(symtabSection, stringTableSection)); in.header->addLoadCommand(make()); + for (StringRef path : config->runtimePaths) + in.header->addLoadCommand(make(path)); switch (config->outputType) { case MH_EXECUTE: diff --git a/lld/test/MachO/rpath.s b/lld/test/MachO/rpath.s new file mode 100644 --- /dev/null +++ b/lld/test/MachO/rpath.s @@ -0,0 +1,16 @@ +# REQUIRES: x86 +# RUN: llvm-mc -filetype=obj -triple=x86_64-apple-darwin %s -o %t.o +# RUN: lld -flavor darwinnew -o %t %t.o + +## Check that -rpath generates LC_RPATH. +# RUN: lld -flavor darwinnew -o %t %t.o -rpath /some/rpath +# RUN: llvm-objdump --macho --all-headers %t | FileCheck %s +# CHECK: LC_RPATH +# CHECK-NEXT: cmdsize 24 +# CHECK-NEXT: path /some/rpath + +.text +.global _main +_main: + mov $0, %rax + ret