| 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 | #include "../common/ThreadPostMortemTrace.h" |
| 10 | #include "LibiptDecoder.h" |
| 11 | #include "TraceIntelPT.h" |
| 12 | #include "llvm/Support/MemoryBuffer.h" |
| 13 | #include <optional> |
| 14 | #include <utility> |
| 15 | |
| 16 | using namespace lldb; |
| 17 | using namespace lldb_private; |
| 18 | using namespace lldb_private::trace_intel_pt; |
| 19 | using namespace llvm; |
| 20 | |
| 21 | ThreadDecoder::ThreadDecoder(const ThreadSP &thread_sp, TraceIntelPT &trace) |
| 22 | : m_thread_sp(thread_sp), m_trace(trace) {} |
| 23 | |
| 24 | Expected<std::optional<uint64_t>> ThreadDecoder::FindLowestTSC() { |
| 25 | std::optional<uint64_t> lowest_tsc; |
| 26 | Error err = m_trace.OnThreadBufferRead( |
| 27 | tid: m_thread_sp->GetID(), callback: [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error { |
| 28 | Expected<std::optional<uint64_t>> tsc = |
| 29 | FindLowestTSCInTrace(trace_intel_pt&: m_trace, buffer: data); |
| 30 | if (!tsc) |
| 31 | return tsc.takeError(); |
| 32 | lowest_tsc = *tsc; |
| 33 | return Error::success(); |
| 34 | }); |
| 35 | if (err) |
| 36 | return std::move(err); |
| 37 | return lowest_tsc; |
| 38 | } |
| 39 | |
| 40 | Expected<DecodedThreadSP> ThreadDecoder::Decode() { |
| 41 | if (!m_decoded_thread.has_value()) { |
| 42 | if (Expected<DecodedThreadSP> decoded_thread = DoDecode()) { |
| 43 | m_decoded_thread = *decoded_thread; |
| 44 | } else { |
| 45 | return decoded_thread.takeError(); |
| 46 | } |
| 47 | } |
| 48 | return *m_decoded_thread; |
| 49 | } |
| 50 | |
| 51 | llvm::Expected<DecodedThreadSP> ThreadDecoder::DoDecode() { |
| 52 | return m_trace.GetThreadTimer(tid: m_thread_sp->GetID()) |
| 53 | .TimeTask(name: "Decoding instructions" , task: [&]() -> Expected<DecodedThreadSP> { |
| 54 | DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>( |
| 55 | args&: m_thread_sp, args: m_trace.GetPerfZeroTscConversion()); |
| 56 | |
| 57 | Error err = m_trace.OnThreadBufferRead( |
| 58 | tid: m_thread_sp->GetID(), callback: [&](llvm::ArrayRef<uint8_t> data) { |
| 59 | return DecodeSingleTraceForThread(decoded_thread&: *decoded_thread_sp, trace_intel_pt&: m_trace, |
| 60 | buffer: data); |
| 61 | }); |
| 62 | |
| 63 | if (err) |
| 64 | return std::move(err); |
| 65 | return decoded_thread_sp; |
| 66 | }); |
| 67 | } |
| 68 | |