diff options
| author | Davide Italiano <davide@freebsd.org> | 2016-04-26 00:22:24 +0000 |
|---|---|---|
| committer | Davide Italiano <davide@freebsd.org> | 2016-04-26 00:22:24 +0000 |
| commit | 034f58a9bd5cdf36e3dd1043bf2d4a9d82b0caab (patch) | |
| tree | dd874475495fbb6c3b928d3e6e1ea72eaaeb8a24 /lld | |
| parent | e74d91314abb82891dcd3e6f8ef6d91e4e97c981 (diff) | |
| download | bcm5719-llvm-034f58a9bd5cdf36e3dd1043bf2d4a9d82b0caab.tar.gz bcm5719-llvm-034f58a9bd5cdf36e3dd1043bf2d4a9d82b0caab.zip | |
[ELF] Introduce --reproduce flag.
--reproduce dumps the object files in a directory chosen
(preserving the file system layout) and the linker invocation
so that people can create an archive and upload for debugging.
Differential Revision: http://reviews.llvm.org/D19494
llvm-svn: 267497
Diffstat (limited to 'lld')
| -rw-r--r-- | lld/ELF/Config.h | 1 | ||||
| -rw-r--r-- | lld/ELF/Driver.cpp | 43 | ||||
| -rw-r--r-- | lld/ELF/Options.td | 3 | ||||
| -rw-r--r-- | lld/test/ELF/reproduce.s | 26 |
4 files changed, 73 insertions, 0 deletions
diff --git a/lld/ELF/Config.h b/lld/ELF/Config.h index 54ef5b771bb..b6d1d4caa75 100644 --- a/lld/ELF/Config.h +++ b/lld/ELF/Config.h @@ -48,6 +48,7 @@ struct Configuration { llvm::StringRef SoName; llvm::StringRef Sysroot; std::string RPath; + std::string Reproduce; std::vector<llvm::StringRef> DynamicList; std::vector<llvm::StringRef> SearchPaths; std::vector<llvm::StringRef> Undefined; diff --git a/lld/ELF/Driver.cpp b/lld/ELF/Driver.cpp index 3bf2a5327bb..52981594ead 100644 --- a/lld/ELF/Driver.cpp +++ b/lld/ELF/Driver.cpp @@ -19,6 +19,7 @@ #include "Writer.h" #include "lld/Driver/Driver.h" #include "llvm/ADT/StringExtras.h" +#include "llvm/Support/Path.h" #include "llvm/Support/TargetSelect.h" #include "llvm/Support/raw_ostream.h" #include <utility> @@ -97,12 +98,29 @@ LinkerDriver::getArchiveMembers(MemoryBufferRef MB) { 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"); + 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"); +} + // Opens and parses a file. Path has to be resolved already. // Newly created memory buffers are owned by this driver. void LinkerDriver::addFile(StringRef Path) { using namespace llvm::sys::fs; if (Config->Verbose) llvm::outs() << Path << "\n"; + if (!Config->Reproduce.empty()) + dumpFile(Path); + Optional<MemoryBufferRef> Buffer = readFile(Path); if (!Buffer.hasValue()) return; @@ -223,6 +241,25 @@ static bool hasZOption(opt::InputArgList &Args, StringRef Key) { 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"); + return; + } + + SmallString<128> InvocationPath; + sys::path::append(InvocationPath, Config->Reproduce, "invocation.txt"); + raw_fd_ostream OS(InvocationPath, EC, sys::fs::OpenFlags::F_None); + check(EC); + + OS << Args[0]; + for (unsigned I = 1, E = Args.size(); I < E; ++I) + OS << " " << Args[I]; + OS << "\n"; +} + void LinkerDriver::main(ArrayRef<const char *> ArgsArr) { ELFOptTable Parser; opt::InputArgList Args = Parser.parse(ArgsArr.slice(1)); @@ -237,6 +274,10 @@ void LinkerDriver::main(ArrayRef<const char *> ArgsArr) { initLLVM(Args); readConfigs(Args); + + if (!Config->Reproduce.empty()) + dumpLinkerInvocation(ArgsArr); + createFiles(Args); checkOptions(Args); if (HasError) @@ -311,6 +352,8 @@ void LinkerDriver::readConfigs(opt::InputArgList &Args) { Config->Fini = getString(Args, OPT_fini, "_fini"); Config->Init = getString(Args, OPT_init, "_init"); Config->OutputFile = getString(Args, OPT_o); + if (auto *Arg = Args.getLastArg(OPT_reproduce)) + Config->Reproduce = Arg->getValue(); Config->SoName = getString(Args, OPT_soname); Config->Sysroot = getString(Args, OPT_sysroot); diff --git a/lld/ELF/Options.td b/lld/ELF/Options.td index 09f96495b3d..4b8b1b9796d 100644 --- a/lld/ELF/Options.td +++ b/lld/ELF/Options.td @@ -120,6 +120,9 @@ def pie : Flag<["-"], "pie">, def print_gc_sections: Flag<["--"], "print-gc-sections">, HelpText<"List removed unused sections">; +def reproduce : Separate<["--"], "reproduce">, + HelpText<"Dump linker invocation and input files for debugging">; + def rpath : Separate<["-"], "rpath">, HelpText<"Add a DT_RUNPATH to the output">; diff --git a/lld/test/ELF/reproduce.s b/lld/test/ELF/reproduce.s new file mode 100644 index 00000000000..c1f5b05ea43 --- /dev/null +++ b/lld/test/ELF/reproduce.s @@ -0,0 +1,26 @@ +# REQUIRES: x86 + +# RUN: rm -rf %S/repro +# RUN: llvm-mc -filetype=obj -triple=x86_64-unknown-linux %s -o %t +# RUN: ld.lld %t -o %t2 -shared --as-needed --reproduce %S/repro +# RUN: llvm-objdump -d %S/repro/%t | FileCheck %s --check-prefix=DUMP +# RUN: cat %S/repro/invocation.txt | FileCheck %s --check-prefix=INVOCATION + +.globl _start; +_start: + mov $60, %rax + mov $42, %rdi + syscall + +# DUMP: Disassembly of section .text: +# DUMP: _start: +# DUMP: 0: 48 c7 c0 3c 00 00 00 movq $60, %rax +# DUMP: 7: 48 c7 c7 2a 00 00 00 movq $42, %rdi +# DUMP: e: 0f 05 syscall + +# INVOCATION: lld {{.*}}reproduce.s{{.*}} -o {{.*}} -shared --as-needed --reproduce + +# RUN: rm -rf %S/repro2 +# RUN: mkdir %S/repro2 +# RUN: not ld.lld %t -o %t2 --reproduce %S/repro2 2>&1 | FileCheck --check-prefix=EDIR %s +# EDIR: --reproduce: can't create directory |

