forked from OSchip/llvm-project
[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
This commit is contained in:
parent
e74d91314a
commit
034f58a9bd
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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">;
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
Loading…
Reference in New Issue