xref: /llvm-project/lldb/source/Plugins/Process/Linux/IntelPTThreadTraceCollection.cpp (revision fc5ef57c7df5805c828de2e3e334c2cf74648e58)
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 
16 bool IntelPTThreadTraceCollection::TracesThread(lldb::tid_t tid) const {
17   return m_thread_traces.count(tid);
18 }
19 
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.GetTraceBufferSize();
26   m_thread_traces.erase(tid);
27   return Error::success();
28 }
29 
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->GetTraceBufferSize();
42   m_thread_traces.try_emplace(tid, std::move(*trace));
43   return Error::success();
44 }
45 
46 size_t IntelPTThreadTraceCollection::GetTotalBufferSize() const {
47   return m_total_buffer_size;
48 }
49 
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 &>
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 
66 void IntelPTThreadTraceCollection::Clear() {
67   m_thread_traces.clear();
68   m_total_buffer_size = 0;
69 }
70 
71 size_t IntelPTThreadTraceCollection::GetTracedThreadsCount() const {
72   return m_thread_traces.size();
73 }
74 
75 llvm::Expected<llvm::Optional<std::vector<uint8_t>>>
76 IntelPTThreadTraceCollection::TryGetBinaryData(
77     const TraceGetBinaryDataRequest &request) {
78   if (!request.tid)
79     return None;
80   if (request.kind != IntelPTDataKinds::kTraceBuffer)
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->GetTraceBuffer(request.offset, request.size);
89   else
90     return trace.takeError();
91 }
92