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