diff --git a/main.cc b/main.cc index cb1b099a..8ee9ba0d 100644 --- a/main.cc +++ b/main.cc @@ -796,6 +796,9 @@ int main(int argc, char **argv) { config.print_map = args.hasArg(OPT_print_map); config.sysroot = args.getLastArgValue(OPT_sysroot, ""); + for (auto *arg : args.filtered(OPT_rpath)) + config.rpaths.push_back(arg->getValue()); + for (auto *arg : args.filtered(OPT_trace_symbol)) Symbol::intern(arg->getValue())->traced = true; @@ -973,10 +976,14 @@ int main(int argc, char **argv) { // Beyond this point, no new symbols will be added to the result. - // Copy shared object name strings to .dynsym + // Copy shared object name strings to .dynstr for (SharedFile *file : out::dsos) out::dynstr->add_string(file->soname); + // Copy DT_RUNPATH strings to .dynstr. + for (StringRef path : config.rpaths) + out::dynstr->add_string(path); + // Add headers and sections that have to be at the beginning // or the ending of a file. out::chunks.insert(out::chunks.begin(), out::ehdr); diff --git a/mold.h b/mold.h index 0818d2f4..bb56627e 100644 --- a/mold.h +++ b/mold.h @@ -76,6 +76,7 @@ struct Config { int filler = -1; std::string sysroot; std::vector library_paths; + std::vector rpaths; u64 image_base = 0x200000; }; diff --git a/options.td b/options.td index 6aa2d950..fcf630d7 100644 --- a/options.td +++ b/options.td @@ -44,6 +44,8 @@ def: JoinedOrSeparate<["-"], "y">, Alias, HelpText<"Alias for --tr def as_needed: F<"as-needed">; def no_as_needed: F<"no-as-needed">; +defm rpath: Eq<"rpath", "Add a DT_RUNPATH to the output">; + def: JoinedOrSeparate<["-"], "z">; def: F<"hash-style">; def: J<"hash-style=">; diff --git a/output_chunks.cc b/output_chunks.cc index 763c8e48..ae78f606 100644 --- a/output_chunks.cc +++ b/output_chunks.cc @@ -280,6 +280,9 @@ static std::vector create_dynamic_section() { for (SharedFile *file : out::dsos) define(DT_NEEDED, out::dynstr->find_string(file->soname)); + for (StringRef path : config.rpaths) + define(DT_RUNPATH, out::dynstr->find_string(path)); + define(DT_RELA, out::reldyn->shdr.sh_addr); define(DT_RELASZ, out::reldyn->shdr.sh_size); define(DT_RELAENT, sizeof(ELF64LE::Rela)); diff --git a/test/rpath.s b/test/rpath.s new file mode 100644 index 00000000..f6a7bc9d --- /dev/null +++ b/test/rpath.s @@ -0,0 +1,10 @@ +// RUN: cc -o %t.o -c %s +// RUN: mold -o %t.exe %t.o -rpath /foo -rpath /bar +// RUN: readelf --dynamic %t.exe | FileCheck %s +// CHECK: 0x000000000000001d (RUNPATH) Library runpath: [/foo] +// CHECK: 0x000000000000001d (RUNPATH) Library runpath: [/bar] + + .text + .globl _start +_start: + nop