xref: /openbsd-src/gnu/llvm/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp (revision f6aab3d83b51b91c24247ad2c2573574de475a82)
1*f6aab3d8Srobert //===-- IntelPTThreadTraceCollection.cpp ----------------------------------===//
2*f6aab3d8Srobert //
3*f6aab3d8Srobert // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*f6aab3d8Srobert // See https://llvm.org/LICENSE.txt for license information.
5*f6aab3d8Srobert // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*f6aab3d8Srobert //
7*f6aab3d8Srobert //===----------------------------------------------------------------------===//
8*f6aab3d8Srobert 
9*f6aab3d8Srobert #include "IntelPTThreadTraceCollection.h"
10*f6aab3d8Srobert #include <optional>
11*f6aab3d8Srobert 
12*f6aab3d8Srobert using namespace lldb;
13*f6aab3d8Srobert using namespace lldb_private;
14*f6aab3d8Srobert using namespace process_linux;
15*f6aab3d8Srobert using namespace llvm;
16*f6aab3d8Srobert 
TracesThread(lldb::tid_t tid) const17*f6aab3d8Srobert bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
18*f6aab3d8Srobert   return m_thread_traces.count(tid);
19*f6aab3d8Srobert }
20*f6aab3d8Srobert 
TraceStop(lldb::tid_t tid)21*f6aab3d8Srobert Error IntelPTThreadTraceCollection::TraceStop(lldb::tid_t tid) {
22*f6aab3d8Srobert   auto it = m_thread_traces.find(tid);
23*f6aab3d8Srobert   if (it == m_thread_traces.end())
24*f6aab3d8Srobert     return createStringError(inconvertibleErrorCode(),
25*f6aab3d8Srobert                              "Thread %" PRIu64 " not currently traced", tid);
26*f6aab3d8Srobert   m_total_buffer_size -= it->second.GetIptTraceSize();
27*f6aab3d8Srobert   m_thread_traces.erase(tid);
28*f6aab3d8Srobert   return Error::success();
29*f6aab3d8Srobert }
30*f6aab3d8Srobert 
TraceStart(lldb::tid_t tid,const TraceIntelPTStartRequest & request)31*f6aab3d8Srobert Error IntelPTThreadTraceCollection::TraceStart(
32*f6aab3d8Srobert     lldb::tid_t tid, const TraceIntelPTStartRequest &request) {
33*f6aab3d8Srobert   if (TracesThread(tid))
34*f6aab3d8Srobert     return createStringError(inconvertibleErrorCode(),
35*f6aab3d8Srobert                              "Thread %" PRIu64 " already traced", tid);
36*f6aab3d8Srobert 
37*f6aab3d8Srobert   Expected<IntelPTSingleBufferTrace> trace =
38*f6aab3d8Srobert       IntelPTSingleBufferTrace::Start(request, tid);
39*f6aab3d8Srobert   if (!trace)
40*f6aab3d8Srobert     return trace.takeError();
41*f6aab3d8Srobert 
42*f6aab3d8Srobert   m_total_buffer_size += trace->GetIptTraceSize();
43*f6aab3d8Srobert   m_thread_traces.try_emplace(tid, std::move(*trace));
44*f6aab3d8Srobert   return Error::success();
45*f6aab3d8Srobert }
46*f6aab3d8Srobert 
GetTotalBufferSize() const47*f6aab3d8Srobert size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
48*f6aab3d8Srobert   return m_total_buffer_size;
49*f6aab3d8Srobert }
50*f6aab3d8Srobert 
ForEachThread(std::function<void (lldb::tid_t tid,IntelPTSingleBufferTrace & thread_trace)> callback)51*f6aab3d8Srobert void IntelPTThreadTraceCollection::ForEachThread(
52*f6aab3d8Srobert     std::function<void(lldb::tid_t tid, IntelPTSingleBufferTrace &thread_trace)>
53*f6aab3d8Srobert         callback) {
54*f6aab3d8Srobert   for (auto &it : m_thread_traces)
55*f6aab3d8Srobert     callback(it.first, it.second);
56*f6aab3d8Srobert }
57*f6aab3d8Srobert 
58*f6aab3d8Srobert Expected<IntelPTSingleBufferTrace &>
GetTracedThread(lldb::tid_t tid)59*f6aab3d8Srobert IntelPTThreadTraceCollection::GetTracedThread(lldb::tid_t tid) {
60*f6aab3d8Srobert   auto it = m_thread_traces.find(tid);
61*f6aab3d8Srobert   if (it == m_thread_traces.end())
62*f6aab3d8Srobert     return createStringError(inconvertibleErrorCode(),
63*f6aab3d8Srobert                              "Thread %" PRIu64 " not currently traced", tid);
64*f6aab3d8Srobert   return it->second;
65*f6aab3d8Srobert }
66*f6aab3d8Srobert 
Clear()67*f6aab3d8Srobert void IntelPTThreadTraceCollection::Clear() {
68*f6aab3d8Srobert   m_thread_traces.clear();
69*f6aab3d8Srobert   m_total_buffer_size = 0;
70*f6aab3d8Srobert }
71*f6aab3d8Srobert 
GetTracedThreadsCount() const72*f6aab3d8Srobert size_t IntelPTThreadTraceCollection::GetTracedThreadsCount() const {
73*f6aab3d8Srobert   return m_thread_traces.size();
74*f6aab3d8Srobert }
75*f6aab3d8Srobert 
76*f6aab3d8Srobert llvm::Expected<std::optional<std::vector<uint8_t>>>
TryGetBinaryData(const TraceGetBinaryDataRequest & request)77*f6aab3d8Srobert IntelPTThreadTraceCollection::TryGetBinaryData(
78*f6aab3d8Srobert     const TraceGetBinaryDataRequest &request) {
79*f6aab3d8Srobert   if (!request.tid)
80*f6aab3d8Srobert     return std::nullopt;
81*f6aab3d8Srobert   if (request.kind != IntelPTDataKinds::kIptTrace)
82*f6aab3d8Srobert     return std::nullopt;
83*f6aab3d8Srobert 
84*f6aab3d8Srobert   if (!TracesThread(*request.tid))
85*f6aab3d8Srobert     return std::nullopt;
86*f6aab3d8Srobert 
87*f6aab3d8Srobert   if (Expected<IntelPTSingleBufferTrace &> trace =
88*f6aab3d8Srobert           GetTracedThread(*request.tid))
89*f6aab3d8Srobert     return trace->GetIptTrace();
90*f6aab3d8Srobert   else
91*f6aab3d8Srobert     return trace.takeError();
92*f6aab3d8Srobert }
93