summaryrefslogtreecommitdiffstats
path: root/lld
diff options
context:
space:
mode:
authorDavide Italiano <davide@freebsd.org>2016-04-26 00:22:24 +0000
committerDavide Italiano <davide@freebsd.org>2016-04-26 00:22:24 +0000
commit034f58a9bd5cdf36e3dd1043bf2d4a9d82b0caab (patch)
treedd874475495fbb6c3b928d3e6e1ea72eaaeb8a24 /lld
parente74d91314abb82891dcd3e6f8ef6d91e4e97c981 (diff)
downloadbcm5719-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.h1
-rw-r--r--lld/ELF/Driver.cpp43
-rw-r--r--lld/ELF/Options.td3
-rw-r--r--lld/test/ELF/reproduce.s26
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
OpenPOWER on IntegriCloud