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