JDevlieghere created this revision.
JDevlieghere added reviewers: labath, arphaman, aprantl.
JDevlieghere added a project: LLDB.
Herald added subscribers: teemperor, abidh, dexonsmith, hiraditya, mgorny.
JDevlieghere added a parent revision: D76671: [FileCollector] Add a method to 
add a whole directory and it contents..

The FileCollector in LLDB collects every files that's used during a debug 
session when capture is enabled. This ensures that the reproducer only contains 
the files necessary to reproduce. This approach is not a good fit for the dSYM 
bundle, which is a directory on disk, but should be treated as a single unit. 
On macOS LLDB have automatically find the matching dSYM for a binary by its 
UUID. Having a incomplete dSYM in a reproducer can break debugging even when 
reproducers are disabled.

This patch adds a custom FileCollector to LLDB that is aware of dSYM. When it 
encounters a dSYM bundle, it iterates over everything inside it and adds it to 
the reproducer. While this might seem like overkill right now, having custom 
FileCollector is going to be inevitable as soon as we want to be smarter in 
what we include in the reproducer. For example, to keep its size small, we 
might want to skip system libraries in the future.


Repository:
  rLLDB LLDB

https://reviews.llvm.org/D76672

Files:
  lldb/include/lldb/Host/FileSystem.h
  lldb/include/lldb/Utility/FileCollector.h
  lldb/include/lldb/Utility/Reproducer.h
  lldb/source/Utility/CMakeLists.txt
  lldb/source/Utility/FileCollector.cpp
  lldb/test/Shell/Reproducer/TestDSYM.test
  llvm/include/llvm/Support/FileCollector.h
  llvm/lib/Support/FileCollector.cpp

Index: llvm/lib/Support/FileCollector.cpp
===================================================================
--- llvm/lib/Support/FileCollector.cpp
+++ llvm/lib/Support/FileCollector.cpp
@@ -61,26 +61,25 @@
   return true;
 }
 
-void FileCollector::addFile(const Twine &file) {
-  std::lock_guard<std::mutex> lock(Mutex);
-  std::string FileStr = file.str();
-  if (markAsSeen(FileStr))
-    addFileImpl(FileStr);
-}
+void FileCollector::addFile(const Twine &file) { addFileImpl(file.str()); }
 
 void FileCollector::addDirectory(const Twine &dir) {
   assert(sys::fs::is_directory(dir));
   std::error_code EC;
   sys::fs::recursive_directory_iterator Iter(dir, EC);
   sys::fs::recursive_directory_iterator End;
-  addFile(dir); // Add the directory in case it's empty.
+  addFileImpl(dir.str()); // Add the directory in case it's empty.
   for (; Iter != End && !EC; Iter.increment(EC)) {
     if (sys::fs::is_regular_file(Iter->path()))
-      addFile(Iter->path());
+      addFileImpl(Iter->path());
   }
 }
 
 void FileCollector::addFileImpl(StringRef SrcPath) {
+  std::lock_guard<std::mutex> lock(Mutex);
+  if (!markAsSeen(SrcPath))
+    return;
+
   // We need an absolute src path to append to the root.
   SmallString<256> AbsoluteSrc = SrcPath;
   sys::fs::make_absolute(AbsoluteSrc);
Index: llvm/include/llvm/Support/FileCollector.h
===================================================================
--- llvm/include/llvm/Support/FileCollector.h
+++ llvm/include/llvm/Support/FileCollector.h
@@ -45,7 +45,7 @@
   createCollectorVFS(IntrusiveRefCntPtr<vfs::FileSystem> BaseFS,
                      std::shared_ptr<FileCollector> Collector);
 
-private:
+protected:
   void addFileImpl(StringRef SrcPath);
 
   bool markAsSeen(StringRef Path) {
@@ -60,7 +60,6 @@
     VFSWriter.addFileMapping(VirtualPath, RealPath);
   }
 
-protected:
   /// Synchronizes adding files.
   std::mutex Mutex;
 
Index: lldb/test/Shell/Reproducer/TestDSYM.test
===================================================================
--- /dev/null
+++ lldb/test/Shell/Reproducer/TestDSYM.test
@@ -0,0 +1,11 @@
+# REQUIRES: system-darwin
+# Ensure that the reproducers captures the whole dSYM bundle.
+
+# RUN: rm -rf %t.repro
+# RUN: %clang_host %S/Inputs/simple.c -g -o %t.out
+# RUN: touch %t.out.dSYM/foo.bar
+
+# RUN: %lldb -x -b --capture --capture-path %t.repro %t.out -o 'b main' -o 'run' -o 'reproducer generate'
+
+# RUN: %lldb -b -o 'reproducer dump -p files -f %t.repro' | FileCheck %s --check-prefix FILES
+# FILES: foo.bar
Index: lldb/source/Utility/FileCollector.cpp
===================================================================
--- /dev/null
+++ lldb/source/Utility/FileCollector.cpp
@@ -0,0 +1,43 @@
+//===-- FileCollector.cpp ---------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Utility/FileCollector.h"
+#include "llvm/ADT/SmallString.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/Process.h"
+
+using namespace lldb_private;
+
+void FileCollector::addFile(const llvm::Twine &file) {
+  // Add dSYM bundle if applicable.
+  if (addDSYM(file))
+    return;
+
+  // Add the file.
+  addFileImpl(file.str());
+}
+
+bool FileCollector::addDSYM(const llvm::Twine &file) {
+  auto begin = llvm::sys::path::begin(file.str());
+  auto end = llvm::sys::path::end(file.str());
+  llvm::SmallString<128> bundle;
+  for (auto it = begin; it != end; ++it) {
+    if (llvm::sys::path::extension(*it).lower() == ".dsym") {
+      llvm::sys::path::append(bundle, begin, ++it);
+      break;
+    }
+  }
+
+  // If bundle is empty the path is not a dSYM.
+  if (bundle.empty())
+    return false;
+
+  llvm::FileCollector::addDirectory(bundle.str());
+  return true;
+}
Index: lldb/source/Utility/CMakeLists.txt
===================================================================
--- lldb/source/Utility/CMakeLists.txt
+++ lldb/source/Utility/CMakeLists.txt
@@ -24,6 +24,7 @@
   DataExtractor.cpp
   Environment.cpp
   Event.cpp
+  FileCollector.cpp
   FileSpec.cpp
   GDBRemote.cpp
   IOObject.cpp
Index: lldb/include/lldb/Utility/Reproducer.h
===================================================================
--- lldb/include/lldb/Utility/Reproducer.h
+++ lldb/include/lldb/Utility/Reproducer.h
@@ -9,10 +9,10 @@
 #ifndef LLDB_UTILITY_REPRODUCER_H
 #define LLDB_UTILITY_REPRODUCER_H
 
+#include "lldb/Utility/FileCollector.h"
 #include "lldb/Utility/FileSpec.h"
 #include "llvm/ADT/DenseMap.h"
 #include "llvm/Support/Error.h"
-#include "llvm/Support/FileCollector.h"
 #include "llvm/Support/YAMLTraits.h"
 
 #include <mutex>
@@ -90,13 +90,11 @@
 
   FileProvider(const FileSpec &directory)
       : Provider(directory),
-        m_collector(std::make_shared<llvm::FileCollector>(
+        m_collector(std::make_shared<FileCollector>(
             directory.CopyByAppendingPathComponent("root").GetPath(),
             directory.GetPath())) {}
 
-  std::shared_ptr<llvm::FileCollector> GetFileCollector() {
-    return m_collector;
-  }
+  std::shared_ptr<FileCollector> GetFileCollector() { return m_collector; }
 
   void Keep() override {
     auto mapping = GetRoot().CopyByAppendingPathComponent(Info::file);
@@ -109,7 +107,7 @@
   static char ID;
 
 private:
-  std::shared_ptr<llvm::FileCollector> m_collector;
+  std::shared_ptr<FileCollector> m_collector;
 };
 
 /// Provider for the LLDB version number.
Index: lldb/include/lldb/Utility/FileCollector.h
===================================================================
--- /dev/null
+++ lldb/include/lldb/Utility/FileCollector.h
@@ -0,0 +1,31 @@
+//===-- FileCollector.h -----------------------------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLDD_SUPPORT_FILE_COLLECTOR_H
+#define LLDD_SUPPORT_FILE_COLLECTOR_H
+
+#include "llvm/Support/FileCollector.h"
+
+#include <mutex>
+
+namespace lldb_private {
+
+class FileCollector : public llvm::FileCollector {
+public:
+  FileCollector(std::string Root, std::string OverlayRoot)
+      : llvm::FileCollector(Root, OverlayRoot) {}
+
+  void addFile(const llvm::Twine &file) override;
+
+private:
+  bool addDSYM(const llvm::Twine &file);
+};
+
+} // namespace lldb_private
+
+#endif // LLVM_SUPPORT_FILE_COLLECTOR_H
Index: lldb/include/lldb/Host/FileSystem.h
===================================================================
--- lldb/include/lldb/Host/FileSystem.h
+++ lldb/include/lldb/Host/FileSystem.h
@@ -11,12 +11,12 @@
 
 #include "lldb/Host/File.h"
 #include "lldb/Utility/DataBufferLLVM.h"
+#include "lldb/Utility/FileCollector.h"
 #include "lldb/Utility/FileSpec.h"
 #include "lldb/Utility/Status.h"
 
 #include "llvm/ADT/Optional.h"
 #include "llvm/Support/Chrono.h"
-#include "llvm/Support/FileCollector.h"
 #include "llvm/Support/VirtualFileSystem.h"
 
 #include "lldb/lldb-types.h"
@@ -34,7 +34,7 @@
   FileSystem()
       : m_fs(llvm::vfs::getRealFileSystem()), m_collector(nullptr),
         m_mapped(false) {}
-  FileSystem(std::shared_ptr<llvm::FileCollector> collector)
+  FileSystem(std::shared_ptr<FileCollector> collector)
       : m_fs(llvm::vfs::getRealFileSystem()), m_collector(collector),
         m_mapped(false) {}
   FileSystem(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs,
@@ -47,7 +47,7 @@
   static FileSystem &Instance();
 
   static void Initialize();
-  static void Initialize(std::shared_ptr<llvm::FileCollector> collector);
+  static void Initialize(std::shared_ptr<FileCollector> collector);
   static llvm::Error Initialize(const FileSpec &mapping);
   static void Initialize(llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> fs);
   static void Terminate();
@@ -190,7 +190,7 @@
   void AddFile(const llvm::Twine &file);
   static llvm::Optional<FileSystem> &InstanceImpl();
   llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem> m_fs;
-  std::shared_ptr<llvm::FileCollector> m_collector;
+  std::shared_ptr<FileCollector> m_collector;
   bool m_mapped;
 };
 } // namespace lldb_private
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to