[Lldb-commits] [lldb] 1f56f7f - [trace][intelpt] Support system-wide tracing [7] - Create a base IntelPTProcessTrace class

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Wed Jun 15 12:08:06 PDT 2022


Author: Walter Erquinigo
Date: 2022-06-15T12:07:59-07:00
New Revision: 1f56f7fc16bcb9966d508e462e0f408080fdb362

URL: https://github.com/llvm/llvm-project/commit/1f56f7fc16bcb9966d508e462e0f408080fdb362
DIFF: https://github.com/llvm/llvm-project/commit/1f56f7fc16bcb9966d508e462e0f408080fdb362.diff

LOG: [trace][intelpt] Support system-wide tracing [7] - Create a base IntelPTProcessTrace class

We have two different "process trace" implementations: per thread and per core. As a way to simplify the collector who uses both, I'm creating a base abstract class that is used by these implementations. This effectively simplify a good chunk of code.

Differential Revision: https://reviews.llvm.org/D125503

Added: 
    lldb/source/Plugins/Process/Linux/IntelPTProcessTrace.h

Modified: 
    lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
    lldb/source/Plugins/Process/Linux/IntelPTCollector.h
    lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
    lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
    lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
    lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
    lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
index 154e1d9b0ad14..08fa6924121cb 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
@@ -44,13 +44,8 @@ IntelPTCollector::IntelPTCollector(NativeProcessProtocol &process)
 }
 
 Error IntelPTCollector::TraceStop(lldb::tid_t tid) {
-  if (m_per_thread_process_trace_up &&
-      m_per_thread_process_trace_up->TracesThread(tid))
-    return m_per_thread_process_trace_up->TraceStop(tid);
-  else if (m_per_core_process_trace_up)
-    return createStringError(inconvertibleErrorCode(),
-                             "Can't stop tracing an individual thread when "
-                             "per-core process tracing is enabled.");
+  if (m_process_trace_up && m_process_trace_up->TracesThread(tid))
+    return m_process_trace_up->TraceStop(tid);
   return m_thread_traces.TraceStop(tid);
 }
 
@@ -67,23 +62,9 @@ Error IntelPTCollector::TraceStop(const TraceStopRequest &request) {
   }
 }
 
-Expected<IntelPTPerThreadProcessTraceUP>
-IntelPTPerThreadProcessTrace::Start(const TraceIntelPTStartRequest &request,
-                                    ArrayRef<lldb::tid_t> current_tids) {
-  IntelPTPerThreadProcessTraceUP trace(
-      new IntelPTPerThreadProcessTrace(request));
-
-  Error error = Error::success();
-  for (lldb::tid_t tid : current_tids)
-    error = joinErrors(std::move(error), trace->TraceStart(tid));
-  if (error)
-    return std::move(error);
-  return std::move(trace);
-}
-
 Error IntelPTCollector::TraceStart(const TraceIntelPTStartRequest &request) {
   if (request.IsProcessTracing()) {
-    if (IsProcessTracingEnabled()) {
+    if (m_process_trace_up) {
       return createStringError(
           inconvertibleErrorCode(),
           "Process currently traced. Stop process tracing first");
@@ -93,9 +74,9 @@ Error IntelPTCollector::TraceStart(const TraceIntelPTStartRequest &request) {
         return createStringError(
             inconvertibleErrorCode(),
             "Threads currently traced. Stop tracing them first.");
-      if (Expected<IntelPTMultiCoreTraceUP> trace =
-              IntelPTMultiCoreTrace::StartOnAllCores(request)) {
-        m_per_core_process_trace_up = std::move(*trace);
+      if (Expected<IntelPTProcessTraceUP> trace =
+              IntelPTMultiCoreTrace::StartOnAllCores(request, m_process)) {
+        m_process_trace_up = std::move(*trace);
         return Error::success();
       } else {
         return trace.takeError();
@@ -106,9 +87,9 @@ Error IntelPTCollector::TraceStart(const TraceIntelPTStartRequest &request) {
         process_threads.push_back(m_process.GetThreadAtIndex(i)->GetID());
 
       // per-thread process tracing
-      if (Expected<IntelPTPerThreadProcessTraceUP> trace =
+      if (Expected<IntelPTProcessTraceUP> trace =
               IntelPTPerThreadProcessTrace::Start(request, process_threads)) {
-        m_per_thread_process_trace_up = std::move(trace.get());
+        m_process_trace_up = std::move(trace.get());
         return Error::success();
       } else {
         return trace.takeError();
@@ -116,35 +97,40 @@ Error IntelPTCollector::TraceStart(const TraceIntelPTStartRequest &request) {
     }
   } else {
     // individual thread tracing
-    if (m_per_core_process_trace_up)
-      return createStringError(inconvertibleErrorCode(),
-                               "Process currently traced with per-core "
-                               "tracing. Stop process tracing first");
-
     Error error = Error::success();
-    for (int64_t tid : *request.tids)
-      error = joinErrors(std::move(error),
-                         m_thread_traces.TraceStart(tid, request));
+    for (int64_t tid : *request.tids) {
+      if (m_process_trace_up && m_process_trace_up->TracesThread(tid))
+        error = joinErrors(
+            std::move(error),
+            createStringError(inconvertibleErrorCode(),
+                              formatv("Thread with tid {0} is currently "
+                                      "traced. Stop tracing it first.",
+                                      tid)
+                                  .str()
+                                  .c_str()));
+      else
+        error = joinErrors(std::move(error),
+                           m_thread_traces.TraceStart(tid, request));
+    }
     return error;
   }
 }
 
 void IntelPTCollector::OnProcessStateChanged(lldb::StateType state) {
-  if (m_per_core_process_trace_up)
-    m_per_core_process_trace_up->OnProcessStateChanged(state);
+  if (m_process_trace_up)
+    m_process_trace_up->OnProcessStateChanged(state);
 }
 
 Error IntelPTCollector::OnThreadCreated(lldb::tid_t tid) {
-  if (m_per_thread_process_trace_up)
-    return m_per_thread_process_trace_up->TraceStart(tid);
+  if (m_process_trace_up)
+    return m_process_trace_up->TraceStart(tid);
 
   return Error::success();
 }
 
 Error IntelPTCollector::OnThreadDestroyed(lldb::tid_t tid) {
-  if (m_per_thread_process_trace_up &&
-      m_per_thread_process_trace_up->TracesThread(tid))
-    return m_per_thread_process_trace_up->TraceStop(tid);
+  if (m_process_trace_up && m_process_trace_up->TracesThread(tid))
+    return m_process_trace_up->TraceStop(tid);
   else if (m_thread_traces.TracesThread(tid))
     return m_thread_traces.TraceStop(tid);
   return Error::success();
@@ -156,6 +142,9 @@ Expected<json::Value> IntelPTCollector::GetState() {
     return cpu_info.takeError();
 
   TraceGetStateResponse state;
+  if (m_process_trace_up)
+    state = m_process_trace_up->GetState();
+
   state.process_binary_data.push_back(
       {IntelPTDataKinds::kProcFsCpuInfo, cpu_info->size()});
 
@@ -165,48 +154,22 @@ Expected<json::Value> IntelPTCollector::GetState() {
                                         {{IntelPTDataKinds::kTraceBuffer,
                                           thread_trace.GetTraceBufferSize()}}});
       });
-
-  if (m_per_thread_process_trace_up) {
-    m_per_thread_process_trace_up->GetThreadTraces().ForEachThread(
-        [&](lldb::tid_t tid, const IntelPTSingleBufferTrace &thread_trace) {
-          state.traced_threads.push_back(
-              {tid,
-               {{IntelPTDataKinds::kTraceBuffer,
-                 thread_trace.GetTraceBufferSize()}}});
-        });
-  }
-
-  if (m_per_core_process_trace_up) {
-    for (size_t i = 0; m_process.GetThreadAtIndex(i); i++)
-      state.traced_threads.push_back(
-          TraceThreadState{m_process.GetThreadAtIndex(i)->GetID(), {}});
-
-    state.cores.emplace();
-    m_per_core_process_trace_up->ForEachCore(
-        [&](lldb::core_id_t core_id,
-            const IntelPTSingleBufferTrace &core_trace) {
-          state.cores->push_back({core_id,
-                                  {{IntelPTDataKinds::kTraceBuffer,
-                                    core_trace.GetTraceBufferSize()}}});
-        });
-  }
   return toJSON(state);
 }
 
-Expected<IntelPTSingleBufferTrace &>
-IntelPTCollector::GetTracedThread(lldb::tid_t tid) {
-  if (m_per_thread_process_trace_up &&
-      m_per_thread_process_trace_up->TracesThread(tid))
-    return m_per_thread_process_trace_up->GetThreadTraces().GetTracedThread(
-        tid);
-  return m_thread_traces.GetTracedThread(tid);
-}
-
 Expected<std::vector<uint8_t>>
 IntelPTCollector::GetBinaryData(const TraceGetBinaryDataRequest &request) {
   if (request.kind == IntelPTDataKinds::kTraceBuffer) {
+    if (!request.tid)
+      return createStringError(
+          inconvertibleErrorCode(),
+          "Getting a trace buffer without a tid is currently unsupported");
+
+    if (m_process_trace_up && m_process_trace_up->TracesThread(*request.tid))
+      return m_process_trace_up->GetBinaryData(request);
+
     if (Expected<IntelPTSingleBufferTrace &> trace =
-            GetTracedThread(*request.tid))
+            m_thread_traces.GetTracedThread(*request.tid))
       return trace->GetTraceBuffer(request.offset, request.size);
     else
       return trace.takeError();
@@ -218,11 +181,6 @@ IntelPTCollector::GetBinaryData(const TraceGetBinaryDataRequest &request) {
                            request.kind.c_str());
 }
 
-void IntelPTCollector::ClearProcessTracing() {
-  m_per_thread_process_trace_up.reset();
-  m_per_core_process_trace_up.reset();
-}
-
 bool IntelPTCollector::IsSupported() {
   if (Expected<uint32_t> intel_pt_type = GetIntelPTOSEventType()) {
     return true;
@@ -232,12 +190,7 @@ bool IntelPTCollector::IsSupported() {
   }
 }
 
-bool IntelPTCollector::IsProcessTracingEnabled() const {
-  return (bool)m_per_thread_process_trace_up ||
-         (bool)m_per_core_process_trace_up;
-}
-
 void IntelPTCollector::Clear() {
-  ClearProcessTracing();
+  m_process_trace_up.reset();
   m_thread_traces.Clear();
 }

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.h b/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
index 10ffa18a6f145..5173ef4cc04fe 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
@@ -69,26 +69,14 @@ class IntelPTCollector {
   llvm::Error TraceStart(lldb::tid_t tid,
                          const TraceIntelPTStartRequest &request);
 
-  llvm::Expected<IntelPTSingleBufferTrace &> GetTracedThread(lldb::tid_t tid);
-
-  bool IsProcessTracingEnabled() const;
-
-  void ClearProcessTracing();
-
+  /// The target process.
   NativeProcessProtocol &m_process;
   /// Threads traced due to "thread tracing"
   IntelPTThreadTraceCollection m_thread_traces;
 
-  /// Only one of the following "process tracing" handlers can be active at a
-  /// given time.
-  ///
-  /// \{
-  /// Threads traced due to per-thread "process tracing".  This might be \b
-  /// nullptr.
-  IntelPTPerThreadProcessTraceUP m_per_thread_process_trace_up;
-  /// Cores traced due to per-core "process tracing".  This might be \b nullptr.
-  IntelPTMultiCoreTraceUP m_per_core_process_trace_up;
-  /// \}
+  /// Only one instance of "process trace" can be active at a given time.
+  /// It might be \b nullptr.
+  IntelPTProcessTraceUP m_process_trace_up;
 
   /// TSC to wall time conversion.
   TraceTscConversionUP m_tsc_conversion;

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
index f9e25b28b1f77..c32a1b9d5e550 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
@@ -33,8 +33,9 @@ static Error IncludePerfEventParanoidMessageInError(Error &&error) {
       toString(std::move(error)).c_str());
 }
 
-Expected<IntelPTMultiCoreTraceUP> IntelPTMultiCoreTrace::StartOnAllCores(
-    const TraceIntelPTStartRequest &request) {
+Expected<IntelPTProcessTraceUP>
+IntelPTMultiCoreTrace::StartOnAllCores(const TraceIntelPTStartRequest &request,
+                                       NativeProcessProtocol &process) {
   Expected<ArrayRef<core_id_t>> core_ids = GetAvailableLogicalCoreIDs();
   if (!core_ids)
     return core_ids.takeError();
@@ -55,7 +56,8 @@ Expected<IntelPTMultiCoreTraceUP> IntelPTMultiCoreTrace::StartOnAllCores(
       return IncludePerfEventParanoidMessageInError(core_trace.takeError());
   }
 
-  return IntelPTMultiCoreTraceUP(new IntelPTMultiCoreTrace(std::move(buffers)));
+  return IntelPTProcessTraceUP(
+      new IntelPTMultiCoreTrace(std::move(buffers), process));
 }
 
 void IntelPTMultiCoreTrace::ForEachCore(
@@ -94,3 +96,42 @@ void IntelPTMultiCoreTrace::OnProcessStateChanged(lldb::StateType state) {
     break;
   }
 }
+
+TraceGetStateResponse IntelPTMultiCoreTrace::GetState() {
+  TraceGetStateResponse state;
+
+  for (size_t i = 0; m_process.GetThreadAtIndex(i); i++)
+    state.traced_threads.push_back(
+        TraceThreadState{m_process.GetThreadAtIndex(i)->GetID(), {}});
+
+  state.cores.emplace();
+  ForEachCore([&](lldb::core_id_t core_id,
+                  const IntelPTSingleBufferTrace &core_trace) {
+    state.cores->push_back(
+        {core_id,
+         {{IntelPTDataKinds::kTraceBuffer, core_trace.GetTraceBufferSize()}}});
+  });
+
+  return state;
+}
+
+bool IntelPTMultiCoreTrace::TracesThread(lldb::tid_t tid) const {
+  // All the process' threads are being traced automatically.
+  return (bool)m_process.GetThreadByID(tid);
+}
+
+llvm::Error IntelPTMultiCoreTrace::TraceStart(lldb::tid_t tid) {
+  // This instance is already tracing all threads automatically.
+  return llvm::Error::success();
+}
+
+Error IntelPTMultiCoreTrace::TraceStop(lldb::tid_t tid) {
+  return createStringError(inconvertibleErrorCode(),
+                           "Can't stop tracing an individual thread when "
+                           "per-core process tracing is enabled.");
+}
+
+Expected<std::vector<uint8_t>>
+IntelPTMultiCoreTrace::GetBinaryData(const TraceGetBinaryDataRequest &request) {
+  return createStringError(inconvertibleErrorCode(), "Unimplemented");
+}

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
index b57e3409d3602..e0ef795481c16 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
@@ -9,8 +9,10 @@
 #ifndef liblldb_IntelPTMultiCoreTrace_H_
 #define liblldb_IntelPTMultiCoreTrace_H_
 
+#include "IntelPTProcessTrace.h"
 #include "IntelPTSingleBufferTrace.h"
 
+#include "lldb/Host/common/NativeProcessProtocol.h"
 #include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
 #include "lldb/lldb-types.h"
 
@@ -21,21 +23,22 @@
 namespace lldb_private {
 namespace process_linux {
 
-class IntelPTMultiCoreTrace;
-using IntelPTMultiCoreTraceUP = std::unique_ptr<IntelPTMultiCoreTrace>;
-
-class IntelPTMultiCoreTrace {
+class IntelPTMultiCoreTrace : public IntelPTProcessTrace {
 public:
   /// Start tracing all CPU cores.
   ///
   /// \param[in] request
   ///   Intel PT configuration parameters.
   ///
+  /// \param[in] process
+  ///   The process being debugged.
+  ///
   /// \return
   ///   An \a IntelPTMultiCoreTrace instance if tracing was successful, or
   ///   an \a llvm::Error otherwise.
-  static llvm::Expected<IntelPTMultiCoreTraceUP>
-  StartOnAllCores(const TraceIntelPTStartRequest &request);
+  static llvm::Expected<IntelPTProcessTraceUP>
+  StartOnAllCores(const TraceIntelPTStartRequest &request,
+                  NativeProcessProtocol &process);
 
   /// Execute the provided callback on each core that is being traced.
   ///
@@ -48,27 +51,34 @@ class IntelPTMultiCoreTrace {
                                       IntelPTSingleBufferTrace &core_trace)>
                        callback);
 
-  /// This method should be invoked as early as possible whenever the process
-  /// resumes or stops so that intel-pt collection is not enabled when
-  /// the process is not running. This is done to prevent polluting the core
-  /// traces with executions of unrelated processes, which increases the data
-  /// loss of the target process, given that core traces don't filter by
-  /// process.
-  /// A possible way to avoid this is to use CR3 filtering, which is equivalent
-  /// to process filtering, but the perf_event API doesn't support it.
-  void OnProcessStateChanged(lldb::StateType state);
+  void OnProcessStateChanged(lldb::StateType state) override;
+
+  TraceGetStateResponse GetState() override;
+
+  bool TracesThread(lldb::tid_t tid) const override;
+
+  llvm::Error TraceStart(lldb::tid_t tid) override;
+
+  llvm::Error TraceStop(lldb::tid_t tid) override;
+
+  llvm::Expected<std::vector<uint8_t>>
+  GetBinaryData(const TraceGetBinaryDataRequest &request) override;
 
 private:
   IntelPTMultiCoreTrace(
       llvm::DenseMap<lldb::core_id_t, IntelPTSingleBufferTraceUP>
-          &&traces_per_core)
-      : m_traces_per_core(std::move(traces_per_core)) {}
+          &&traces_per_core,
+      NativeProcessProtocol &process)
+      : m_traces_per_core(std::move(traces_per_core)), m_process(process) {}
 
   llvm::DenseMap<lldb::core_id_t, IntelPTSingleBufferTraceUP> m_traces_per_core;
 
   /// The initial state is stopped because tracing can only start when the
   /// process is paused.
   lldb::StateType m_process_state = lldb::StateType::eStateStopped;
+
+  /// The target process.
+  NativeProcessProtocol &m_process;
 };
 
 } // namespace process_linux

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
index 087597c4f2a57..48761d6c1d2ea 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
@@ -35,6 +35,35 @@ Error IntelPTPerThreadProcessTrace::TraceStart(lldb::tid_t tid) {
   return m_thread_traces.TraceStart(tid, m_tracing_params);
 }
 
-IntelPTThreadTraceCollection &IntelPTPerThreadProcessTrace::GetThreadTraces() {
-  return m_thread_traces;
+TraceGetStateResponse IntelPTPerThreadProcessTrace::GetState() {
+  TraceGetStateResponse state;
+  m_thread_traces.ForEachThread(
+      [&](lldb::tid_t tid, const IntelPTSingleBufferTrace &thread_trace) {
+        state.traced_threads.push_back({tid,
+                                        {{IntelPTDataKinds::kTraceBuffer,
+                                          thread_trace.GetTraceBufferSize()}}});
+      });
+  return state;
+}
+
+Expected<std::vector<uint8_t>> IntelPTPerThreadProcessTrace::GetBinaryData(
+    const TraceGetBinaryDataRequest &request) {
+  if (Expected<IntelPTSingleBufferTrace &> trace =
+          m_thread_traces.GetTracedThread(*request.tid))
+    return trace->GetTraceBuffer(request.offset, request.size);
+  else
+    return trace.takeError();
+}
+
+Expected<IntelPTProcessTraceUP>
+IntelPTPerThreadProcessTrace::Start(const TraceIntelPTStartRequest &request,
+                                    ArrayRef<lldb::tid_t> current_tids) {
+  IntelPTProcessTraceUP trace(new IntelPTPerThreadProcessTrace(request));
+
+  Error error = Error::success();
+  for (lldb::tid_t tid : current_tids)
+    error = joinErrors(std::move(error), trace->TraceStart(tid));
+  if (error)
+    return std::move(error);
+  return trace;
 }

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
index 84b749b78620a..d850dbd5fc76b 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
@@ -9,18 +9,15 @@
 #ifndef liblldb_IntelPTPerThreadProcessTrace_H_
 #define liblldb_IntelPTPerThreadProcessTrace_H_
 
+#include "IntelPTProcessTrace.h"
 #include "IntelPTSingleBufferTrace.h"
 #include "IntelPTThreadTraceCollection.h"
 
 namespace lldb_private {
 namespace process_linux {
 
-class IntelPTPerThreadProcessTrace;
-using IntelPTPerThreadProcessTraceUP =
-    std::unique_ptr<IntelPTPerThreadProcessTrace>;
-
 /// Manages a "process trace" instance by tracing each thread individually.
-class IntelPTPerThreadProcessTrace {
+class IntelPTPerThreadProcessTrace : public IntelPTProcessTrace {
 public:
   /// Start tracing the current process by tracing each of its tids
   /// individually.
@@ -35,19 +32,20 @@ class IntelPTPerThreadProcessTrace {
   /// \return
   ///   An \a IntelPTMultiCoreTrace instance if tracing was successful, or
   ///   an \a llvm::Error otherwise.
-  static llvm::Expected<IntelPTPerThreadProcessTraceUP>
+  static llvm::Expected<IntelPTProcessTraceUP>
   Start(const TraceIntelPTStartRequest &request,
         llvm::ArrayRef<lldb::tid_t> current_tids);
 
-  bool TracesThread(lldb::tid_t tid) const;
+  bool TracesThread(lldb::tid_t tid) const override;
+
+  llvm::Error TraceStart(lldb::tid_t tid) override;
 
-  IntelPTThreadTraceCollection &GetThreadTraces();
+  llvm::Error TraceStop(lldb::tid_t tid) override;
 
-  /// \copydoc IntelPTThreadTraceCollection::TraceStart()
-  llvm::Error TraceStart(lldb::tid_t tid);
+  TraceGetStateResponse GetState() override;
 
-  /// \copydoc IntelPTThreadTraceCollection::TraceStop()
-  llvm::Error TraceStop(lldb::tid_t tid);
+  llvm::Expected<std::vector<uint8_t>>
+  GetBinaryData(const TraceGetBinaryDataRequest &request) override;
 
 private:
   IntelPTPerThreadProcessTrace(const TraceIntelPTStartRequest &request)

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTProcessTrace.h b/lldb/source/Plugins/Process/Linux/IntelPTProcessTrace.h
new file mode 100644
index 0000000000000..ec4e42602d3c9
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/IntelPTProcessTrace.h
@@ -0,0 +1,59 @@
+//===-- IntelPTProcessTrace.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 liblldb_IntelPTProcessTrace_H_
+#define liblldb_IntelPTProcessTrace_H_
+
+#include "lldb/Utility/TraceIntelPTGDBRemotePackets.h"
+
+#include <memory>
+
+namespace lldb_private {
+namespace process_linux {
+
+// Abstract class to be inherited by all the process tracing strategies.
+class IntelPTProcessTrace {
+public:
+  virtual ~IntelPTProcessTrace() = default;
+
+  /// This method should be invoked as early as possible whenever the process
+  /// resumes or stops so that intel-pt collection is not enabled when
+  /// the process is not running. A case in which this is useful in when
+  /// tracing is done per-core. In this case we want to prevent polluting the
+  /// core traces with executions of unrelated processes, which increases the
+  /// data loss of the target process, given that core traces don't filter by
+  /// process.
+  /// A possible way to avoid this is to use CR3 filtering, which is equivalent
+  /// to process filtering, but the perf_event API doesn't support it.
+  ///
+  /// \param[in] state
+  ///     The new state of the target process.
+  virtual void OnProcessStateChanged(lldb::StateType state){};
+
+  /// Construct a minimal jLLDBTraceGetState response for this process trace.
+  virtual TraceGetStateResponse GetState() = 0;
+
+  virtual bool TracesThread(lldb::tid_t tid) const = 0;
+
+  /// \copydoc IntelPTThreadTraceCollection::TraceStart()
+  virtual llvm::Error TraceStart(lldb::tid_t tid) = 0;
+
+  /// \copydoc IntelPTThreadTraceCollection::TraceStop()
+  virtual llvm::Error TraceStop(lldb::tid_t tid) = 0;
+
+  /// Get binary data owned by this instance.
+  virtual llvm::Expected<std::vector<uint8_t>>
+  GetBinaryData(const TraceGetBinaryDataRequest &request) = 0;
+};
+
+using IntelPTProcessTraceUP = std::unique_ptr<IntelPTProcessTrace>;
+
+} // namespace process_linux
+} // namespace lldb_private
+
+#endif // liblldb_IntelPTProcessTrace_H_

diff  --git a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
index 33177ca5ff01f..b76c0559ff776 100644
--- a/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
+++ b/lldb/test/API/commands/trace/multiple-threads/TestTraceStartStopMultipleThreads.py
@@ -189,7 +189,7 @@ def testStartPerCoreSession(self):
         # We can't support tracing per thread is per core is enabled.
         self.traceStartThread(
             error="True",
-            substrs=["Process currently traced with per-core tracing. Stop process tracing first"])
+            substrs=["Thread with tid ", "is currently traced"])
 
         # We can't stop individual thread when per core is enabled.
         self.traceStopThread(error="True",


        


More information about the lldb-commits mailing list