[lld] r267600 - Handle Windows drive letters and ".." for --reproduce.
Rui Ueyama via llvm-commits
llvm-commits at lists.llvm.org
Tue Apr 26 13:36:46 PDT 2016
Author: ruiu
Date: Tue Apr 26 15:36:46 2016
New Revision: 267600
URL: http://llvm.org/viewvc/llvm-project?rev=267600&view=rev
Log:
Handle Windows drive letters and ".." for --reproduce.
When --reproduce <path> is given, then we need to concatenate input
file paths to the given path to save input files to the directory.
Previously, path concatenation didn't handle Windows drive letters
so it could generate invalid paths such as "C:\D:\foo". It also didn't
handle ".." path components, so it could produce some bad paths
such as "foo/../../etc/passwd".
In this patch, Windows drive letters and ".." are removed before
concatenating paths.
Differential Revision: http://reviews.llvm.org/D19551
Modified:
lld/trunk/ELF/Driver.cpp
lld/trunk/test/ELF/reproduce.s
Modified: lld/trunk/ELF/Driver.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=267600&r1=267599&r2=267600&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Tue Apr 26 15:36:46 2016
@@ -27,6 +27,7 @@
using namespace llvm;
using namespace llvm::ELF;
using namespace llvm::object;
+using namespace llvm::sys;
using namespace lld;
using namespace lld::elf;
@@ -98,18 +99,31 @@ LinkerDriver::getArchiveMembers(MemoryBu
return V;
}
-static void dumpFile(StringRef SrcPath) {
- SmallString<128> DirName;
- sys::path::append(DirName, Config->Reproduce, sys::path::parent_path(SrcPath));
- if (std::error_code EC = sys::fs::create_directories(DirName)) {
- error(EC, "--reproduce: can't create directory");
+// Concatenates S and T so that the resulting path becomes S/T.
+// There are a few exceptions:
+//
+// 1. The result will never escape from S. Therefore, all ".."
+// are removed from T before concatenatig them.
+// 2. Windows drive letters are removed from T before concatenation.
+static std::string concat(StringRef S, StringRef T) {
+ // Remove leading '/' or a drive letter, and then remove "..".
+ SmallString<128> T2(path::relative_path(T));
+ path::remove_dots(T2, /*remove_dot_dot=*/true);
+
+ SmallString<128> Res;
+ path::append(Res, S, T2);
+ return Res.str();
+}
+
+static void copyFile(StringRef Src, StringRef Dest) {
+ SmallString<128> Dir(Dest);
+ path::remove_filename(Dir);
+ if (std::error_code EC = sys::fs::create_directories(Dir)) {
+ error(EC, Dir + ": can't create directory");
return;
}
-
- SmallString<128> DestPathName;
- sys::path::append(DestPathName, Config->Reproduce, SrcPath);
- if (std::error_code EC = sys::fs::copy_file(SrcPath, DestPathName))
- error(EC, "--reproduce: can't copy file");
+ if (std::error_code EC = sys::fs::copy_file(Src, Dest))
+ error(EC, "failed to copy file: " + Dest);
}
// Opens and parses a file. Path has to be resolved already.
@@ -119,7 +133,7 @@ void LinkerDriver::addFile(StringRef Pat
if (Config->Verbose)
llvm::outs() << Path << "\n";
if (!Config->Reproduce.empty())
- dumpFile(Path);
+ copyFile(Path, concat(Config->Reproduce, Path));
Optional<MemoryBufferRef> Buffer = readFile(Path);
if (!Buffer.hasValue())
@@ -241,21 +255,21 @@ static bool hasZOption(opt::InputArgList
return false;
}
-static void dumpLinkerInvocation(ArrayRef<const char *> Args) {
- std::error_code EC = sys::fs::create_directories(Config->Reproduce,
- false /* IgnoreExisting */);
- if (EC) {
- error(EC, "--reproduce: can't create directory");
+static void logCommandline(ArrayRef<const char *> Args) {
+ if (std::error_code EC = sys::fs::create_directories(
+ Config->Reproduce, /*IgnoreExisting=*/false)) {
+ error(EC, Config->Reproduce + ": can't create directory");
return;
}
- SmallString<128> InvocationPath;
- sys::path::append(InvocationPath, Config->Reproduce, "invocation.txt");
- raw_fd_ostream OS(InvocationPath, EC, sys::fs::OpenFlags::F_None);
+ SmallString<128> Path;
+ path::append(Path, Config->Reproduce, "invocation.txt");
+ std::error_code EC;
+ raw_fd_ostream OS(Path, EC, sys::fs::OpenFlags::F_None);
check(EC);
OS << Args[0];
- for (unsigned I = 1, E = Args.size(); I < E; ++I)
+ for (size_t I = 1, E = Args.size(); I < E; ++I)
OS << " " << Args[I];
OS << "\n";
}
@@ -276,7 +290,7 @@ void LinkerDriver::main(ArrayRef<const c
readConfigs(Args);
if (!Config->Reproduce.empty())
- dumpLinkerInvocation(ArgsArr);
+ logCommandline(ArgsArr);
createFiles(Args);
checkOptions(Args);
Modified: lld/trunk/test/ELF/reproduce.s
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/reproduce.s?rev=267600&r1=267599&r2=267600&view=diff
==============================================================================
--- lld/trunk/test/ELF/reproduce.s (original)
+++ lld/trunk/test/ELF/reproduce.s Tue Apr 26 15:36:46 2016
@@ -1,21 +1,27 @@
# REQUIRES: x86
-# RUN: rm -rf %t.dir1
-# RUN: mkdir -p %t.dir1/build
-# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir1/build/foo.o
-# RUN: cd %t.dir1
-# RUN: ld.lld build/foo.o -o bar -shared --as-needed --reproduce repro
-# RUN: diff build/foo.o repro/build/foo.o
+# RUN: rm -rf %t.dir
+# RUN: mkdir -p %t.dir/build1
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build1/foo.o
+# RUN: cd %t.dir
+# RUN: ld.lld build1/foo.o -o bar -shared --as-needed --reproduce repro
+# RUN: diff build1/foo.o repro/build1/foo.o
+
+# RUN: FileCheck %s --check-prefix=INVOCATION < repro/invocation.txt
+# INVOCATION: lld{{[^\s]*}} build1/foo.o -o bar -shared --as-needed --reproduce repro
+
+# RUN: mkdir -p %t.dir/build2/a/b/c
+# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t.dir/build2/foo.o
+# RUN: cd %t.dir/build2/a/b/c
+# RUN: ld.lld ./../../../foo.o -o bar -shared --as-needed --reproduce repro
+# RUN: diff %t.dir/build2/foo.o repro/foo.o
+
+# RUN: not ld.lld build1/foo.o -o bar -shared --as-needed --reproduce . 2>&1 \
+# RUN: | FileCheck --check-prefix=ERROR %s
+# ERROR: can't create directory
.globl _start
_start:
mov $60, %rax
mov $42, %rdi
syscall
-
-# RUN: FileCheck %s --check-prefix=INVOCATION < repro/invocation.txt
-# INVOCATION: lld{{[^\s]*}} build/foo.o -o bar -shared --as-needed --reproduce repro
-
-# RUN: not ld.lld build/foo.o -o bar -shared --as-needed --reproduce repro 2>&1 \
-# RUN: | FileCheck --check-prefix=ERROR %s
-# ERROR: --reproduce: can't create directory
More information about the llvm-commits
mailing list