1 //===-- ThreadDecoder.cpp --======-----------------------------------------===//
2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
3 // See https://llvm.org/LICENSE.txt for license information.
4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
5 //
6 //===----------------------------------------------------------------------===//
7 
8 #include "ThreadDecoder.h"
9 
10 #include "llvm/Support/MemoryBuffer.h"
11 
12 #include "../common/ThreadPostMortemTrace.h"
13 #include "LibiptDecoder.h"
14 #include "TraceIntelPT.h"
15 
16 #include <utility>
17 
18 using namespace lldb;
19 using namespace lldb_private;
20 using namespace lldb_private::trace_intel_pt;
21 using namespace llvm;
22 
23 ThreadDecoder::ThreadDecoder(const ThreadSP &thread_sp, TraceIntelPT &trace)
24     : m_thread_sp(thread_sp), m_trace(trace) {}
25 
26 Expected<Optional<uint64_t>> ThreadDecoder::FindLowestTSC() {
27   Optional<uint64_t> lowest_tsc;
28   Error err = m_trace.OnThreadBufferRead(
29       m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
30         Expected<Optional<uint64_t>> tsc = FindLowestTSCInTrace(m_trace, data);
31         if (!tsc)
32           return tsc.takeError();
33         lowest_tsc = *tsc;
34         return Error::success();
35       });
36   if (err)
37     return std::move(err);
38   return lowest_tsc;
39 }
40 
41 Expected<DecodedThreadSP> ThreadDecoder::Decode() {
42   if (!m_decoded_thread.hasValue()) {
43     if (Expected<DecodedThreadSP> decoded_thread = DoDecode()) {
44       m_decoded_thread = *decoded_thread;
45     } else {
46       return decoded_thread.takeError();
47     }
48   }
49   return *m_decoded_thread;
50 }
51 
52 llvm::Expected<DecodedThreadSP> ThreadDecoder::DoDecode() {
53   return m_trace.GetThreadTimer(m_thread_sp->GetID())
54       .TimeTask(
55           "Decoding instructions", [&]() -> Expected<DecodedThreadSP> {
56             DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>(
57                 m_thread_sp, m_trace.GetPerfZeroTscConversion());
58 
59             Error err = m_trace.OnThreadBufferRead(
60                 m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) {
61                   return DecodeSingleTraceForThread(*decoded_thread_sp, m_trace,
62                                                     data);
63                 });
64 
65             if (err)
66               return std::move(err);
67             return decoded_thread_sp;
68           });
69 }
70