From: Jez Ng Date: Wed, 5 May 2021 18:38:36 +0000 (-0400) Subject: [lld-macho] Have --reproduce account for path rerooting X-Git-Tag: llvmorg-14-init~7530 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=20f51ffe67d12ab72c917dc4b371b55c80321393;p=platform%2Fupstream%2Fllvm.git [lld-macho] Have --reproduce account for path rerooting We need to account for path rerooting when generating the response file. We could either reroot the paths before generating the file, or pass through the original filenames and change just the syslibroot. I've opted for the latter, in order that the reproduction run more closely mirrors the original. We must also be careful *not* to make an absolute path relative if it is shadowed by a rerooted path. See repro6.tar in reroot-path.s for details. I've moved the call to `createResponseFile()` after the initialization of `config->systemLibraryRoots`, since it now needs to know what those roots are. Reviewed By: #lld-macho, oontvoo Differential Revision: https://reviews.llvm.org/D101224 --- diff --git a/lld/MachO/Driver.cpp b/lld/MachO/Driver.cpp index 133d3ba..e1efac0 100644 --- a/lld/MachO/Driver.cpp +++ b/lld/MachO/Driver.cpp @@ -77,26 +77,6 @@ static HeaderFileType getOutputType(const InputArgList &args) { } } -// Search for all possible combinations of `{root}/{name}.{extension}`. -// If \p extensions are not specified, then just search for `{root}/{name}`. -static Optional -findPathCombination(const Twine &name, const std::vector &roots, - ArrayRef extensions = {""}) { - SmallString<261> base; - for (StringRef dir : roots) { - base = dir; - path::append(base, name); - for (StringRef ext : extensions) { - Twine location = base + ext; - if (fs::exists(location)) - return saver.save(location.str()); - else - depTracker->logFileNotFound(location); - } - } - return {}; -} - static Optional findLibrary(StringRef name) { if (config->searchDylibsFirst) { if (Optional path = findPathCombination( @@ -109,19 +89,6 @@ static Optional findLibrary(StringRef name) { {".tbd", ".dylib", ".a"}); } -// If -syslibroot is specified, absolute paths to non-object files may be -// rerooted. -static StringRef rerootPath(StringRef path) { - if (!path::is_absolute(path, path::Style::posix) || path.endswith(".o")) - return path; - - if (Optional rerootedPath = - findPathCombination(path, config->systemLibraryRoots)) - return *rerootedPath; - - return path; -} - static Optional findFramework(StringRef name) { SmallString<260> symlink; StringRef suffix; @@ -244,7 +211,7 @@ static std::vector getArchiveMembers(MemoryBufferRef mb) { std::vector v; Error err = Error::success(); - // Thin archives refer to .o files, so --reproduces needs the .o files too. + // Thin archives refer to .o files, so --reproduce needs the .o files too. bool addToTar = archive->isThin() && tar; for (const Archive::Child &c : archive->children(err)) { @@ -925,6 +892,13 @@ bool macho::link(ArrayRef argsArr, bool canExitEarly, return true; } + config = make(); + symtab = make(); + target = createTargetInfo(args); + depTracker = + make(args.getLastArgValue(OPT_dependency_info)); + + config->systemLibraryRoots = getSystemLibraryRoots(args); if (const char *path = getReproduceOption(args)) { // Note that --reproduce is a debug option so you can ignore it // if you are trying to understand the whole picture of the code. @@ -939,13 +913,6 @@ bool macho::link(ArrayRef argsArr, bool canExitEarly, } } - config = make(); - symtab = make(); - target = createTargetInfo(args); - - depTracker = - make(args.getLastArgValue(OPT_dependency_info, "")); - if (auto *arg = args.getLastArg(OPT_threads_eq)) { StringRef v(arg->getValue()); unsigned threads = 0; @@ -1035,7 +1002,6 @@ bool macho::link(ArrayRef argsArr, bool canExitEarly, config->undefinedSymbolTreatment = getUndefinedSymbolTreatment(args); - config->systemLibraryRoots = getSystemLibraryRoots(args); config->librarySearchPaths = getLibrarySearchPaths(args, config->systemLibraryRoots); config->frameworkSearchPaths = diff --git a/lld/MachO/Driver.h b/lld/MachO/Driver.h index c1b677a..72f00cd 100644 --- a/lld/MachO/Driver.h +++ b/lld/MachO/Driver.h @@ -57,6 +57,17 @@ llvm::Optional loadDylib(llvm::MemoryBufferRef mbref, DylibFile *umbrella = nullptr, bool isBundleLoader = false); +// Search for all possible combinations of `{root}/{name}.{extension}`. +// If \p extensions are not specified, then just search for `{root}/{name}`. +llvm::Optional +findPathCombination(const llvm::Twine &name, + const std::vector &roots, + ArrayRef extensions = {""}); + +// If -syslibroot is specified, absolute paths to non-object files may be +// rerooted. +llvm::StringRef rerootPath(llvm::StringRef path); + llvm::Optional loadArchiveMember(MemoryBufferRef, uint32_t modTime, StringRef archiveName, bool objCOnly); diff --git a/lld/MachO/DriverUtils.cpp b/lld/MachO/DriverUtils.cpp index e0f6a35..d897eef 100644 --- a/lld/MachO/DriverUtils.cpp +++ b/lld/MachO/DriverUtils.cpp @@ -118,6 +118,14 @@ static std::string rewritePath(StringRef s) { return std::string(s); } +static std::string rewriteInputPath(StringRef s) { + // Don't bother rewriting "absolute" paths that are actually under the + // syslibroot; simply rewriting the syslibroot is sufficient. + if (rerootPath(s) == s && fs::exists(s)) + return relativeToRoot(s); + return std::string(s); +} + // Reconstructs command line arguments so that so that you can re-run // the same command with the same inputs. This is for --reproduce. std::string macho::createResponseFile(const InputArgList &args) { @@ -130,7 +138,7 @@ std::string macho::createResponseFile(const InputArgList &args) { case OPT_reproduce: break; case OPT_INPUT: - os << quote(rewritePath(arg->getValue())) << "\n"; + os << quote(rewriteInputPath(arg->getValue())) << "\n"; break; case OPT_o: os << "-o " << quote(path::filename(arg->getValue())) << "\n"; @@ -138,13 +146,17 @@ std::string macho::createResponseFile(const InputArgList &args) { case OPT_filelist: if (Optional buffer = readFile(arg->getValue())) for (StringRef path : args::getLines(*buffer)) - os << quote(rewritePath(path)) << "\n"; + os << quote(rewriteInputPath(path)) << "\n"; + break; + case OPT_force_load: + case OPT_weak_library: + os << arg->getSpelling() << " " + << quote(rewriteInputPath(arg->getValue())) << "\n"; break; case OPT_F: case OPT_L: case OPT_bundle_loader: case OPT_exported_symbols_list: - case OPT_force_load: case OPT_order_file: case OPT_rpath: case OPT_syslibroot: @@ -217,6 +229,36 @@ Optional macho::loadDylib(MemoryBufferRef mbref, return file; } +Optional +macho::findPathCombination(const Twine &name, + const std::vector &roots, + ArrayRef extensions) { + SmallString<261> base; + for (StringRef dir : roots) { + base = dir; + path::append(base, name); + for (StringRef ext : extensions) { + Twine location = base + ext; + if (fs::exists(location)) + return saver.save(location.str()); + else + depTracker->logFileNotFound(location); + } + } + return {}; +} + +StringRef macho::rerootPath(StringRef path) { + if (!path::is_absolute(path, path::Style::posix) || path.endswith(".o")) + return path; + + if (Optional rerootedPath = + findPathCombination(path, config->systemLibraryRoots)) + return *rerootedPath; + + return path; +} + Optional macho::loadArchiveMember(MemoryBufferRef mb, uint32_t modTime, StringRef archiveName, diff --git a/lld/test/MachO/reroot-path.s b/lld/test/MachO/reroot-path.s index b70c72e..ab3a018 100644 --- a/lld/test/MachO/reroot-path.s +++ b/lld/test/MachO/reroot-path.s @@ -23,14 +23,30 @@ # RUN: %lld -dylib %t/bar.o -o %t/%:t/libbar.dylib ## Test our various file-loading flags to make sure all bases are covered. -# RUN: %lld -lSystem -syslibroot %t %t/foo.a %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" -# RUN: %lld -lSystem -syslibroot %t -force_load %t/foo.a -force_load %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" -# RUN: %lld -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" -# RUN: %lld -lSystem -syslibroot %t -weak_library %t/libfoo.dylib -weak_library %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" +# RUN: %lld --reproduce %t/repro1.tar -lSystem -syslibroot %t %t/foo.a %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" +# RUN: tar xf %t/repro1.tar -C %t +# RUN: cd %t/repro1; ld64.lld @response.txt | FileCheck %s -DDIR="%:t/%:t" + +# RUN: %lld --reproduce %t/repro2.tar -lSystem -syslibroot %t -force_load %t/foo.a -force_load %t/bar.a %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" +# RUN: tar xf %t/repro2.tar -C %t +# RUN: cd %t/repro2; ld64.lld @response.txt | FileCheck %s -DDIR="%:t/%:t" + +# RUN: %lld --reproduce %t/repro3.tar -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" +# RUN: tar xf %t/repro3.tar -C %t +# RUN: cd %t/repro3; ld64.lld @response.txt | FileCheck %s -DDIR="%:t/%:t" + +# RUN: %lld --reproduce %t/repro4.tar -lSystem -syslibroot %t -weak_library %t/libfoo.dylib -weak_library %t/libbar.dylib %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" +# RUN: tar xf %t/repro4.tar -C %t +# RUN: cd %t/repro4; ld64.lld @response.txt | FileCheck %s -DDIR="%:t/%:t" + # RUN: echo "%t/libfoo.dylib" > %t/filelist # RUN: echo "%t/libbar.dylib" >> %t/filelist -# RUN: %lld -lSystem -syslibroot %t -filelist %t/filelist %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" -# CHECK: [[DIR]]/{{(lib)?}}bar +# RUN: %lld --reproduce %t/repro5.tar -lSystem -syslibroot %t -filelist %t/filelist %t/test.o -o /dev/null -t | FileCheck %s -DDIR="%t/%:t" +# RUN: tar xf %t/repro5.tar -C %t +# RUN: cd %t/repro5; ld64.lld @response.txt | FileCheck %s -DDIR="%:t/%:t" + +## The {{^}} ensures that we only match relative paths if DIR is relative. +# CHECK: {{^}}[[DIR]]/{{(lib)?}}bar ## Paths to object files don't get rerooted. # RUN: mv %t/bar.o %t/%:t/bar.o @@ -42,8 +58,15 @@ ## rerooted path takes precedence over the original path. We will get an ## undefined symbol error since we aren't loading %t/libfoo.dylib. # RUN: cp %t/%:t/libbar.dylib %t/%:t/libfoo.dylib -# RUN: not %lld -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o \ -# RUN: -o /dev/null 2>&1 | FileCheck %s --check-prefix=UNDEF +# RUN: not %lld --reproduce %t/repro6.tar -lSystem -syslibroot %t %t/libfoo.dylib %t/libbar.dylib %t/test.o \ +# RUN: -o /dev/null -t 2> %t/error | FileCheck %s -DDIR="%t/%:t" --check-prefix=FOO +# RUN: FileCheck %s --check-prefix=UNDEF < %t/error + +# RUN: tar xf %t/repro6.tar -C %t +# RUN: cd %t/repro6; not ld64.lld @response.txt 2> %t/error | FileCheck %s -DDIR="%:t/%:t" --check-prefix=FOO +# RUN: FileCheck %s --check-prefix=UNDEF < %t/error + +# FOO: [[DIR]]/libfoo.dylib # UNDEF: error: undefined symbol: _foo #--- foo.s