This revision was landed with ongoing or failed builds. This revision was automatically updated to reflect the committed changes. Closed by commit rG1188faa7ab4b: [trace][intelpt] Support system-wide tracing [6] - Break IntelPTCollector into… (authored by Walter Erquinigo <wall...@fb.com>).
Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D125047/new/ https://reviews.llvm.org/D125047 Files: 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 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
Index: lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.h =================================================================== --- /dev/null +++ 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_ Index: lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp =================================================================== --- /dev/null +++ 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(); +} Index: lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.h =================================================================== --- /dev/null +++ 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_ Index: lldb/source/Plugins/Process/Linux/IntelPTPerThreadProcessTrace.cpp =================================================================== --- /dev/null +++ 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; +} Index: lldb/source/Plugins/Process/Linux/IntelPTCollector.h =================================================================== --- lldb/source/Plugins/Process/Linux/IntelPTCollector.h +++ 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 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 @@ 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>> Index: lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp +++ lldb/source/Plugins/Process/Linux/IntelPTCollector.cpp @@ -32,101 +32,6 @@ 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 @@ 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 @@ 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(), {}}); Index: lldb/source/Plugins/Process/Linux/CMakeLists.txt =================================================================== --- lldb/source/Plugins/Process/Linux/CMakeLists.txt +++ lldb/source/Plugins/Process/Linux/CMakeLists.txt @@ -2,6 +2,8 @@ IntelPTCollector.cpp IntelPTSingleBufferTrace.cpp IntelPTMultiCoreTrace.cpp + IntelPTPerThreadProcessTrace.cpp + IntelPTThreadTraceCollection.cpp NativeProcessLinux.cpp NativeRegisterContextLinux.cpp NativeRegisterContextLinux_arm.cpp Index: lldb/include/lldb/Utility/TraceGDBRemotePackets.h =================================================================== --- lldb/include/lldb/Utility/TraceGDBRemotePackets.h +++ 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"
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits