[lld-macho] Support -rpath

Pretty straightforward; just emits LC_RPATH for dyld to consume.

Note that lld itself does not yet support dylib lookup via @rpath.

Reviewed By: #lld-macho, compnerd

Differential Revision: https://reviews.llvm.org/D85701
This commit is contained in:
Jez Ng 2020-08-12 19:50:28 -07:00
parent 437e6bd286
commit e48d1262b8
5 changed files with 46 additions and 1 deletions

View File

@ -41,6 +41,7 @@ struct Configuration {
llvm::MachO::HeaderFileType outputType;
std::vector<llvm::StringRef> librarySearchPaths;
std::vector<llvm::StringRef> frameworkSearchPaths;
std::vector<llvm::StringRef> runtimePaths;
llvm::DenseMap<llvm::StringRef, SymbolPriorityEntry> priorities;
};

View File

@ -499,6 +499,7 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
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<StringRef> roots;
for (const Arg *arg : args.filtered(OPT_syslibroot))
@ -569,6 +570,8 @@ bool macho::link(llvm::ArrayRef<const char *> argsArr, bool canExitEarly,
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:

View File

@ -410,7 +410,6 @@ def undefined : Separate<["-"], "undefined">,
def rpath : Separate<["-"], "rpath">,
MetaVarName<"<path>">,
HelpText<"Add <path> to dyld search list for dylibs with load path prefix `@rpath/'">,
Flags<[HelpHidden]>,
Group<grp_resolve>;
def commons : Separate<["-"], "commons">,
MetaVarName<"<treatment>">,

View File

@ -247,6 +247,30 @@ private:
// 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<rpath_command *>(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 @@ void Writer::createLoadCommands() {
make<LCDyldInfo>(in.binding, lazyBindingSection, exportSection));
in.header->addLoadCommand(make<LCSymtab>(symtabSection, stringTableSection));
in.header->addLoadCommand(make<LCDysymtab>());
for (StringRef path : config->runtimePaths)
in.header->addLoadCommand(make<LCRPath>(path));
switch (config->outputType) {
case MH_EXECUTE:

16
lld/test/MachO/rpath.s Normal file
View File

@ -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