[Lldb-commits] [lldb] 1188faa - [trace][intelpt] Support system-wide tracing [6] - Break IntelPTCollector into smaller files and minor refactor
Walter Erquinigo via lldb-commits
lldb-commits at lists.llvm.org
Tue May 17 12:47:05 PDT 2022
Author: Walter Erquinigo
Date: 2022-05-17T12:46:54-07:00
New Revision: 1188faa7ab4b005e3ee28f30055de2f76e210eb8
URL: https://github.com/llvm/llvm-project/commit/1188faa7ab4b005e3ee28f30055de2f76e210eb8
DIFF: https://github.com/llvm/llvm-project/commit/1188faa7ab4b005e3ee28f30055de2f76e210eb8.diff
LOG: [trace][intelpt] Support system-wide tracing [6] - Break IntelPTCollector into smaller files and minor refactor
IntelPTCollector is very big and has 3 classes in it. It's actually cleaner if each one has its own file. This also gives more visibility to the developer about the different kinds of "tracers" that we have.
Besides that, I'm now restricting the creation of the BinaryData chunks to GetState() instead of having it in different places, which is not very clean, because the gdb-remote protocol should be as restricted as possible.
Differential Revision: https://reviews.llvm.org/D125047
Added:
lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp
lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.h
Modified:
lldb/include/lldb/Utility/TraceGDBRemotePackets.h
lldb/source/Plugins/Process/Linux/CMakeLists.txt
lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
lldb/source/Plugins/Process/Linux/IntelPTCollector.h
Removed:
################################################################################
diff --git a/lldb/include/lldb/Utility/TraceGDBRemotePackets.h b/lldb/include/lldb/Utility/TraceGDBRemotePackets.h
index 2f1cc872f687..163c1d33ab4f 100644
--- a/lldb/include/lldb/Utility/TraceGDBRemotePackets.h
+++ b/lldb/include/lldb/Utility/TraceGDBRemotePackets.h
@@ -10,6 +10,7 @@
#define LLDB_UTILITY_TRACEGDBREMOTEPACKETS_H
#include "llvm/Support/JSON.h"
+
#include <chrono>
#include "lldb/lldb-defines.h"
diff --git a/lldb/source/Plugins/Process/Linux/CMakeLists.txt b/lldb/source/Plugins/Process/Linux/CMakeLists.txt
index 5830a4072106..36d5037b0486 100644
--- a/lldb/source/Plugins/Process/Linux/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Linux/CMakeLists.txt
@@ -2,6 +2,8 @@ add_lldb_library(lldbPluginProcessLinux
IntelPTCollector.cpp
IntelPTSingleBufferTrace.cpp
IntelPTMultiCoreTrace.cpp
+ IntelPTPerThreadProcessTrace.cpp
+ IntelPTThreadTraceCollection.cpp
NativeProcessLinux.cpp
NativeRegisterContextLinux.cpp
NativeRegisterContextLinux_arm.cpp
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
index ef6dddd54dbf..9abfc190bf68 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp
@@ -32,101 +32,6 @@ using namespace lldb_private;
using namespace process_linux;
using namespace llvm;
-/// IntelPTThreadTraceCollection
-
-bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
- return m_thread_traces.count(tid);
-}
-
-Error IntelPTThreadTraceCollection::TraceStop(lldb::tid_t tid) {
- auto it = m_thread_traces.find(tid);
- if (it == m_thread_traces.end())
- return createStringError(inconvertibleErrorCode(),
- "Thread %" PRIu64 " not currently traced", tid);
- m_total_buffer_size -= it->second->GetTraceBufferSize();
- m_thread_traces.erase(tid);
- return Error::success();
-}
-
-Error IntelPTThreadTraceCollection::TraceStart(
- lldb::tid_t tid, const TraceIntelPTStartRequest &request) {
- if (TracesThread(tid))
- return createStringError(inconvertibleErrorCode(),
- "Thread %" PRIu64 " already traced", tid);
-
- Expected<IntelPTSingleBufferTraceUP> trace_up =
- IntelPTSingleBufferTrace::Start(request, tid, /*core_id=*/None,
- TraceCollectionState::Running);
- if (!trace_up)
- return trace_up.takeError();
-
- m_total_buffer_size += (*trace_up)->GetTraceBufferSize();
- m_thread_traces.try_emplace(tid, std::move(*trace_up));
- return Error::success();
-}
-
-size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
- return m_total_buffer_size;
-}
-
-std::vector<TraceThreadState>
-IntelPTThreadTraceCollection::GetThreadStates() const {
- std::vector<TraceThreadState> states;
- for (const auto &it : m_thread_traces)
- states.push_back({it.first,
- {TraceBinaryData{IntelPTDataKinds::kTraceBuffer,
- it.second->GetTraceBufferSize()}}});
- return states;
-}
-
-Expected<IntelPTSingleBufferTrace &>
-IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) {
- auto it = m_thread_traces.find(tid);
- if (it == m_thread_traces.end())
- return createStringError(inconvertibleErrorCode(),
- "Thread %" PRIu64 " not currently traced", tid);
- return *it->second.get();
-}
-
-void IntelPTThreadTraceCollection::Clear() {
- m_thread_traces.clear();
- m_total_buffer_size = 0;
-}
-
-size_t IntelPTThreadTraceCollection::GetTracedThreadsCount() const {
- return m_thread_traces.size();
-}
-
-/// IntelPTPerThreadProcessTrace
-
-bool IntelPTPerThreadProcessTrace::TracesThread(lldb::tid_t tid) const {
- return m_thread_traces.TracesThread(tid);
-}
-
-Error IntelPTPerThreadProcessTrace::TraceStop(lldb::tid_t tid) {
- return m_thread_traces.TraceStop(tid);
-}
-
-Error IntelPTPerThreadProcessTrace::TraceStart(lldb::tid_t tid) {
- if (m_thread_traces.GetTotalBufferSize() +
- m_tracing_params.trace_buffer_size >
- static_cast<size_t>(*m_tracing_params.process_buffer_size_limit))
- return createStringError(
- inconvertibleErrorCode(),
- "Thread %" PRIu64 " can't be traced as the process trace size limit "
- "has been reached. Consider retracing with a higher "
- "limit.",
- tid);
-
- return m_thread_traces.TraceStart(tid, m_tracing_params);
-}
-
-IntelPTThreadTraceCollection &IntelPTPerThreadProcessTrace::GetThreadTraces() {
- return m_thread_traces;
-}
-
-/// IntelPTCollector
-
IntelPTCollector::IntelPTCollector(NativeProcessProtocol &process)
: m_process(process) {
if (Expected<LinuxPerfZeroTscConversion> tsc_conversion =
@@ -245,7 +150,7 @@ Error IntelPTCollector::OnThreadDestroyed(lldb::tid_t tid) {
return Error::success();
}
-Expected<json::Value> IntelPTCollector::GetState() const {
+Expected<json::Value> IntelPTCollector::GetState() {
Expected<ArrayRef<uint8_t>> cpu_info = GetProcfsCpuInfo();
if (!cpu_info)
return cpu_info.takeError();
@@ -254,17 +159,24 @@ Expected<json::Value> IntelPTCollector::GetState() const {
state.process_binary_data.push_back(
{IntelPTDataKinds::kProcFsCpuInfo, cpu_info->size()});
- std::vector<TraceThreadState> thread_states =
- m_thread_traces.GetThreadStates();
- state.traced_threads.insert(state.traced_threads.end(), thread_states.begin(),
- thread_states.end());
+ m_thread_traces.ForEachThread(
+ [&](lldb::tid_t tid, const IntelPTSingleBufferTrace &thread_trace) {
+ state.traced_threads.push_back({tid,
+ {{IntelPTDataKinds::kTraceBuffer,
+ thread_trace.GetTraceBufferSize()}}});
+ });
if (m_per_thread_process_trace_up) {
- thread_states =
- m_per_thread_process_trace_up->GetThreadTraces().GetThreadStates();
- state.traced_threads.insert(state.traced_threads.end(),
- thread_states.begin(), thread_states.end());
- } else if (m_per_core_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(), {}});
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTCollector.h b/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
index 74a9d80d83df..10ffa18a6f14 100644
--- a/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
+++ b/lldb/source/Plugins/Process/Linux/IntelPTCollector.h
@@ -12,6 +12,7 @@
#include "Perf.h"
#include "IntelPTMultiCoreTrace.h"
+#include "IntelPTPerThreadProcessTrace.h"
#include "IntelPTSingleBufferTrace.h"
#include "lldb/Host/common/NativeProcessProtocol.h"
@@ -27,76 +28,6 @@ namespace lldb_private {
namespace process_linux {
-/// Manages a list of thread traces.
-class IntelPTThreadTraceCollection {
-public:
- IntelPTThreadTraceCollection() {}
-
- /// Dispose of all traces
- void Clear();
-
- bool TracesThread(lldb::tid_t tid) const;
-
- size_t GetTotalBufferSize() const;
-
- std::vector<TraceThreadState> GetThreadStates() const;
-
- llvm::Expected<IntelPTSingleBufferTrace &> GetTracedThread(lldb::tid_t tid);
-
- llvm::Error TraceStart(lldb::tid_t tid,
- const TraceIntelPTStartRequest &request);
-
- llvm::Error TraceStop(lldb::tid_t tid);
-
- size_t GetTracedThreadsCount() const;
-
-private:
- llvm::DenseMap<lldb::tid_t, IntelPTSingleBufferTraceUP> m_thread_traces;
- /// Total actual thread buffer size in bytes
- size_t m_total_buffer_size = 0;
-};
-
-class IntelPTPerThreadProcessTrace;
-using IntelPTPerThreadProcessTraceUP =
- std::unique_ptr<IntelPTPerThreadProcessTrace>;
-
-/// Manages a "process trace" instance by tracing each thread individually.
-class IntelPTPerThreadProcessTrace {
-public:
- /// Start tracing the current process by tracing each of its tids
- /// individually.
- ///
- /// \param[in] request
- /// Intel PT configuration parameters.
- ///
- /// \param[in] current_tids
- /// List of tids currently alive. In the future, whenever a new thread is
- /// spawned, they should be traced by calling the \a TraceStart(tid) method.
- ///
- /// \return
- /// An \a IntelPTMultiCoreTrace instance if tracing was successful, or
- /// an \a llvm::Error otherwise.
- static llvm::Expected<IntelPTPerThreadProcessTraceUP>
- Start(const TraceIntelPTStartRequest &request,
- llvm::ArrayRef<lldb::tid_t> current_tids);
-
- bool TracesThread(lldb::tid_t tid) const;
-
- IntelPTThreadTraceCollection &GetThreadTraces();
-
- llvm::Error TraceStart(lldb::tid_t tid);
-
- llvm::Error TraceStop(lldb::tid_t tid);
-
-private:
- IntelPTPerThreadProcessTrace(const TraceIntelPTStartRequest &request)
- : m_tracing_params(request) {}
-
- IntelPTThreadTraceCollection m_thread_traces;
- /// Params used to trace threads when the user started "process tracing".
- TraceIntelPTStartRequest m_tracing_params;
-};
-
/// Main class that manages intel-pt process and thread tracing.
class IntelPTCollector {
public:
@@ -122,7 +53,7 @@ class IntelPTCollector {
llvm::Error TraceStart(const TraceIntelPTStartRequest &request);
/// Implementation of the jLLDBTraceGetState packet
- llvm::Expected<llvm::json::Value> GetState() const;
+ llvm::Expected<llvm::json::Value> GetState();
/// Implementation of the jLLDBTraceGetBinaryData packet
llvm::Expected<std::vector<uint8_t>>
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
new file mode 100644
index 000000000000..087597c4f2a5
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp
@@ -0,0 +1,40 @@
+//===-- IntelPTPerThreadProcessTrace.cpp ----------------------------------===//
+//
+// 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 "IntelPTPerThreadProcessTrace.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace process_linux;
+using namespace llvm;
+
+bool IntelPTPerThreadProcessTrace::TracesThread(lldb::tid_t tid) const {
+ return m_thread_traces.TracesThread(tid);
+}
+
+Error IntelPTPerThreadProcessTrace::TraceStop(lldb::tid_t tid) {
+ return m_thread_traces.TraceStop(tid);
+}
+
+Error IntelPTPerThreadProcessTrace::TraceStart(lldb::tid_t tid) {
+ if (m_thread_traces.GetTotalBufferSize() +
+ m_tracing_params.trace_buffer_size >
+ static_cast<size_t>(*m_tracing_params.process_buffer_size_limit))
+ return createStringError(
+ inconvertibleErrorCode(),
+ "Thread %" PRIu64 " can't be traced as the process trace size limit "
+ "has been reached. Consider retracing with a higher "
+ "limit.",
+ tid);
+
+ return m_thread_traces.TraceStart(tid, m_tracing_params);
+}
+
+IntelPTThreadTraceCollection &IntelPTPerThreadProcessTrace::GetThreadTraces() {
+ return m_thread_traces;
+}
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
new file mode 100644
index 000000000000..84b749b78620
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h
@@ -0,0 +1,64 @@
+//===-- IntelPTPerThreadProcessTrace.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_IntelPTPerThreadProcessTrace_H_
+#define liblldb_IntelPTPerThreadProcessTrace_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 {
+public:
+ /// Start tracing the current process by tracing each of its tids
+ /// individually.
+ ///
+ /// \param[in] request
+ /// Intel PT configuration parameters.
+ ///
+ /// \param[in] current_tids
+ /// List of tids currently alive. In the future, whenever a new thread is
+ /// spawned, they should be traced by calling the \a TraceStart(tid) method.
+ ///
+ /// \return
+ /// An \a IntelPTMultiCoreTrace instance if tracing was successful, or
+ /// an \a llvm::Error otherwise.
+ static llvm::Expected<IntelPTPerThreadProcessTraceUP>
+ Start(const TraceIntelPTStartRequest &request,
+ llvm::ArrayRef<lldb::tid_t> current_tids);
+
+ bool TracesThread(lldb::tid_t tid) const;
+
+ IntelPTThreadTraceCollection &GetThreadTraces();
+
+ /// \copydoc IntelPTThreadTraceCollection::TraceStart()
+ llvm::Error TraceStart(lldb::tid_t tid);
+
+ /// \copydoc IntelPTThreadTraceCollection::TraceStop()
+ llvm::Error TraceStop(lldb::tid_t tid);
+
+private:
+ IntelPTPerThreadProcessTrace(const TraceIntelPTStartRequest &request)
+ : m_tracing_params(request) {}
+
+ IntelPTThreadTraceCollection m_thread_traces;
+ /// Params used to trace threads when the user started "process tracing".
+ TraceIntelPTStartRequest m_tracing_params;
+};
+
+} // namespace process_linux
+} // namespace lldb_private
+
+#endif // liblldb_IntelPTPerThreadProcessTrace_H_
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp b/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp
new file mode 100644
index 000000000000..2ae179ce795f
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp
@@ -0,0 +1,74 @@
+//===-- IntelPTThreadTraceCollection.cpp ----------------------------------===//
+//
+// 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 "IntelPTThreadTraceCollection.h"
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace process_linux;
+using namespace llvm;
+
+bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
+ return m_thread_traces.count(tid);
+}
+
+Error IntelPTThreadTraceCollection::TraceStop(lldb::tid_t tid) {
+ auto it = m_thread_traces.find(tid);
+ if (it == m_thread_traces.end())
+ return createStringError(inconvertibleErrorCode(),
+ "Thread %" PRIu64 " not currently traced", tid);
+ m_total_buffer_size -= it->second->GetTraceBufferSize();
+ m_thread_traces.erase(tid);
+ return Error::success();
+}
+
+Error IntelPTThreadTraceCollection::TraceStart(
+ lldb::tid_t tid, const TraceIntelPTStartRequest &request) {
+ if (TracesThread(tid))
+ return createStringError(inconvertibleErrorCode(),
+ "Thread %" PRIu64 " already traced", tid);
+
+ Expected<IntelPTSingleBufferTraceUP> trace_up =
+ IntelPTSingleBufferTrace::Start(request, tid, /*core_id=*/None,
+ TraceCollectionState::Running);
+ if (!trace_up)
+ return trace_up.takeError();
+
+ m_total_buffer_size += (*trace_up)->GetTraceBufferSize();
+ m_thread_traces.try_emplace(tid, std::move(*trace_up));
+ return Error::success();
+}
+
+size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
+ return m_total_buffer_size;
+}
+
+void IntelPTThreadTraceCollection::ForEachThread(
+ std::function<void(lldb::tid_t tid, IntelPTSingleBufferTrace &thread_trace)>
+ callback) {
+ for (auto &it : m_thread_traces)
+ callback(it.first, *it.second);
+}
+
+Expected<IntelPTSingleBufferTrace &>
+IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) {
+ auto it = m_thread_traces.find(tid);
+ if (it == m_thread_traces.end())
+ return createStringError(inconvertibleErrorCode(),
+ "Thread %" PRIu64 " not currently traced", tid);
+ return *it->second.get();
+}
+
+void IntelPTThreadTraceCollection::Clear() {
+ m_thread_traces.clear();
+ m_total_buffer_size = 0;
+}
+
+size_t IntelPTThreadTraceCollection::GetTracedThreadsCount() const {
+ return m_thread_traces.size();
+}
diff --git a/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.h b/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.h
new file mode 100644
index 000000000000..3dfbc2ee34d1
--- /dev/null
+++ b/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.h
@@ -0,0 +1,71 @@
+//===-- IntelPTThreadTraceCollection.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_IntelPTPerThreadTraceCollection_H_
+#define liblldb_IntelPTPerThreadTraceCollection_H_
+
+#include "IntelPTSingleBufferTrace.h"
+
+namespace lldb_private {
+namespace process_linux {
+
+/// Manages a list of thread traces.
+class IntelPTThreadTraceCollection {
+public:
+ IntelPTThreadTraceCollection() {}
+
+ /// Dispose of all traces
+ void Clear();
+
+ /// \return
+ /// \b true if and only if this instance of tracing the provided \p tid.
+ bool TracesThread(lldb::tid_t tid) const;
+
+ /// \return
+ /// The total sum of the trace buffer sizes used by this collection.
+ size_t GetTotalBufferSize() const;
+
+ /// Execute the provided callback on each thread that is being traced.
+ ///
+ /// \param[in] callback.tid
+ /// The id of the thread that is being traced.
+ ///
+ /// \param[in] callback.core_trace
+ /// The single-buffer trace instance for the given core.
+ void ForEachThread(std::function<void(lldb::tid_t tid,
+ IntelPTSingleBufferTrace &thread_trace)>
+ callback);
+
+ llvm::Expected<IntelPTSingleBufferTrace &> GetTracedThread(lldb::tid_t tid);
+
+ /// Start tracing the thread given by its \p tid.
+ ///
+ /// \return
+ /// An error if the operation failed.
+ llvm::Error TraceStart(lldb::tid_t tid,
+ const TraceIntelPTStartRequest &request);
+
+ /// Stop tracing the thread given by its \p tid.
+ ///
+ /// \return
+ /// An error if the given thread is not being traced or tracing couldn't be
+ /// stopped.
+ llvm::Error TraceStop(lldb::tid_t tid);
+
+ size_t GetTracedThreadsCount() const;
+
+private:
+ llvm::DenseMap<lldb::tid_t, IntelPTSingleBufferTraceUP> m_thread_traces;
+ /// Total actual thread buffer size in bytes
+ size_t m_total_buffer_size = 0;
+};
+
+} // namespace process_linux
+} // namespace lldb_private
+
+#endif // liblldb_IntelPTPerThreadTraceCollection_H_
More information about the lldb-commits
mailing list