diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.h @@ -146,6 +146,12 @@ /// The instructions of the trace. llvm::ArrayRef GetInstructions() const; + /// Append a successfully decoded instruction to thread. + void AppendInstructions(pt_insn insn, ...); + + /// Append a error of instruction decoding to thread. + void AppendError(llvm::Error err); + /// Get a new cursor for the decoded thread. lldb::TraceCursorUP GetCursor(); @@ -162,8 +168,10 @@ private: /// When adding new members to this class, make sure /// to update \a CalculateApproximateMemoryUsage() accordingly. - lldb::ThreadSP m_thread_sp; std::vector m_instructions; + std::vector m_errors; + + lldb::ThreadSP m_thread_sp; size_t m_raw_trace_size; }; diff --git a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp --- a/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/DecodedThread.cpp @@ -119,6 +119,17 @@ return std::make_unique(m_thread_sp, shared_from_this()); } +void DecodedThread::AppendInstructions(pt_insn insn, ...) { + va_list args; + va_start(args, insn); + m_instructions.emplace_back(insn, args); + va_end(args); +} + +void DecodedThread::AppendError(llvm::Error err) { + m_errors.emplace_back(err); +} + size_t DecodedThread::CalculateApproximateMemoryUsage() const { return m_raw_trace_size + IntelPTInstruction::GetNonErrorMemoryUsage() * m_instructions.size() diff --git a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp --- a/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp +++ b/lldb/source/Plugins/Trace/intel-pt/IntelPTDecoder.cpp @@ -104,9 +104,11 @@ /// /// \return /// The decoded instructions. -static std::vector -DecodeInstructions(pt_insn_decoder &decoder) { - std::vector instructions; +static DecodedThread DecodeInstructions(pt_insn_decoder &decoder, + const ThreadSP &thread_sp, + const size_t raw_trace_size) { + DecodedThread thread = DecodedThread( + thread_sp, std::vector(), raw_trace_size); while (true) { int errcode = FindNextSynchronizationPoint(decoder); @@ -114,7 +116,8 @@ break; if (errcode < 0) { - instructions.emplace_back(make_error(errcode)); + thread.AppendError(make_error(errcode)); + // instructions.emplace_back(make_error(errcode)); break; } @@ -123,7 +126,7 @@ while (true) { errcode = ProcessPTEvents(decoder, errcode); if (errcode < 0) { - instructions.emplace_back(make_error(errcode)); + thread.AppendError(make_error(errcode)); break; } pt_insn insn; @@ -133,7 +136,7 @@ break; if (errcode < 0) { - instructions.emplace_back(make_error(errcode, insn.ip)); + thread.AppendError(make_error(errcode, insn.ip)); break; } @@ -142,22 +145,21 @@ if (time_error == -pte_invalid) { // This happens if we invoke the pt_insn_time method incorrectly, // but the instruction is good though. - instructions.emplace_back( - make_error(time_error, insn.ip)); - instructions.emplace_back(insn); + thread.AppendError(make_error(time_error, insn.ip)); + thread.AppendInstructions(insn); break; } if (time_error == -pte_no_time) { // We simply don't have time information, i.e. None of TSC, MTC or CYC // was enabled. - instructions.emplace_back(insn); + thread.AppendInstructions(insn); } else { - instructions.emplace_back(insn, time); + thread.AppendInstructions(insn, time); } } } - return instructions; + return thread; } /// Callback used by libipt for reading the process memory. @@ -176,9 +178,9 @@ return bytes_read; } -static Expected> -DecodeInMemoryTrace(Process &process, TraceIntelPT &trace_intel_pt, - MutableArrayRef buffer) { +static Expected DecodeInMemoryTrace( + const ThreadSP &thread_sp, Process &process, TraceIntelPT &trace_intel_pt, + MutableArrayRef buffer, const size_t raw_trace_size) { Expected cpu_info = trace_intel_pt.GetCPUInfo(); if (!cpu_info) return cpu_info.takeError(); @@ -203,77 +205,76 @@ assert(errcode == 0); (void)errcode; - std::vector instructions = DecodeInstructions(*decoder); + DecodedThread decoded_thread = + DecodeInstructions(*decoder, thread_sp, raw_trace_size); pt_insn_free_decoder(decoder); - return instructions; + return decoded_thread.shared_from_this(); } +// --------------------------- -static Expected> -DecodeTraceFile(Process &process, TraceIntelPT &trace_intel_pt, - const FileSpec &trace_file, size_t &raw_trace_size) { - ErrorOr> trace_or_error = - MemoryBuffer::getFile(trace_file.GetPath()); - if (std::error_code err = trace_or_error.getError()) - return errorCodeToError(err); - - MemoryBuffer &trace = **trace_or_error; - MutableArrayRef trace_data( - // The libipt library does not modify the trace buffer, hence the - // following cast is safe. - reinterpret_cast(const_cast(trace.getBufferStart())), - trace.getBufferSize()); - raw_trace_size = trace_data.size(); - return DecodeInMemoryTrace(process, trace_intel_pt, trace_data); +DecodedThreadSP ThreadDecoder::Decode() { + if (!m_decoded_thread.hasValue()) + m_decoded_thread = DoDecode(); + return *m_decoded_thread; } -static Expected> -DecodeLiveThread(Thread &thread, TraceIntelPT &trace, size_t &raw_trace_size) { +// LiveThreadDecoder ==================== + +LiveThreadDecoder::LiveThreadDecoder(Thread &thread, TraceIntelPT &trace) + : m_thread_sp(thread.shared_from_this()), m_trace(trace) {} + +static Expected DecodeLiveThread(const ThreadSP &thread_sp, + TraceIntelPT &trace, + size_t &raw_trace_size) { Expected> buffer = - trace.GetLiveThreadBuffer(thread.GetID()); + trace.GetLiveThreadBuffer(thread_sp->GetID()); if (!buffer) return buffer.takeError(); raw_trace_size = buffer->size(); if (Expected cpu_info = trace.GetCPUInfo()) - return DecodeInMemoryTrace(*thread.GetProcess(), trace, - MutableArrayRef(*buffer)); + return DecodeInMemoryTrace(thread_sp, *thread_sp->GetProcess(), trace, + MutableArrayRef(*buffer), + raw_trace_size); else return cpu_info.takeError(); } -DecodedThreadSP ThreadDecoder::Decode() { - if (!m_decoded_thread.hasValue()) - m_decoded_thread = DoDecode(); - return *m_decoded_thread; +DecodedThreadSP LiveThreadDecoder::DoDecode() { + size_t raw_trace_size = 0; + return *(DecodeLiveThread(m_thread_sp, m_trace, raw_trace_size)); } +// PostMortemThreadDecoder ======================= + PostMortemThreadDecoder::PostMortemThreadDecoder( const lldb::ThreadPostMortemTraceSP &trace_thread, TraceIntelPT &trace) : m_trace_thread(trace_thread), m_trace(trace) {} -DecodedThreadSP PostMortemThreadDecoder::DoDecode() { - size_t raw_trace_size = 0; - if (Expected> instructions = - DecodeTraceFile(*m_trace_thread->GetProcess(), m_trace, - m_trace_thread->GetTraceFile(), raw_trace_size)) - return std::make_shared(m_trace_thread->shared_from_this(), - std::move(*instructions), - raw_trace_size); - else - return std::make_shared(m_trace_thread->shared_from_this(), - instructions.takeError()); -} +static Expected DecodeTraceFile(const ThreadSP &thread_sp, + Process &process, + TraceIntelPT &trace_intel_pt, + const FileSpec &trace_file, + size_t &raw_trace_size) { + ErrorOr> trace_or_error = + MemoryBuffer::getFile(trace_file.GetPath()); + if (std::error_code err = trace_or_error.getError()) + return errorCodeToError(err); -LiveThreadDecoder::LiveThreadDecoder(Thread &thread, TraceIntelPT &trace) - : m_thread_sp(thread.shared_from_this()), m_trace(trace) {} + MemoryBuffer &trace = **trace_or_error; + MutableArrayRef trace_data( + // The libipt library does not modify the trace buffer, hence the + // following cast is safe. + reinterpret_cast(const_cast(trace.getBufferStart())), + trace.getBufferSize()); + raw_trace_size = trace_data.size(); + return DecodeInMemoryTrace(thread_sp, process, trace_intel_pt, trace_data, + raw_trace_size); +} -DecodedThreadSP LiveThreadDecoder::DoDecode() { +DecodedThreadSP PostMortemThreadDecoder::DoDecode() { size_t raw_trace_size = 0; - if (Expected> instructions = - DecodeLiveThread(*m_thread_sp, m_trace, raw_trace_size)) - return std::make_shared( - m_thread_sp, std::move(*instructions), raw_trace_size); - else - return std::make_shared(m_thread_sp, - instructions.takeError()); + return *(DecodeTraceFile(m_trace_thread, *m_trace_thread->GetProcess(), + m_trace, m_trace_thread->GetTraceFile(), + raw_trace_size)); }