181ad6265SDimitry Andric //===-- ThreadDecoder.cpp --======-----------------------------------------===//
281ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
381ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
481ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
581ad6265SDimitry Andric //
681ad6265SDimitry Andric //===----------------------------------------------------------------------===//
781ad6265SDimitry Andric
881ad6265SDimitry Andric #include "ThreadDecoder.h"
981ad6265SDimitry Andric #include "../common/ThreadPostMortemTrace.h"
1081ad6265SDimitry Andric #include "LibiptDecoder.h"
1181ad6265SDimitry Andric #include "TraceIntelPT.h"
12*bdd1243dSDimitry Andric #include "llvm/Support/MemoryBuffer.h"
13*bdd1243dSDimitry Andric #include <optional>
1481ad6265SDimitry Andric #include <utility>
1581ad6265SDimitry Andric
1681ad6265SDimitry Andric using namespace lldb;
1781ad6265SDimitry Andric using namespace lldb_private;
1881ad6265SDimitry Andric using namespace lldb_private::trace_intel_pt;
1981ad6265SDimitry Andric using namespace llvm;
2081ad6265SDimitry Andric
ThreadDecoder(const ThreadSP & thread_sp,TraceIntelPT & trace)2181ad6265SDimitry Andric ThreadDecoder::ThreadDecoder(const ThreadSP &thread_sp, TraceIntelPT &trace)
2281ad6265SDimitry Andric : m_thread_sp(thread_sp), m_trace(trace) {}
2381ad6265SDimitry Andric
FindLowestTSC()24*bdd1243dSDimitry Andric Expected<std::optional<uint64_t>> ThreadDecoder::FindLowestTSC() {
25*bdd1243dSDimitry Andric std::optional<uint64_t> lowest_tsc;
26972a253aSDimitry Andric Error err = m_trace.OnThreadBufferRead(
27972a253aSDimitry Andric m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) -> llvm::Error {
28*bdd1243dSDimitry Andric Expected<std::optional<uint64_t>> tsc =
29*bdd1243dSDimitry Andric FindLowestTSCInTrace(m_trace, data);
30972a253aSDimitry Andric if (!tsc)
31972a253aSDimitry Andric return tsc.takeError();
32972a253aSDimitry Andric lowest_tsc = *tsc;
33972a253aSDimitry Andric return Error::success();
34972a253aSDimitry Andric });
35972a253aSDimitry Andric if (err)
36972a253aSDimitry Andric return std::move(err);
37972a253aSDimitry Andric return lowest_tsc;
38972a253aSDimitry Andric }
39972a253aSDimitry Andric
Decode()4081ad6265SDimitry Andric Expected<DecodedThreadSP> ThreadDecoder::Decode() {
41*bdd1243dSDimitry Andric if (!m_decoded_thread.has_value()) {
4281ad6265SDimitry Andric if (Expected<DecodedThreadSP> decoded_thread = DoDecode()) {
4381ad6265SDimitry Andric m_decoded_thread = *decoded_thread;
4481ad6265SDimitry Andric } else {
4581ad6265SDimitry Andric return decoded_thread.takeError();
4681ad6265SDimitry Andric }
4781ad6265SDimitry Andric }
4881ad6265SDimitry Andric return *m_decoded_thread;
4981ad6265SDimitry Andric }
5081ad6265SDimitry Andric
DoDecode()5181ad6265SDimitry Andric llvm::Expected<DecodedThreadSP> ThreadDecoder::DoDecode() {
52753f127fSDimitry Andric return m_trace.GetThreadTimer(m_thread_sp->GetID())
53*bdd1243dSDimitry Andric .TimeTask("Decoding instructions", [&]() -> Expected<DecodedThreadSP> {
54972a253aSDimitry Andric DecodedThreadSP decoded_thread_sp = std::make_shared<DecodedThread>(
55972a253aSDimitry Andric m_thread_sp, m_trace.GetPerfZeroTscConversion());
5681ad6265SDimitry Andric
5781ad6265SDimitry Andric Error err = m_trace.OnThreadBufferRead(
5881ad6265SDimitry Andric m_thread_sp->GetID(), [&](llvm::ArrayRef<uint8_t> data) {
5981ad6265SDimitry Andric return DecodeSingleTraceForThread(*decoded_thread_sp, m_trace,
6081ad6265SDimitry Andric data);
6181ad6265SDimitry Andric });
6281ad6265SDimitry Andric
6381ad6265SDimitry Andric if (err)
6481ad6265SDimitry Andric return std::move(err);
6581ad6265SDimitry Andric return decoded_thread_sp;
6681ad6265SDimitry Andric });
6781ad6265SDimitry Andric }
68