JDevlieghere created this revision.
JDevlieghere added reviewers: bulbazord, clayborg, jingham, jasonmolenda.
Herald added a project: All.
JDevlieghere requested review of this revision.

Add two new `source` subcommands: `source cache dump` and `source cache clear`. 
As the name implies the first one dumps the source cache while the later clears 
the cache.

This patch was motivated by a handful of (internal) bug reports related to 
sources not being available. Right now those issues can be hard to diagnose. 
The new commands give users, as well as us as developers, more insight into and 
control over the source cache.


https://reviews.llvm.org/D153685

Files:
  lldb/include/lldb/Core/Debugger.h
  lldb/include/lldb/Core/SourceManager.h
  lldb/source/Commands/CommandObjectSource.cpp
  lldb/source/Core/SourceManager.cpp
  lldb/test/API/source-manager/TestSourceManager.py

Index: lldb/test/API/source-manager/TestSourceManager.py
===================================================================
--- lldb/test/API/source-manager/TestSourceManager.py
+++ lldb/test/API/source-manager/TestSourceManager.py
@@ -317,3 +317,24 @@
                 "that has no source code associated " "with it.",
             ],
         )
+
+    def test_source_cache_dump_and_clear(self):
+        self.build()
+        exe = self.getBuildArtifact("a.out")
+        self.runCmd("file " + exe, CURRENT_EXECUTABLE_SET)
+        lldbutil.run_break_set_by_file_and_line(
+            self, self.file, self.line, num_expected_locations=1, loc_exact=True
+        )
+        self.runCmd("run", RUN_SUCCEEDED)
+
+        # Make sure the main source file is in the source cache.
+        self.expect(
+            "source cache dump",
+            substrs=["Modification time", "Lines", "Path", " 7", self.file],
+        )
+
+        # Clear the cache.
+        self.expect("source cache clear")
+
+        # Make sure the main source file is no longer in the source cache.
+        self.expect("source cache dump", matching=False, substrs=[self.file])
Index: lldb/source/Core/SourceManager.cpp
===================================================================
--- lldb/source/Core/SourceManager.cpp
+++ lldb/source/Core/SourceManager.cpp
@@ -727,3 +727,15 @@
     file_sp = pos->second;
   return file_sp;
 }
+
+void SourceManager::SourceFileCache::Dump(Stream &stream) const {
+  stream << "Modification time   Lines    Path\n";
+  stream << "------------------- -------- --------------------------------\n";
+  for (auto &entry : m_file_cache) {
+    if (!entry.second)
+      continue;
+    FileSP file = entry.second;
+    stream.Format("{0:%Y-%m-%d %H:%M:%S} {1,8:d} {2}\n", file->GetTimestamp(),
+                  file->GetNumLines(), entry.first.GetPath());
+  }
+}
Index: lldb/source/Commands/CommandObjectSource.cpp
===================================================================
--- lldb/source/Commands/CommandObjectSource.cpp
+++ lldb/source/Commands/CommandObjectSource.cpp
@@ -1201,6 +1201,62 @@
   std::string m_reverse_name;
 };
 
+class CommandObjectSourceCacheDump : public CommandObjectParsed {
+public:
+  CommandObjectSourceCacheDump(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "source cache dump",
+                            "Dump the state of the source code cache.\n"
+                            "Intended to be used for debugging LLDB itself.",
+                            nullptr) {}
+
+  ~CommandObjectSourceCacheDump() override = default;
+
+protected:
+  bool DoExecute(Args &command, CommandReturnObject &result) override {
+    SourceManager::SourceFileCache &cache = GetDebugger().GetSourceFileCache();
+    cache.Dump(result.GetOutputStream());
+    result.SetStatus(eReturnStatusSuccessFinishResult);
+    return result.Succeeded();
+  }
+};
+
+class CommandObjectSourceCacheClear : public CommandObjectParsed {
+public:
+  CommandObjectSourceCacheClear(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "source cache clear",
+                            "Clear the source code cache.\n", nullptr) {}
+
+  ~CommandObjectSourceCacheClear() override = default;
+
+protected:
+  bool DoExecute(Args &command, CommandReturnObject &result) override {
+    SourceManager::SourceFileCache &cache = GetDebugger().GetSourceFileCache();
+    cache.Clear();
+    result.SetStatus(eReturnStatusSuccessFinishNoResult);
+    return result.Succeeded();
+  }
+};
+
+class CommandObjectSourceCache : public CommandObjectMultiword {
+public:
+  CommandObjectSourceCache(CommandInterpreter &interpreter)
+      : CommandObjectMultiword(interpreter, "source cache",
+                               "Commands for managing the source code cache.",
+                               "source cache <sub-command>") {
+    LoadSubCommand(
+        "dump", CommandObjectSP(new CommandObjectSourceCacheDump(interpreter)));
+    LoadSubCommand("clear", CommandObjectSP(new CommandObjectSourceCacheClear(
+                                interpreter)));
+  }
+
+  ~CommandObjectSourceCache() override = default;
+
+private:
+  CommandObjectSourceCache(const CommandObjectSourceCache &) = delete;
+  const CommandObjectSourceCache &
+  operator=(const CommandObjectSourceCache &) = delete;
+};
+
 #pragma mark CommandObjectMultiwordSource
 // CommandObjectMultiwordSource
 
@@ -1216,6 +1272,8 @@
                  CommandObjectSP(new CommandObjectSourceInfo(interpreter)));
   LoadSubCommand("list",
                  CommandObjectSP(new CommandObjectSourceList(interpreter)));
+  LoadSubCommand("cache",
+                 CommandObjectSP(new CommandObjectSourceCache(interpreter)));
 }
 
 CommandObjectMultiwordSource::~CommandObjectMultiwordSource() = default;
Index: lldb/include/lldb/Core/SourceManager.h
===================================================================
--- lldb/include/lldb/Core/SourceManager.h
+++ lldb/include/lldb/Core/SourceManager.h
@@ -65,6 +65,8 @@
 
     uint32_t GetNumLines();
 
+    llvm::sys::TimePoint<> GetTimestamp() const { return m_mod_time; }
+
   protected:
     bool CalculateLineOffsets(uint32_t line = UINT32_MAX);
 
@@ -105,6 +107,8 @@
     // Removes all elements from the cache.
     void Clear() { m_file_cache.clear(); }
 
+    void Dump(Stream &stream) const;
+
   protected:
     typedef std::map<FileSpec, FileSP> FileCache;
     FileCache m_file_cache;
Index: lldb/include/lldb/Core/Debugger.h
===================================================================
--- lldb/include/lldb/Core/Debugger.h
+++ lldb/include/lldb/Core/Debugger.h
@@ -76,8 +76,6 @@
 class Debugger : public std::enable_shared_from_this<Debugger>,
                  public UserID,
                  public Properties {
-  friend class SourceManager; // For GetSourceFileCache.
-
 public:
   /// Broadcaster event bits definitions.
   enum {
@@ -515,6 +513,10 @@
   void FlushProcessOutput(Process &process, bool flush_stdout,
                           bool flush_stderr);
 
+  SourceManager::SourceFileCache &GetSourceFileCache() {
+    return m_source_file_cache;
+  }
+
 protected:
   friend class CommandInterpreter;
   friend class REPL;
@@ -599,10 +601,6 @@
   // Ensures two threads don't attempt to flush process output in parallel.
   std::mutex m_output_flush_mutex;
 
-  SourceManager::SourceFileCache &GetSourceFileCache() {
-    return m_source_file_cache;
-  }
-
   void InstanceInitialize();
 
   // these should never be NULL
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to