[lld] r267497 - [ELF] Introduce --reproduce flag.

Davide Italiano via llvm-commits llvm-commits at lists.llvm.org
Tue Apr 26 09:33:46 PDT 2016


On Mon, Apr 25, 2016 at 6:56 PM, Sean Silva <chisophugis at gmail.com> wrote:
>
>
> On Mon, Apr 25, 2016 at 5:22 PM, Davide Italiano via llvm-commits
> <llvm-commits at lists.llvm.org> wrote:
>>
>> Author: davide
>> Date: Mon Apr 25 19:22:24 2016
>> New Revision: 267497
>>
>> URL: http://llvm.org/viewvc/llvm-project?rev=267497&view=rev
>> Log:
>> [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
>>
>> Added:
>>     lld/trunk/test/ELF/reproduce.s
>> Modified:
>>     lld/trunk/ELF/Config.h
>>     lld/trunk/ELF/Driver.cpp
>>     lld/trunk/ELF/Options.td
>>
>> Modified: lld/trunk/ELF/Config.h
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=267497&r1=267496&r2=267497&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Config.h (original)
>> +++ lld/trunk/ELF/Config.h Mon Apr 25 19:22:24 2016
>> @@ -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;
>>
>> Modified: lld/trunk/ELF/Driver.cpp
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.cpp?rev=267497&r1=267496&r2=267497&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Driver.cpp (original)
>> +++ lld/trunk/ELF/Driver.cpp Mon Apr 25 19:22:24 2016
>> @@ -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(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");
>> +    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
>>    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 c
>>
>>    initLLVM(Args);
>>    readConfigs(Args);
>> +
>> +  if (!Config->Reproduce.empty())
>> +    dumpLinkerInvocation(ArgsArr);
>> +
>>    createFiles(Args);
>>    checkOptions(Args);
>>    if (HasError)
>> @@ -311,6 +352,8 @@ void LinkerDriver::readConfigs(opt::Inpu
>>    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);
>>
>>
>> Modified: lld/trunk/ELF/Options.td
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Options.td?rev=267497&r1=267496&r2=267497&view=diff
>>
>> ==============================================================================
>> --- lld/trunk/ELF/Options.td (original)
>> +++ lld/trunk/ELF/Options.td Mon Apr 25 19:22:24 2016
>> @@ -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">;
>>
>>
>> Added: lld/trunk/test/ELF/reproduce.s
>> URL:
>> http://llvm.org/viewvc/llvm-project/lld/trunk/test/ELF/reproduce.s?rev=267497&view=auto
>>
>> ==============================================================================
>> --- lld/trunk/test/ELF/reproduce.s (added)
>> +++ lld/trunk/test/ELF/reproduce.s Mon Apr 25 19:22:24 2016
>> @@ -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
>
>
> You probably want `%t.dir` or something like that instead of `%S` so that
> you avoid littering files in the source directory.
>
> -- Sean Silva
>
>>
>> +# RUN: not ld.lld %t -o %t2 --reproduce %S/repro2 2>&1 | FileCheck
>> --check-prefix=EDIR %s
>> +# EDIR: --reproduce: can't create directory
>>
>>
>> _______________________________________________
>> llvm-commits mailing list
>> llvm-commits at lists.llvm.org
>> http://lists.llvm.org/cgi-bin/mailman/listinfo/llvm-commits
>
>

Addressed both your concerns.
BTW, there's a problem I'm not still able to figure out (which
prevents this test to be enabled on Windows), and I'd like to hear
others' opinions.
My experience on Windows is fairly limited, so, maybe, the solution is
obvious to some of you.

Currently the test runs llvm-objdump like this:

 llvm-objdump -d %t.dir/repro/%t

%t will expand to c:/... so the path will contain two drive letters
(making it invalid).
I can transform the path in lld, e.g. replacing c: -> /c, but I'm not
entirely sure what's the correct way to handle this case in the test
(without hardcoding the path).
Any ideas?

Thanks!

-- 
Davide

"There are no solved problems; there are only problems that are more
or less solved" -- Henri Poincare


More information about the llvm-commits mailing list