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 #include "../common/ThreadPostMortemTrace.h"
106423b502SWalter Erquinigo #include "LibiptDecoder.h"
116423b502SWalter Erquinigo #include "TraceIntelPT.h"
12c4fb631cSWalter Erquinigo #include "llvm/Support/MemoryBuffer.h"
13f190ce62SKazu Hirata #include <optional>
146423b502SWalter Erquinigo #include <utility>
156423b502SWalter Erquinigo
166423b502SWalter Erquinigo using namespace lldb;
176423b502SWalter Erquinigo using namespace lldb_private;
186423b502SWalter Erquinigo using namespace lldb_private::trace_intel_pt;
196423b502SWalter Erquinigo using namespace llvm;
206423b502SWalter Erquinigo
ThreadDecoder(const ThreadSP & thread_sp,TraceIntelPT & trace)21e0cfe20aSWalter Erquinigo ThreadDecoder::ThreadDecoder(const ThreadSP &thread_sp, TraceIntelPT &trace)
22e0cfe20aSWalter Erquinigo : m_thread_sp(thread_sp), m_trace(trace) {}
236423b502SWalter Erquinigo
FindLowestTSC()24*2fe83274SKazu Hirata Expected<std::optional<uint64_t>> ThreadDecoder::FindLowestTSC() {
25*2fe83274SKazu Hirata std::optional<uint64_t> lowest_tsc;
264f676c25SWalter Erquinigo Error err = m_trace.OnThreadBufferRead(
274f676c25SWalter Erquinigo m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
28*2fe83274SKazu Hirata Expected<std::optional<uint64_t>> tsc =
29*2fe83274SKazu Hirata FindLowestTSCInTrace(m_trace, data);
304f676c25SWalter Erquinigo if (!tsc)
314f676c25SWalter Erquinigo return tsc.takeError();
324f676c25SWalter Erquinigo lowest_tsc = *tsc;
334f676c25SWalter Erquinigo return Error::success();
344f676c25SWalter Erquinigo });
354f676c25SWalter Erquinigo if (err)
364f676c25SWalter Erquinigo return std::move(err);
374f676c25SWalter Erquinigo return lowest_tsc;
384f676c25SWalter Erquinigo }
394f676c25SWalter Erquinigo
Decode()40a7d6c3efSWalter Erquinigo Expected<DecodedThreadSP> ThreadDecoder::Decode() {
41c903136fSKazu Hirata if (!m_decoded_thread.has_value()) {
42a7d6c3efSWalter Erquinigo if (Expected<DecodedThreadSP> decoded_thread = DoDecode()) {
43a7d6c3efSWalter Erquinigo m_decoded_thread = *decoded_thread;
44a7d6c3efSWalter Erquinigo } else {
45a7d6c3efSWalter Erquinigo return decoded_thread.takeError();
46a7d6c3efSWalter Erquinigo }
47a7d6c3efSWalter Erquinigo }
486423b502SWalter Erquinigo return *m_decoded_thread;
496423b502SWalter Erquinigo }
506423b502SWalter Erquinigo
DoDecode()51a7d6c3efSWalter Erquinigo llvm::Expected<DecodedThreadSP> ThreadDecoder::DoDecode() {
529f9464e0SPeicong Wu return m_trace.GetThreadTimer(m_thread_sp->GetID())
53d179ea12SWalter Erquinigo .TimeTask("Decoding instructions", [&]() -> Expected<DecodedThreadSP> {
544f676c25SWalter Erquinigo DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>(
554f676c25SWalter Erquinigo m_thread_sp, m_trace.GetPerfZeroTscConversion());
566423b502SWalter Erquinigo
57e0cfe20aSWalter Erquinigo Error err = m_trace.OnThreadBufferRead(
58e0cfe20aSWalter Erquinigo m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) {
59a7d6c3efSWalter Erquinigo return DecodeSingleTraceForThread(*decoded_thread_sp, m_trace,
60a7d6c3efSWalter Erquinigo data);
61e0cfe20aSWalter Erquinigo });
62bdf3e7e5SWalter Erquinigo
63e0cfe20aSWalter Erquinigo if (err)
64a7d6c3efSWalter Erquinigo return std::move(err);
656423b502SWalter Erquinigo return decoded_thread_sp;
66bdf3e7e5SWalter Erquinigo });
676423b502SWalter Erquinigo }
68