[Lldb-commits] [lldb] 1637545 - [trace][intelpt] Support system-wide tracing [5] - Disable/enable per-core tracing based on the process state

Walter Erquinigo via lldb-commits lldb-commits at lists.llvm.org
Tue May 17 12:47:03 PDT 2022


Author: Walter Erquinigo
Date: 2022-05-17T12:46:54-07:00
New Revision: 1637545f689b8c4ef888ca385de75982a6a932e3

URL: https://github.com/llvm/llvm-project/commit/1637545f689b8c4ef888ca385de75982a6a932e3
DIFF: https://github.com/llvm/llvm-project/commit/1637545f689b8c4ef888ca385de75982a6a932e3.diff

LOG: [trace][intelpt] Support system-wide tracing [5] - Disable/enable per-core tracing based on the process state

When tracing on per-core mode, we are tracing all processes, which means
that after hitting a breakpoint, our process will stop running (thus
producing no more tracing data) but other processes will continue
writing to our trace buffers. This causes a big data loss for our trace.
As a way to remediate this, I'm adding some logic to pause and unpause
tracing based on the target's state. The earlier we do it the better,
however, I'm not adding the trigger at the earliest possible point for
simplicity of this diff. Later we can improve that part.

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

Added: 
    

Modified: 
    lldb/include/lldb/Host/common/NativeProcessProtocol.h
    lldb/source/Host/common/NativeProcessProtocol.cpp
    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/IntelPTSingleBufferTrace.cpp
    lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.h
    lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
    lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
    lldb/source/Plugins/Process/Linux/Perf.cpp
    lldb/source/Plugins/Process/Linux/Perf.h

Removed: 
    


################################################################################
diff  --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
index c7494ba6b1957..ce16e869489ce 100644
--- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h
+++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h
@@ -461,6 +461,9 @@ class NativeProcessProtocol {
 
   NativeThreadProtocol *GetThreadByIDUnlocked(lldb::tid_t tid);
 
+  /// Notify tracers that the state of the target process has changed.
+  virtual void NotifyTracersProcessStateChanged(lldb::StateType state) {}
+
 private:
   void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
   llvm::Expected<SoftwareBreakpoint>

diff  --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp
index 6da5ccc9db931..761f38080efef 100644
--- a/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -312,6 +312,7 @@ void NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged(
   Log *log = GetLog(LLDBLog::Process);
 
   m_delegate.ProcessStateChanged(this, state);
+  NotifyTracersProcessStateChanged(state);
 
   LLDB_LOG(log, "sent state notification [{0}] from process {1}", state,
            GetID());

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
index f986ec459082d..ef6dddd54dbf6 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
@@ -55,7 +55,8 @@ Error IntelPTThreadTraceCollection::TraceStart(
                              "Thread %" PRIu64 " already traced", tid);
 
   Expected<IntelPTSingleBufferTraceUP> trace_up =
-      IntelPTSingleBufferTrace::Start(request, tid);
+      IntelPTSingleBufferTrace::Start(request, tid, /*core_id=*/None,
+                                      TraceCollectionState::Running);
   if (!trace_up)
     return trace_up.takeError();
 
@@ -78,8 +79,8 @@ IntelPTThreadTraceCollection::GetThreadStates() const {
   return states;
 }
 
-Expected<const IntelPTSingleBufferTrace &>
-IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) const {
+Expected<IntelPTSingleBufferTrace &>
+IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) {
   auto it = m_thread_traces.find(tid);
   if (it == m_thread_traces.end())
     return createStringError(inconvertibleErrorCode(),
@@ -120,8 +121,7 @@ Error IntelPTPerThreadProcessTrace::TraceStart(lldb::tid_t tid) {
   return m_thread_traces.TraceStart(tid, m_tracing_params);
 }
 
-const IntelPTThreadTraceCollection &
-IntelPTPerThreadProcessTrace::GetThreadTraces() const {
+IntelPTThreadTraceCollection &IntelPTPerThreadProcessTrace::GetThreadTraces() {
   return m_thread_traces;
 }
 
@@ -224,6 +224,11 @@ Error IntelPTCollector::TraceStart(const TraceIntelPTStartRequest &request) {
   }
 }
 
+void IntelPTCollector::OnProcessStateChanged(lldb::StateType state) {
+  if (m_per_core_process_trace_up)
+    m_per_core_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);
@@ -276,8 +281,8 @@ Expected<json::Value> IntelPTCollector::GetState() const {
   return toJSON(state);
 }
 
-Expected<const IntelPTSingleBufferTrace &>
-IntelPTCollector::GetTracedThread(lldb::tid_t tid) const {
+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(
@@ -286,9 +291,9 @@ IntelPTCollector::GetTracedThread(lldb::tid_t tid) const {
 }
 
 Expected<std::vector<uint8_t>>
-IntelPTCollector::GetBinaryData(const TraceGetBinaryDataRequest &request) const {
+IntelPTCollector::GetBinaryData(const TraceGetBinaryDataRequest &request) {
   if (request.kind == IntelPTDataKinds::kTraceBuffer) {
-    if (Expected<const IntelPTSingleBufferTrace &> trace =
+    if (Expected<IntelPTSingleBufferTrace &> trace =
             GetTracedThread(*request.tid))
       return trace->GetTraceBuffer(request.offset, request.size);
     else

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.h b/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
index 6125d335931b3..74a9d80d83df9 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
@@ -41,8 +41,7 @@ class IntelPTThreadTraceCollection {
 
   std::vector<TraceThreadState> GetThreadStates() const;
 
-  llvm::Expected<const IntelPTSingleBufferTrace &>
-  GetTracedThread(lldb::tid_t tid) const;
+  llvm::Expected<IntelPTSingleBufferTrace &> GetTracedThread(lldb::tid_t tid);
 
   llvm::Error TraceStart(lldb::tid_t tid,
                          const TraceIntelPTStartRequest &request);
@@ -83,7 +82,7 @@ class IntelPTPerThreadProcessTrace {
 
   bool TracesThread(lldb::tid_t tid) const;
 
-  const IntelPTThreadTraceCollection &GetThreadTraces() const;
+  IntelPTThreadTraceCollection &GetThreadTraces();
 
   llvm::Error TraceStart(lldb::tid_t tid);
 
@@ -107,6 +106,9 @@ class IntelPTCollector {
 
   static bool IsSupported();
 
+  /// To be invoked whenever the state of the target process has changed.
+  void OnProcessStateChanged(lldb::StateType state);
+
   /// If "process tracing" is enabled, then trace the given thread.
   llvm::Error OnThreadCreated(lldb::tid_t tid);
 
@@ -124,7 +126,7 @@ class IntelPTCollector {
 
   /// Implementation of the jLLDBTraceGetBinaryData packet
   llvm::Expected<std::vector<uint8_t>>
-  GetBinaryData(const TraceGetBinaryDataRequest &request) const;
+  GetBinaryData(const TraceGetBinaryDataRequest &request);
 
   /// Dispose of all traces
   void Clear();
@@ -136,8 +138,7 @@ class IntelPTCollector {
   llvm::Error TraceStart(lldb::tid_t tid,
                          const TraceIntelPTStartRequest &request);
 
-  llvm::Expected<const IntelPTSingleBufferTrace &>
-  GetTracedThread(lldb::tid_t tid) const;
+  llvm::Expected<IntelPTSingleBufferTrace &> GetTracedThread(lldb::tid_t tid);
 
   bool IsProcessTracingEnabled() const;
 

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
index 3762179496c3a..f9e25b28b1f77 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.cpp
@@ -10,6 +10,8 @@
 
 #include "Procfs.h"
 
+#include "Plugins/Process/POSIX/ProcessPOSIXLog.h"
+
 using namespace lldb;
 using namespace lldb_private;
 using namespace process_linux;
@@ -46,7 +48,8 @@ Expected<IntelPTMultiCoreTraceUP> IntelPTMultiCoreTrace::StartOnAllCores(
   llvm::DenseMap<core_id_t, IntelPTSingleBufferTraceUP> buffers;
   for (core_id_t core_id : *core_ids) {
     if (Expected<IntelPTSingleBufferTraceUP> core_trace =
-            IntelPTSingleBufferTrace::Start(request, /*tid=*/None, core_id))
+            IntelPTSingleBufferTrace::Start(request, /*tid=*/None, core_id,
+                                            TraceCollectionState::Paused))
       buffers.try_emplace(core_id, std::move(*core_trace));
     else
       return IncludePerfEventParanoidMessageInError(core_trace.takeError());
@@ -56,9 +59,38 @@ Expected<IntelPTMultiCoreTraceUP> IntelPTMultiCoreTrace::StartOnAllCores(
 }
 
 void IntelPTMultiCoreTrace::ForEachCore(
-    std::function<void(core_id_t core_id,
-                       const IntelPTSingleBufferTrace &core_trace)>
+    std::function<void(core_id_t core_id, IntelPTSingleBufferTrace &core_trace)>
         callback) {
   for (auto &it : m_traces_per_core)
     callback(it.first, *it.second);
 }
+
+void IntelPTMultiCoreTrace::OnProcessStateChanged(lldb::StateType state) {
+  if (m_process_state == state)
+    return;
+  switch (state) {
+  case eStateStopped:
+  case eStateExited: {
+    ForEachCore([](core_id_t core_id, IntelPTSingleBufferTrace &core_trace) {
+      if (Error err =
+              core_trace.ChangeCollectionState(TraceCollectionState::Paused)) {
+        LLDB_LOG_ERROR(GetLog(POSIXLog::Trace), std::move(err),
+                       "Unable to pause the core trace for core {0}", core_id);
+      }
+    });
+    break;
+  }
+  case eStateRunning: {
+    ForEachCore([](core_id_t core_id, IntelPTSingleBufferTrace &core_trace) {
+      if (Error err =
+              core_trace.ChangeCollectionState(TraceCollectionState::Running)) {
+        LLDB_LOG_ERROR(GetLog(POSIXLog::Trace), std::move(err),
+                       "Unable to resume the core trace for core {0}", core_id);
+      }
+    });
+    break;
+  }
+  default:
+    break;
+  }
+}

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
index 5aaea4d0b341d..b57e3409d3602 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTMultiCoreTrace.h
@@ -44,10 +44,19 @@ class IntelPTMultiCoreTrace {
   ///
   /// \param[in] callback.core_trace
   ///   The single-buffer trace instance for the given core.
-  void
-  ForEachCore(std::function<void(lldb::core_id_t core_id,
-                                 const IntelPTSingleBufferTrace &core_trace)>
-                  callback);
+  void ForEachCore(std::function<void(lldb::core_id_t core_id,
+                                      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);
 
 private:
   IntelPTMultiCoreTrace(
@@ -56,6 +65,10 @@ class IntelPTMultiCoreTrace {
       : m_traces_per_core(std::move(traces_per_core)) {}
 
   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;
 };
 
 } // namespace process_linux

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.cpp b/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.cpp
index b86c28bf10485..9b10919839b5f 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.cpp
@@ -18,7 +18,6 @@
 #include <sstream>
 
 #include <linux/perf_event.h>
-#include <sys/ioctl.h>
 #include <sys/syscall.h>
 #include <unistd.h>
 
@@ -209,29 +208,48 @@ size_t IntelPTSingleBufferTrace::GetTraceBufferSize() const {
   return m_perf_event.GetAuxBuffer().size();
 }
 
+Error IntelPTSingleBufferTrace::ChangeCollectionState(
+    TraceCollectionState new_state) {
+  if (new_state == m_collection_state)
+    return Error::success();
+
+  switch (new_state) {
+  case TraceCollectionState::Paused:
+    if (Error err = m_perf_event.DisableWithIoctl())
+      return err;
+    break;
+  case TraceCollectionState::Running:
+    if (Error err = m_perf_event.EnableWithIoctl())
+      return err;
+    break;
+  }
+  m_collection_state = new_state;
+  return Error::success();
+}
+
 Expected<std::vector<uint8_t>>
-IntelPTSingleBufferTrace::GetTraceBuffer(size_t offset, size_t size) const {
-  auto fd = m_perf_event.GetFd();
-  perf_event_mmap_page &mmap_metadata = m_perf_event.GetMetadataPage();
+IntelPTSingleBufferTrace::GetTraceBuffer(size_t offset, size_t size) {
   // Disable the perf event to force a flush out of the CPU's internal buffer.
   // Besides, we can guarantee that the CPU won't override any data as we are
   // reading the buffer.
-  //
   // The Intel documentation says:
   //
-  // Packets are first buffered internally and then written out asynchronously.
-  // To collect packet output for postprocessing, a collector needs first to
-  // ensure that all packet data has been flushed from internal buffers.
-  // Software can ensure this by stopping packet generation by clearing
-  // IA32_RTIT_CTL.TraceEn (see “Disabling Packet Generation” in
+  // Packets are first buffered internally and then written out
+  // asynchronously. To collect packet output for postprocessing, a collector
+  // needs first to ensure that all packet data has been flushed from internal
+  // buffers. Software can ensure this by stopping packet generation by
+  // clearing IA32_RTIT_CTL.TraceEn (see “Disabling Packet Generation” in
   // Section 35.2.7.2).
   //
-  // This is achieved by the PERF_EVENT_IOC_DISABLE ioctl request, as mentioned
-  // in the man page of perf_event_open.
-  ioctl(fd, PERF_EVENT_IOC_DISABLE);
+  // This is achieved by the PERF_EVENT_IOC_DISABLE ioctl request, as
+  // mentioned in the man page of perf_event_open.
+  TraceCollectionState previous_state = m_collection_state;
+  if (Error err = ChangeCollectionState(TraceCollectionState::Paused))
+    return std::move(err);
 
+  std::vector<uint8_t> data(size, 0);
+  perf_event_mmap_page &mmap_metadata = m_perf_event.GetMetadataPage();
   Log *log = GetLog(POSIXLog::Trace);
-  Status error;
   uint64_t head = mmap_metadata.aux_head;
 
   LLDB_LOG(log, "Aux size -{0} , Head - {1}", mmap_metadata.aux_size, head);
@@ -248,20 +266,19 @@ IntelPTSingleBufferTrace::GetTraceBuffer(size_t offset, size_t size) const {
    *
    * */
 
-  std::vector<uint8_t> data(size, 0);
   MutableArrayRef<uint8_t> buffer(data);
   ReadCyclicBuffer(buffer, m_perf_event.GetAuxBuffer(),
                    static_cast<size_t>(head), offset);
 
-  // Reenable tracing now we have read the buffer
-  ioctl(fd, PERF_EVENT_IOC_ENABLE);
+  if (Error err = ChangeCollectionState(previous_state))
+    return std::move(err);
+
   return data;
 }
 
-Expected<IntelPTSingleBufferTraceUP>
-IntelPTSingleBufferTrace::Start(const TraceIntelPTStartRequest &request,
-                                Optional<lldb::tid_t> tid,
-                                Optional<core_id_t> core_id) {
+Expected<IntelPTSingleBufferTraceUP> IntelPTSingleBufferTrace::Start(
+    const TraceIntelPTStartRequest &request, Optional<lldb::tid_t> tid,
+    Optional<core_id_t> core_id, TraceCollectionState initial_state) {
 #ifndef PERF_ATTR_SIZE_VER5
   return createStringError(inconvertibleErrorCode(),
                            "Intel PT Linux perf event not supported");
@@ -289,6 +306,7 @@ IntelPTSingleBufferTrace::Start(const TraceIntelPTStartRequest &request,
       }));
   if (!attr)
     return attr.takeError();
+  attr->disabled = initial_state == TraceCollectionState::Paused;
 
   LLDB_LOG(log, "Will create trace buffer of size {0}",
            request.trace_buffer_size);
@@ -298,8 +316,9 @@ IntelPTSingleBufferTrace::Start(const TraceIntelPTStartRequest &request,
                                                             buffer_numpages)) {
       return std::move(mmap_err);
     }
-    return IntelPTSingleBufferTraceUP(
-        new IntelPTSingleBufferTrace(std::move(*perf_event)));
+    IntelPTSingleBufferTraceUP trace_up(
+        new IntelPTSingleBufferTrace(std::move(*perf_event), initial_state));
+    return trace_up;
   } else {
     return perf_event.takeError();
   }

diff  --git a/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.h b/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.h
index 7613c5408ade3..c22e26e31519a 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTSingleBufferTrace.h
@@ -27,6 +27,11 @@ class IntelPTSingleBufferTrace;
 
 using IntelPTSingleBufferTraceUP = std::unique_ptr<IntelPTSingleBufferTrace>;
 
+enum class TraceCollectionState {
+  Running,
+  Paused,
+};
+
 /// This class wraps a single perf event collecting intel pt data in a single
 /// buffer.
 class IntelPTSingleBufferTrace {
@@ -43,13 +48,17 @@ class IntelPTSingleBufferTrace {
   /// \param[in] core_id
   ///     The CPU core id where to trace. If \b None, then this traces all CPUs.
   ///
+  /// \param[in] initial_state
+  ///     The initial trace collection state.
+  ///
   /// \return
   ///   A \a IntelPTSingleBufferTrace instance if tracing was successful, or
   ///   an \a llvm::Error otherwise.
   static llvm::Expected<IntelPTSingleBufferTraceUP>
   Start(const TraceIntelPTStartRequest &request,
         llvm::Optional<lldb::tid_t> tid,
-        llvm::Optional<lldb::core_id_t> core_id = llvm::None);
+        llvm::Optional<lldb::core_id_t> core_id,
+        TraceCollectionState initial_state);
 
   /// \return
   ///    The bytes requested by a jLLDBTraceGetBinaryData packet that was routed
@@ -57,7 +66,10 @@ class IntelPTSingleBufferTrace {
   llvm::Expected<std::vector<uint8_t>>
   GetBinaryData(const TraceGetBinaryDataRequest &request) const;
 
-  /// Read the trace buffer managed by this trace instance.
+  /// Read the trace buffer managed by this trace instance. To ensure that the
+  /// data is up-to-date and is not corrupted by read-write race conditions, the
+  /// underlying perf_event is paused during read, and later it's returned to
+  /// its initial state.
   ///
   /// \param[in] offset
   ///     Offset of the data to read.
@@ -70,13 +82,24 @@ class IntelPTSingleBufferTrace {
   ///     size of the requested \a size. Non-available positions will be
   ///     filled with zeroes.
   llvm::Expected<std::vector<uint8_t>> GetTraceBuffer(size_t offset,
-                                                      size_t size) const;
+                                                      size_t size);
 
   /// \return
-  ///   The total the size in bytes used by the trace buffer managed by this
-  ///   trace instance.
+  ///     The total the size in bytes used by the trace buffer managed by this
+  ///     trace instance.
   size_t GetTraceBufferSize() const;
 
+  /// Change the collection state for this trace.
+  ///
+  /// This is a no-op if \p state is the same as the current state.
+  ///
+  /// \param[in] state
+  ///     The new state.
+  ///
+  /// \return
+  ///     An error if the state couldn't be changed.
+  llvm::Error ChangeCollectionState(TraceCollectionState state);
+
 private:
   /// Construct new \a IntelPTSingleBufferThreadTrace. Users are supposed to
   /// create instances of this class via the \a Start() method and not invoke
@@ -84,11 +107,20 @@ class IntelPTSingleBufferTrace {
   ///
   /// \param[in] perf_event
   ///   perf event configured for IntelPT.
-  IntelPTSingleBufferTrace(PerfEvent &&perf_event)
-      : m_perf_event(std::move(perf_event)) {}
+  ///
+  /// \param[in] collection_state
+  ///   The initial collection state for the provided perf_event.
+  IntelPTSingleBufferTrace(PerfEvent &&perf_event,
+                           TraceCollectionState collection_state)
+      : m_perf_event(std::move(perf_event)),
+        m_collection_state(collection_state) {}
 
   /// perf event configured for IntelPT.
   PerfEvent m_perf_event;
+
+  /// The initial state is stopped because tracing can only start when the
+  /// process is paused.
+  TraceCollectionState m_collection_state;
 };
 
 } // namespace process_linux

diff  --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
index 37da1f12421a5..a7869d2241aec 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp
@@ -1665,6 +1665,11 @@ void NativeProcessLinux::StopTrackingThread(NativeThreadLinux &thread) {
   SignalIfAllThreadsStopped();
 }
 
+void NativeProcessLinux::NotifyTracersProcessStateChanged(
+    lldb::StateType state) {
+  m_intel_pt_collector.OnProcessStateChanged(state);
+}
+
 Status NativeProcessLinux::NotifyTracersOfNewThread(lldb::tid_t tid) {
   Log *log = GetLog(POSIXLog::Thread);
   Status error(m_intel_pt_collector.OnThreadCreated(tid));

diff  --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
index 368b4a3861ef0..d8afc48c650ea 100644
--- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
+++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h
@@ -209,6 +209,8 @@ class NativeProcessLinux : public NativeProcessELF,
   /// stopping for threads being destroyed.
   Status NotifyTracersOfThreadDestroyed(lldb::tid_t tid);
 
+  void NotifyTracersProcessStateChanged(lldb::StateType state) override;
+
   /// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
   /// corresponding to the given thread ID to the memory pointed to by @p
   /// message.

diff  --git a/lldb/source/Plugins/Process/Linux/Perf.cpp b/lldb/source/Plugins/Process/Linux/Perf.cpp
index 89f14a5bb41da..c1ae9d26dcd0b 100644
--- a/lldb/source/Plugins/Process/Linux/Perf.cpp
+++ b/lldb/source/Plugins/Process/Linux/Perf.cpp
@@ -15,6 +15,7 @@
 #include "llvm/Support/MathExtras.h"
 #include "llvm/Support/MemoryBuffer.h"
 
+#include <sys/ioctl.h>
 #include <sys/mman.h>
 #include <sys/syscall.h>
 #include <unistd.h>
@@ -219,3 +220,19 @@ ArrayRef<uint8_t> PerfEvent::GetAuxBuffer() const {
   return {reinterpret_cast<uint8_t *>(m_aux_base.get()),
            static_cast<size_t>(mmap_metadata.aux_size)};
 }
+
+Error PerfEvent::DisableWithIoctl() const {
+  if (ioctl(*m_fd, PERF_EVENT_IOC_DISABLE) < 0)
+    return createStringError(inconvertibleErrorCode(),
+                             "Can't disable perf event. %s",
+                             std::strerror(errno));
+  return Error::success();
+}
+
+Error PerfEvent::EnableWithIoctl() const {
+  if (ioctl(*m_fd, PERF_EVENT_IOC_ENABLE) < 0)
+    return createStringError(inconvertibleErrorCode(),
+                             "Can't disable perf event. %s",
+                             std::strerror(errno));
+  return Error::success();
+}

diff  --git a/lldb/source/Plugins/Process/Linux/Perf.h b/lldb/source/Plugins/Process/Linux/Perf.h
index ea7bea5277ff7..b249ab9858cf6 100644
--- a/lldb/source/Plugins/Process/Linux/Perf.h
+++ b/lldb/source/Plugins/Process/Linux/Perf.h
@@ -213,6 +213,19 @@ class PerfEvent {
   ///   \a ArrayRef<uint8_t> extending \a aux_size bytes from \a aux_offset.
   llvm::ArrayRef<uint8_t> GetAuxBuffer() const;
 
+  /// Use the ioctl API to disable the perf event. This doesn't terminate the
+  /// perf event.
+  ///
+  /// \return
+  ///   An Error if the perf event couldn't be disabled.
+  llvm::Error DisableWithIoctl() const;
+
+  /// Use the ioctl API to enable the perf event.
+  ///
+  /// \return
+  ///   An Error if the perf event couldn't be enabled.
+  llvm::Error EnableWithIoctl() const;
+
 private:
   /// Create new \a PerfEvent.
   ///


        


More information about the lldb-commits mailing list