[lld] r269593 - Reorganize the cpio archiver as CpioFile class. NFC.

Rui Ueyama via llvm-commits llvm-commits at lists.llvm.org
Sun May 15 10:10:23 PDT 2016


Author: ruiu
Date: Sun May 15 12:10:23 2016
New Revision: 269593

URL: http://llvm.org/viewvc/llvm-project?rev=269593&view=rev
Log:
Reorganize the cpio archiver as CpioFile class. NFC.

This code separates the code to create cpio archive from the driver.

Modified:
    lld/trunk/ELF/Config.h
    lld/trunk/ELF/Driver.cpp
    lld/trunk/ELF/Driver.h
    lld/trunk/ELF/DriverUtils.cpp
    lld/trunk/ELF/InputFiles.cpp

Modified: lld/trunk/ELF/Config.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Config.h?rev=269593&r1=269592&r2=269593&view=diff
==============================================================================
--- lld/trunk/ELF/Config.h (original)
+++ lld/trunk/ELF/Config.h Sun May 15 12:10:23 2016
@@ -48,7 +48,6 @@ 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=269593&r1=269592&r2=269593&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.cpp (original)
+++ lld/trunk/ELF/Driver.cpp Sun May 15 12:10:23 2016
@@ -114,7 +114,8 @@ void LinkerDriver::addFile(StringRef Pat
     return;
   MemoryBufferRef MBRef = *Buffer;
 
-  maybeCopyInputFile(Path, MBRef.getBuffer());
+  if (Cpio)
+    Cpio->append(relativeToRoot(Path), MBRef.getBuffer());
 
   switch (identify_magic(MBRef.getBuffer())) {
   case file_magic::unknown:
@@ -252,15 +253,12 @@ void LinkerDriver::main(ArrayRef<const c
   readConfigs(Args);
   initLLVM(Args);
 
-  if (!Config->Reproduce.empty()) {
-    std::error_code EC;
-    std::string File = Config->Reproduce + ".cpio";
-    ReproduceArchive = llvm::make_unique<raw_fd_ostream>(File, EC, fs::F_None);
-    if (EC) {
-      error(EC, "--reproduce: failed to open " + File);
-      return;
-    }
-    createResponseFile(Args);
+  if (auto *Arg = Args.getLastArg(OPT_reproduce)) {
+    // Note that --reproduce is a debug option so you can ignore it
+    // if you are trying to understand the whole picture of the code.
+    Cpio.reset(CpioFile::create(Arg->getValue()));
+    if (Cpio)
+      Cpio->append("response.txt", createResponseFile(Args));
   }
 
   createFiles(Args);
@@ -340,7 +338,6 @@ 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);
-  Config->Reproduce = getString(Args, OPT_reproduce);
   Config->SoName = getString(Args, OPT_soname);
   Config->Sysroot = getString(Args, OPT_sysroot);
 

Modified: lld/trunk/ELF/Driver.h
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/Driver.h?rev=269593&r1=269592&r2=269593&view=diff
==============================================================================
--- lld/trunk/ELF/Driver.h (original)
+++ lld/trunk/ELF/Driver.h Sun May 15 12:10:23 2016
@@ -23,16 +23,15 @@ namespace elf {
 
 extern class LinkerDriver *Driver;
 
+class CpioFile;
+
 class LinkerDriver {
 public:
   void main(ArrayRef<const char *> Args);
   void addFile(StringRef Path);
   void addLibrary(StringRef Name);
-  llvm::LLVMContext Context;
-
-  // for --reproduce
-  std::unique_ptr<llvm::raw_fd_ostream> ReproduceArchive;
-  llvm::StringSet<> IncludedFiles;
+  llvm::LLVMContext Context;      // to parse bitcode ifles
+  std::unique_ptr<CpioFile> Cpio; // for reproduce
 
 private:
   std::vector<MemoryBufferRef> getArchiveMembers(MemoryBufferRef MB);
@@ -70,12 +69,37 @@ enum {
 #undef OPTION
 };
 
+// This is the class to create a .cpio file for --reproduce.
+//
+// If "--reproduce foo" is given, we create a file "foo.cpio" and
+// copy all input files to the archive, along with a response file
+// to re-run the same command with the same inputs.
+// It is useful for reporting issues to LLD developers.
+//
+// Cpio as a file format is a deliberate choice. It's standardized in
+// POSIX and very easy to create. cpio command is available virtually
+// on all Unix systems. See
+// http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_07
+// for the format details.
+class CpioFile {
+public:
+  static CpioFile *create(StringRef OutputPath);
+  void append(StringRef Path, StringRef Data);
+
+private:
+  CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef Basename);
+
+  std::unique_ptr<llvm::raw_fd_ostream> OS;
+  llvm::StringSet<> Seen;
+  std::string Basename;
+};
+
 void printHelp(const char *Argv0);
 void printVersion();
 std::vector<uint8_t> parseHexstring(StringRef S);
 
-void createResponseFile(const llvm::opt::InputArgList &Args);
-void maybeCopyInputFile(StringRef Path, StringRef Buffer);
+std::string createResponseFile(const llvm::opt::InputArgList &Args);
+std::string relativeToRoot(StringRef Path);
 
 std::string findFromSearchPaths(StringRef Path);
 std::string searchLibrary(StringRef Path);

Modified: lld/trunk/ELF/DriverUtils.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/DriverUtils.cpp?rev=269593&r1=269592&r2=269593&view=diff
==============================================================================
--- lld/trunk/ELF/DriverUtils.cpp (original)
+++ lld/trunk/ELF/DriverUtils.cpp Sun May 15 12:10:23 2016
@@ -107,7 +107,7 @@ std::vector<uint8_t> elf::parseHexstring
 // Makes a given pathname an absolute path first, and then remove
 // beginning /. For example, "../foo.o" is converted to "home/john/foo.o",
 // assuming that the current directory is "/home/john/bar".
-static std::string relativeToRoot(StringRef Path) {
+std::string elf::relativeToRoot(StringRef Path) {
   SmallString<128> Abs = Path;
   if (std::error_code EC = fs::make_absolute(Abs))
     fatal("make_absolute failed: " + EC.message());
@@ -127,22 +127,26 @@ static std::string relativeToRoot(String
   return Res.str();
 }
 
-static std::string getDestPath(StringRef Path) {
-  std::string Relpath = relativeToRoot(Path);
-  SmallString<128> Dest;
-  path::append(Dest, path::filename(Config->Reproduce), Relpath);
-  return Dest.str();
-}
+CpioFile::CpioFile(std::unique_ptr<llvm::raw_fd_ostream> OS, StringRef S)
+    : OS(std::move(OS)), Basename(S) {}
 
-static void maybePrintCpioMemberAux(raw_fd_ostream &OS, StringRef Path,
-                                    StringRef Data) {
-  OS << "070707"; // c_magic
-
-  // The c_dev/c_ino pair should be unique according to the spec, but no one
-  // seems to care.
-  OS << "000000"; // c_dev
-  OS << "000000"; // c_ino
+CpioFile *CpioFile::create(StringRef OutputPath) {
+  std::string Path = (OutputPath + ".cpio").str();
+  std::error_code EC;
+  auto OS = llvm::make_unique<raw_fd_ostream>(Path, EC, fs::F_None);
+  if (EC) {
+    error(EC, "--reproduce: failed to open " + Path);
+    return nullptr;
+  }
+  return new CpioFile(std::move(OS), path::filename(OutputPath));
+}
 
+static void writeMember(raw_fd_ostream &OS, StringRef Path, StringRef Data) {
+  // The c_dev/c_ino pair should be unique according to the spec,
+  // but no one seems to care.
+  OS << "070707";                        // c_magic
+  OS << "000000";                        // c_dev
+  OS << "000000";                        // c_ino
   OS << "100664";                        // c_mode: C_ISREG | rw-rw-r--
   OS << "000000";                        // c_uid
   OS << "000000";                        // c_gid
@@ -155,28 +159,22 @@ static void maybePrintCpioMemberAux(raw_
   OS << Data;                            // c_filedata
 }
 
-static void maybePrintCpioMember(StringRef Path, StringRef Data) {
-  if (Config->Reproduce.empty())
+void CpioFile::append(StringRef Path, StringRef Data) {
+  if (!Seen.insert(Path).second)
     return;
 
-  if (!Driver->IncludedFiles.insert(Path).second)
-    return;
-  raw_fd_ostream &OS = *Driver->ReproduceArchive;
-  maybePrintCpioMemberAux(OS, Path, Data);
-
-  // Print the trailer and seek back. This way we have a valid archive if we
-  // crash.
-  // See http://pubs.opengroup.org/onlinepubs/9699919799/utilities/pax.html#tag_20_92_13_11
-  // for the format details.
-  uint64_t Pos = OS.tell();
-  maybePrintCpioMemberAux(OS, "TRAILER!!!", "");
-  OS.seek(Pos);
-}
-
-// Write file Src with content Data to the archive.
-void elf::maybeCopyInputFile(StringRef Src, StringRef Data) {
-  std::string Dest = getDestPath(Src);
-  maybePrintCpioMember(Dest, Data);
+  // Construct an in-archive filename so that /home/foo/bar is stored
+  // as baz/home/foo/bar where baz is the basename of the output file.
+  // (i.e. in that case we are creating baz.cpio.)
+  SmallString<128> Fullpath;
+  path::append(Fullpath, Basename, Path);
+  writeMember(*OS, Fullpath, Data);
+
+  // Print the trailer and seek back.
+  // This way we have a valid archive if we crash.
+  uint64_t Pos = OS->tell();
+  writeMember(*OS, "TRAILER!!!", "");
+  OS->seek(Pos);
 }
 
 // Quote a given string if it contains a space character.
@@ -202,15 +200,13 @@ static std::string stringize(opt::Arg *A
   return K + " " + V;
 }
 
-// Copies all input files to Config->Reproduce directory and
-// create a response file as "response.txt", so that you can re-run
-// the same command with the same inputs just by executing
-// "ld.lld @response.txt". Used by --reproduce. This feature is
-// supposed to be used by users to report an issue to LLD developers.
-void elf::createResponseFile(const opt::InputArgList &Args) {
+// Reconstructs command line arguments so that so that you can re-run
+// the same command with the same inputs. This is for --reproduce.
+std::string elf::createResponseFile(const opt::InputArgList &Args) {
   SmallString<0> Data;
   raw_svector_ostream OS(Data);
-  // Copy the command line to response.txt while rewriting paths.
+
+  // Copy the command line to the output while rewriting paths.
   for (auto *Arg : Args) {
     switch (Arg->getOption().getID()) {
     case OPT_reproduce:
@@ -230,10 +226,7 @@ void elf::createResponseFile(const opt::
       OS << stringize(Arg) << "\n";
     }
   }
-
-  SmallString<128> Dest;
-  path::append(Dest, path::filename(Config->Reproduce), "response.txt");
-  maybePrintCpioMember(Dest, Data);
+  return Data.str();
 }
 
 std::string elf::findFromSearchPaths(StringRef Path) {

Modified: lld/trunk/ELF/InputFiles.cpp
URL: http://llvm.org/viewvc/llvm-project/lld/trunk/ELF/InputFiles.cpp?rev=269593&r1=269592&r2=269593&view=diff
==============================================================================
--- lld/trunk/ELF/InputFiles.cpp (original)
+++ lld/trunk/ELF/InputFiles.cpp Sun May 15 12:10:23 2016
@@ -394,8 +394,9 @@ MemoryBufferRef ArchiveFile::getMember(c
             "could not get the buffer for the member defining symbol " +
                 Sym->getName());
 
-  if (C.getParent()->isThin())
-    maybeCopyInputFile(check(C.getFullName()), Ret.getBuffer());
+  if (C.getParent()->isThin() && Driver->Cpio)
+    Driver->Cpio->append(relativeToRoot(check(C.getFullName())),
+                         Ret.getBuffer());
 
   return Ret;
 }




More information about the llvm-commits mailing list