diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 23627dd812db..bc9567c6516b 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -82,6 +82,7 @@ struct Configuration { uint8_t OSABI = 0; llvm::CachePruningPolicy ThinLTOCachePolicy; llvm::StringMap SectionStartMap; + llvm::StringRef Chroot; llvm::StringRef DynamicLinker; llvm::StringRef Entry; llvm::StringRef Emulation; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 9431e26d75df..526118122575 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -619,6 +619,7 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->AuxiliaryList = getArgs(Args, OPT_auxiliary); Config->Bsymbolic = Args.hasArg(OPT_Bsymbolic); Config->BsymbolicFunctions = Args.hasArg(OPT_Bsymbolic_functions); + Config->Chroot = Args.getLastArgValue(OPT_chroot); Config->CompressDebugSections = getCompressDebugSections(Args); Config->DefineCommon = getArg(Args, OPT_define_common, OPT_no_define_common, !Args.hasArg(OPT_relocatable)); diff --git a/lld/ELF/DriverUtils.cpp b/lld/ELF/DriverUtils.cpp index c3d81e35a8ea..12aa8ae2b257 100644 --- a/lld/ELF/DriverUtils.cpp +++ b/lld/ELF/DriverUtils.cpp @@ -138,6 +138,7 @@ void elf::printHelp(const char *Argv0) { std::string elf::createResponseFile(const opt::InputArgList &Args) { SmallString<0> Data; raw_svector_ostream OS(Data); + OS << "--chroot .\n"; // Copy the command line to the output while rewriting paths. for (auto *Arg : Args) { diff --git a/lld/ELF/InputFiles.cpp b/lld/ELF/InputFiles.cpp index 5306184064bc..9f9e39b7af39 100644 --- a/lld/ELF/InputFiles.cpp +++ b/lld/ELF/InputFiles.cpp @@ -40,7 +40,13 @@ TarWriter *elf::Tar; InputFile::InputFile(Kind K, MemoryBufferRef M) : MB(M), FileKind(K) {} Optional elf::readFile(StringRef Path) { + // The --chroot option changes our virtual root directory. + // This is useful when you are dealing with files created by --reproduce. + if (!Config->Chroot.empty() && Path.startswith("/")) + Path = Saver.save(Config->Chroot + Path); + log(Path); + auto MBOrErr = MemoryBuffer::getFile(Path); if (auto EC = MBOrErr.getError()) { error("cannot open " + Path + ": " + EC.message()); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 9c78608118cc..ca1fccdda3ff 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -44,6 +44,9 @@ def allow_multiple_definition: F<"allow-multiple-definition">, def as_needed: F<"as-needed">, HelpText<"Only set DT_NEEDED for shared libraries if used">; +// -chroot doesn't have a help text because it is an internal option. +def chroot: S<"chroot">; + def color_diagnostics: F<"color-diagnostics">, HelpText<"Use colors in diagnostics">; diff --git a/lld/ELF/ScriptParser.cpp b/lld/ELF/ScriptParser.cpp index b3847081697c..531c61e6cb40 100644 --- a/lld/ELF/ScriptParser.cpp +++ b/lld/ELF/ScriptParser.cpp @@ -256,7 +256,7 @@ void ScriptParser::addFile(StringRef S) { } } - if (sys::path::is_absolute(S)) { + if (S.startswith("/")) { Driver->addFile(S, /*WithLOption=*/false); } else if (S.startswith("=")) { if (Config->Sysroot.empty()) diff --git a/lld/test/ELF/chroot.s b/lld/test/ELF/chroot.s new file mode 100644 index 000000000000..8c97e99af4dc --- /dev/null +++ b/lld/test/ELF/chroot.s @@ -0,0 +1,12 @@ +# REQUIRES: x86 +# RUN: rm -rf %t.dir +# RUN: mkdir %t.dir +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/chroot.o +# RUN: ld.lld --chroot %t.dir -o %t.exe /chroot.o + +# RUN: echo 'INPUT(/chroot.o)' > %t.dir/scr +# RUN: ld.lld --chroot %t.dir -o %t.exe /scr + +.globl _start +_start: + ret diff --git a/lld/test/ELF/reproduce.s b/lld/test/ELF/reproduce.s index 0a93be08d040..a79a32af72f4 100644 --- a/lld/test/ELF/reproduce.s +++ b/lld/test/ELF/reproduce.s @@ -39,6 +39,7 @@ # RUN: --dynamic-linker "some unusual/path" -soname 'foo bar' -soname='foo bar' # RUN: tar xf repro2.tar # RUN: FileCheck %s --check-prefix=RSP2 < repro2/response.txt +# RSP2: --chroot . # RSP2: "{{.*}}foo bar" # RSP2-NEXT: -L "{{.*}}foo bar" # RSP2-NEXT: -L {{.+}}file