wallace created this revision.
wallace added a reviewer: jj10306.
Herald added a subscriber: pengfei.
Herald added a project: All.
wallace requested review of this revision.
Herald added a project: LLDB.
Herald added a subscriber: lldb-commits.

- Add logging for when the live state of the process is refreshed
- Move error handling of the live state refreshing to Trace from TraceIntelPT. 
This allows refreshing to fail either at the plug-in level or at the base class 
level. The error is cached and it can be gotten every time 
RefreshLiveProcessState is invoked.
- Allow DoRefreshLiveProcessState to handle plugin-specific parameters.
- Add some encapsulation to prevent TraceIntelPT from accessing variables 
belonging to Trace.

Test done via logging:

  (lldb) b main
  Breakpoint 1: where = a.out`main + 20 at main.cpp:27:20, address = 
0x00000000004023d9
  (lldb) r
  Process 2359706 launched: '/home/wallace/a.out' (x86_64)
  Process 2359706 stopped
  * thread #1, name = 'a.out', stop reason = breakpoint 1.1
      frame #0: 0x00000000004023d9 a.out`main at main.cpp:27:20
     24   };
     25  
     26   int main() {
  -> 27     std::vector<int> vvv;
     28     for (int i = 0; i < 100000; i++)
     29       vvv.push_back(i);
     30  
  (lldb) process trace start                                                    
                                    (lldb) log enable lldb target -F(lldb) n
  Process 2359706 stopped
  * thread #1, name = 'a.out', stop reason = step over
      frame #0: 0x00000000004023e8 a.out`main at main.cpp:28:12
     25  
     26   int main() {
     27     std::vector<int> vvv;
  -> 28     for (int i = 0; i < 100000; i++)
     29       vvv.push_back(i);
     30  
     31     std::deque<int> dq1 = {1, 2, 3};
  (lldb) thread trace dump instructions -c 2 -t                                 
                                    Trace.cpp:RefreshLiveProcessState           
                 Trace::RefreshLiveProcessState invoked
  TraceIntelPT.cpp:DoRefreshLiveProcessState                   TraceIntelPT 
found tsc conversion information
  thread #1: tid = 2359706
    a.out`std::vector<int, std::allocator<int>>::vector() + 26 at 
stl_vector.h:395:19
      54: [tsc=unavailable] 0x0000000000403a7c    retq   

See the logging lines at the end of the dump. They indicate that refreshing 
happened and that perf conversion information was found.


Repository:
  rG LLVM Github Monorepo

https://reviews.llvm.org/D125943

Files:
  lldb/include/lldb/Target/Trace.h
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
  lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
  lldb/source/Target/Trace.cpp

Index: lldb/source/Target/Trace.cpp
===================================================================
--- lldb/source/Target/Trace.cpp
+++ lldb/source/Target/Trace.cpp
@@ -17,6 +17,7 @@
 #include "lldb/Target/Process.h"
 #include "lldb/Target/SectionLoadList.h"
 #include "lldb/Target/Thread.h"
+#include "lldb/Utility/LLDBLog.h"
 #include "lldb/Utility/Stream.h"
 
 using namespace lldb;
@@ -175,28 +176,37 @@
   return m_live_process->TraceGetBinaryData(request);
 }
 
-void Trace::RefreshLiveProcessState() {
+const char *Trace::RefreshLiveProcessState() {
   if (!m_live_process)
-    return;
+    return nullptr;
 
   uint32_t new_stop_id = m_live_process->GetStopID();
   if (new_stop_id == m_stop_id)
-    return;
+    return nullptr;
+
+  Log *log = GetLog(LLDBLog::Target);
+  LLDB_LOG(log, "Trace::RefreshLiveProcessState invoked");
 
   m_stop_id = new_stop_id;
   m_live_thread_data.clear();
+  m_live_refresh_error.reset();
+
+  auto HandleError = [&](Error &&err) -> const char * {
+    m_live_refresh_error = toString(std::move(err));
+    return m_live_refresh_error->c_str();
+  };
 
   Expected<std::string> json_string = GetLiveProcessState();
-  if (!json_string) {
-    DoRefreshLiveProcessState(json_string.takeError());
-    return;
-  }
+  if (!json_string)
+    return HandleError(json_string.takeError());
+
   Expected<TraceGetStateResponse> live_process_state =
       json::parse<TraceGetStateResponse>(*json_string, "TraceGetStateResponse");
-  if (!live_process_state) {
-    DoRefreshLiveProcessState(live_process_state.takeError());
-    return;
-  }
+  if (!live_process_state)
+    return HandleError(live_process_state.takeError());
+
+  for (std::string &warning : live_process_state->warnings)
+    LLDB_LOG(log, "Warning when fetching the trace state: {0}", warning);
 
   for (const TraceThreadState &thread_state :
        live_process_state->traced_threads) {
@@ -207,9 +217,15 @@
   for (const TraceBinaryData &item : live_process_state->process_binary_data)
     m_live_process_data[item.kind] = item.size;
 
-  DoRefreshLiveProcessState(std::move(live_process_state));
+  if (Error err = DoRefreshLiveProcessState(std::move(*live_process_state),
+                                            *json_string))
+    return HandleError(std::move(err));
+
+  return nullptr;
 }
 
+Process *Trace::GetLiveProcess() { return m_live_process; }
+
 uint32_t Trace::GetStopID() {
   RefreshLiveProcessState();
   return m_stop_id;
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.h
@@ -75,8 +75,8 @@
 
   llvm::Expected<size_t> GetRawTraceSize(Thread &thread);
 
-  void DoRefreshLiveProcessState(
-      llvm::Expected<TraceGetStateResponse> state) override;
+  llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state,
+                                        llvm::StringRef json_response) override;
 
   bool IsTraced(lldb::tid_t tid) override;
 
@@ -148,12 +148,6 @@
 
   llvm::Expected<pt_cpu> GetCPUInfo();
 
-  /// Get the current traced live process.
-  ///
-  /// \return
-  ///     The current traced live process. If it's not a live process,
-  ///     return \a nullptr.
-  Process *GetLiveProcess();
 
   /// \return
   ///     The timer object for this trace.
@@ -191,9 +185,11 @@
   /// binary data.
   llvm::Optional<pt_cpu> m_cpu_info;
   std::map<lldb::tid_t, std::unique_ptr<ThreadDecoder>> m_thread_decoders;
-  /// Error gotten after a failed live process update, if any.
-  llvm::Optional<std::string> m_live_refresh_error;
+  /// Helper variable used to track long running operations for telemetry.
   TaskTimer m_task_timer;
+  /// It is provided by either a session file or a live process to convert TSC
+  /// counters to and from nanos. It might not be available on all hosts.
+  llvm::Optional<LinuxPerfZeroTscConversion> m_tsc_conversion;
 };
 
 } // namespace trace_intel_pt
Index: lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
===================================================================
--- lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
+++ lldb/source/Plugins/Trace/intel-pt/TraceIntelPT.cpp
@@ -87,11 +87,10 @@
 }
 
 DecodedThreadSP TraceIntelPT::Decode(Thread &thread) {
-  RefreshLiveProcessState();
-  if (m_live_refresh_error.hasValue())
+  if (const char *error = RefreshLiveProcessState())
     return std::make_shared<DecodedThread>(
         thread.shared_from_this(),
-        createStringError(inconvertibleErrorCode(), *m_live_refresh_error));
+        createStringError(inconvertibleErrorCode(), error));
 
   auto it = m_thread_decoders.find(thread.GetID());
   if (it == m_thread_decoders.end())
@@ -241,23 +240,29 @@
   return *m_cpu_info;
 }
 
-Process *TraceIntelPT::GetLiveProcess() { return m_live_process; }
-
-void TraceIntelPT::DoRefreshLiveProcessState(
-    Expected<TraceGetStateResponse> state) {
+Error TraceIntelPT::DoRefreshLiveProcessState(TraceGetStateResponse state,
+                                              StringRef json_response) {
   m_thread_decoders.clear();
 
-  if (!state) {
-    m_live_refresh_error = toString(state.takeError());
-    return;
-  }
-
-  for (const TraceThreadState &thread_state : state->traced_threads) {
+  for (const TraceThreadState &thread_state : state.traced_threads) {
     ThreadSP thread_sp =
-        m_live_process->GetThreadList().FindThreadByID(thread_state.tid);
+        GetLiveProcess()->GetThreadList().FindThreadByID(thread_state.tid);
     m_thread_decoders.emplace(
         thread_state.tid, std::make_unique<ThreadDecoder>(thread_sp, *this));
   }
+
+  Expected<TraceIntelPTGetStateResponse> intelpt_state =
+      json::parse<TraceIntelPTGetStateResponse>(json_response,
+                                                "TraceIntelPTGetStateResponse");
+  if (!intelpt_state)
+    return intelpt_state.takeError();
+
+  m_tsc_conversion = intelpt_state->tsc_perf_zero_conversion;
+  if (m_tsc_conversion) {
+    Log *log = GetLog(LLDBLog::Target);
+    LLDB_LOG(log, "TraceIntelPT found TSC conversion information");
+  }
+  return Error::success();
 }
 
 bool TraceIntelPT::IsTraced(lldb::tid_t tid) {
Index: lldb/include/lldb/Target/Trace.h
===================================================================
--- lldb/include/lldb/Target/Trace.h
+++ lldb/include/lldb/Target/Trace.h
@@ -265,6 +265,13 @@
   llvm::Error OnThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind,
                                      OnBinaryDataReadCallback callback);
 
+  /// Get the current traced live process.
+  ///
+  /// \return
+  ///     The current traced live process. If it's not a live process,
+  ///     return \a nullptr.
+  Process *GetLiveProcess();
+
 protected:
   /// Implementation of \a OnThreadBinaryDataRead() for live threads.
   llvm::Error OnLiveThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind,
@@ -365,14 +372,30 @@
   ///
   /// \param[in] state
   ///     The jLLDBTraceGetState response.
-  virtual void
-  DoRefreshLiveProcessState(llvm::Expected<TraceGetStateResponse> state) = 0;
+  ///
+  /// \param[in] json_response
+  ///     The original JSON response as a string. It might be useful to redecode
+  ///     it if it contains custom data for a specific trace plug-in.
+  ///
+  /// \return
+  ///     \b Error::success() if this operation succeedes, or an actual error
+  ///     otherwise.
+  virtual llvm::Error
+  DoRefreshLiveProcessState(TraceGetStateResponse state,
+                            llvm::StringRef json_response) = 0;
 
-  /// Method to be invoked by the plug-in to refresh the live process state.
+  /// Method to be invoked by the plug-in to refresh the live process state. It
+  /// will invoked DoRefreshLiveProcessState at some point, which should be
+  /// implemented by the plug-in for custom state handling.
+  ///
+  /// The result is cached through the same process stop. Even in the case of
+  /// errors, it caches the error.
   ///
-  /// The result is cached through the same process stop.
-  void RefreshLiveProcessState();
+  /// \return
+  ///   An error message if this operation failed, or \b nullptr otherwise.
+  const char *RefreshLiveProcessState();
 
+private:
   uint32_t m_stop_id = LLDB_INVALID_STOP_ID;
   /// Process traced by this object if doing live tracing. Otherwise it's null.
   Process *m_live_process = nullptr;
@@ -395,6 +418,8 @@
   /// tid -> data kind -> file
   llvm::DenseMap<lldb::tid_t, std::unordered_map<std::string, FileSpec>>
       m_postmortem_thread_data;
+
+  llvm::Optional<std::string> m_live_refresh_error;
 };
 
 } // 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