16423b502SWalter Erquinigo //===-- ThreadDecoder.cpp --======-----------------------------------------===//
26423b502SWalter Erquinigo // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
36423b502SWalter Erquinigo // See https://llvm.org/LICENSE.txt for license information.
46423b502SWalter Erquinigo // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
56423b502SWalter Erquinigo //
66423b502SWalter Erquinigo //===----------------------------------------------------------------------===//
76423b502SWalter Erquinigo
86423b502SWalter Erquinigo #include "ThreadDecoder.h"
96423b502SWalter Erquinigo
106423b502SWalter Erquinigo #include "llvm/Support/MemoryBuffer.h"
116423b502SWalter Erquinigo
126423b502SWalter Erquinigo #include "../common/ThreadPostMortemTrace.h"
136423b502SWalter Erquinigo #include "LibiptDecoder.h"
146423b502SWalter Erquinigo #include "TraceIntelPT.h"
156423b502SWalter Erquinigo
166423b502SWalter Erquinigo #include <utility>
176423b502SWalter Erquinigo
186423b502SWalter Erquinigo using namespace lldb;
196423b502SWalter Erquinigo using namespace lldb_private;
206423b502SWalter Erquinigo using namespace lldb_private::trace_intel_pt;
216423b502SWalter Erquinigo using namespace llvm;
226423b502SWalter Erquinigo
ThreadDecoder(const ThreadSP & thread_sp,TraceIntelPT & trace)23e0cfe20aSWalter Erquinigo ThreadDecoder::ThreadDecoder(const ThreadSP &thread_sp, TraceIntelPT &trace)
24e0cfe20aSWalter Erquinigo : m_thread_sp(thread_sp), m_trace(trace) {}
256423b502SWalter Erquinigo
FindLowestTSC()26*4f676c25SWalter Erquinigo Expected<Optional<uint64_t>> ThreadDecoder::FindLowestTSC() {
27*4f676c25SWalter Erquinigo Optional<uint64_t> lowest_tsc;
28*4f676c25SWalter Erquinigo Error err = m_trace.OnThreadBufferRead(
29*4f676c25SWalter Erquinigo m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
30*4f676c25SWalter Erquinigo Expected<Optional<uint64_t>> tsc = FindLowestTSCInTrace(m_trace, data);
31*4f676c25SWalter Erquinigo if (!tsc)
32*4f676c25SWalter Erquinigo return tsc.takeError();
33*4f676c25SWalter Erquinigo lowest_tsc = *tsc;
34*4f676c25SWalter Erquinigo return Error::success();
35*4f676c25SWalter Erquinigo });
36*4f676c25SWalter Erquinigo if (err)
37*4f676c25SWalter Erquinigo return std::move(err);
38*4f676c25SWalter Erquinigo return lowest_tsc;
39*4f676c25SWalter Erquinigo }
40*4f676c25SWalter Erquinigo
Decode()41a7d6c3efSWalter Erquinigo Expected<DecodedThreadSP> ThreadDecoder::Decode() {
42a7d6c3efSWalter Erquinigo if (!m_decoded_thread.hasValue()) {
43a7d6c3efSWalter Erquinigo if (Expected<DecodedThreadSP> decoded_thread = DoDecode()) {
44a7d6c3efSWalter Erquinigo m_decoded_thread = *decoded_thread;
45a7d6c3efSWalter Erquinigo } else {
46a7d6c3efSWalter Erquinigo return decoded_thread.takeError();
47a7d6c3efSWalter Erquinigo }
48a7d6c3efSWalter Erquinigo }
496423b502SWalter Erquinigo return *m_decoded_thread;
506423b502SWalter Erquinigo }
516423b502SWalter Erquinigo
DoDecode()52a7d6c3efSWalter Erquinigo llvm::Expected<DecodedThreadSP> ThreadDecoder::DoDecode() {
539f9464e0SPeicong Wu return m_trace.GetThreadTimer(m_thread_sp->GetID())
549f9464e0SPeicong Wu .TimeTask(
55a7d6c3efSWalter Erquinigo "Decoding instructions", [&]() -> Expected<DecodedThreadSP> {
56*4f676c25SWalter Erquinigo DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>(
57*4f676c25SWalter Erquinigo m_thread_sp, m_trace.GetPerfZeroTscConversion());
586423b502SWalter Erquinigo
59e0cfe20aSWalter Erquinigo Error err = m_trace.OnThreadBufferRead(
60e0cfe20aSWalter Erquinigo m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) {
61a7d6c3efSWalter Erquinigo return DecodeSingleTraceForThread(*decoded_thread_sp, m_trace,
62a7d6c3efSWalter Erquinigo data);
63e0cfe20aSWalter Erquinigo });
64bdf3e7e5SWalter Erquinigo
65e0cfe20aSWalter Erquinigo if (err)
66a7d6c3efSWalter Erquinigo return std::move(err);
676423b502SWalter Erquinigo return decoded_thread_sp;
68bdf3e7e5SWalter Erquinigo });
696423b502SWalter Erquinigo }
70