181ad6265SDimitry Andric //===-- LibiptDecoder.h --======---------------------------------*- C++ -*-===// 281ad6265SDimitry Andric // 381ad6265SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 481ad6265SDimitry Andric // See https://llvm.org/LICENSE.txt for license information. 581ad6265SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 681ad6265SDimitry Andric // 781ad6265SDimitry Andric //===----------------------------------------------------------------------===// 881ad6265SDimitry Andric 981ad6265SDimitry Andric #ifndef LLDB_SOURCE_PLUGINS_TRACE_LIBIPT_DECODER_H 1081ad6265SDimitry Andric #define LLDB_SOURCE_PLUGINS_TRACE_LIBIPT_DECODER_H 1181ad6265SDimitry Andric 1281ad6265SDimitry Andric #include "DecodedThread.h" 1381ad6265SDimitry Andric #include "PerfContextSwitchDecoder.h" 1481ad6265SDimitry Andric #include "forward-declarations.h" 1581ad6265SDimitry Andric #include "intel-pt.h" 16*bdd1243dSDimitry Andric #include <optional> 1781ad6265SDimitry Andric 1881ad6265SDimitry Andric namespace lldb_private { 1981ad6265SDimitry Andric namespace trace_intel_pt { 2081ad6265SDimitry Andric 21*bdd1243dSDimitry Andric /// This struct represents a contiguous section of a trace that starts at a PSB 22*bdd1243dSDimitry Andric /// and ends right before the next PSB or the end of the trace. 23*bdd1243dSDimitry Andric struct PSBBlock { 24*bdd1243dSDimitry Andric /// The memory offset of a PSB packet that is a synchronization point for the 25*bdd1243dSDimitry Andric /// decoder. A decoder normally looks first for a PSB packet and then it 26*bdd1243dSDimitry Andric /// starts decoding. 2781ad6265SDimitry Andric uint64_t psb_offset; 2881ad6265SDimitry Andric /// The timestamp associated with the PSB packet above. 29*bdd1243dSDimitry Andric std::optional<uint64_t> tsc; 30*bdd1243dSDimitry Andric /// Size in bytes of this block 31*bdd1243dSDimitry Andric uint64_t size; 32*bdd1243dSDimitry Andric /// The first ip for this PSB block. 33*bdd1243dSDimitry Andric /// This is \a std::nullopt if tracing was disabled when the PSB block was 34*bdd1243dSDimitry Andric /// emitted. This means that eventually there's be an enablement event that 35*bdd1243dSDimitry Andric /// will come with an ip. 36*bdd1243dSDimitry Andric std::optional<lldb::addr_t> starting_ip; 3781ad6265SDimitry Andric }; 3881ad6265SDimitry Andric 3981ad6265SDimitry Andric /// This struct represents a continuous execution of a thread in a cpu, 4081ad6265SDimitry Andric /// delimited by a context switch in and out, and a list of Intel PT subtraces 4181ad6265SDimitry Andric /// that belong to this execution. 4281ad6265SDimitry Andric struct IntelPTThreadContinousExecution { 4381ad6265SDimitry Andric ThreadContinuousExecution thread_execution; 44*bdd1243dSDimitry Andric std::vector<PSBBlock> psb_blocks; 4581ad6265SDimitry Andric IntelPTThreadContinousExecutionIntelPTThreadContinousExecution4681ad6265SDimitry Andric IntelPTThreadContinousExecution( 4781ad6265SDimitry Andric const ThreadContinuousExecution &thread_execution) 4881ad6265SDimitry Andric : thread_execution(thread_execution) {} 4981ad6265SDimitry Andric 5081ad6265SDimitry Andric /// Comparator by time 5181ad6265SDimitry Andric bool operator<(const IntelPTThreadContinousExecution &o) const; 5281ad6265SDimitry Andric }; 5381ad6265SDimitry Andric 5481ad6265SDimitry Andric /// Decode a raw Intel PT trace for a single thread given in \p buffer and 5581ad6265SDimitry Andric /// append the decoded instructions and errors in \p decoded_thread. It uses the 5681ad6265SDimitry Andric /// low level libipt library underneath. 5781ad6265SDimitry Andric /// 5881ad6265SDimitry Andric /// \return 5981ad6265SDimitry Andric /// An \a llvm::Error if the decoder couldn't be properly set up. 6081ad6265SDimitry Andric llvm::Error DecodeSingleTraceForThread(DecodedThread &decoded_thread, 6181ad6265SDimitry Andric TraceIntelPT &trace_intel_pt, 6281ad6265SDimitry Andric llvm::ArrayRef<uint8_t> buffer); 6381ad6265SDimitry Andric 6481ad6265SDimitry Andric /// Decode a raw Intel PT trace for a single thread that was collected in a per 6581ad6265SDimitry Andric /// cpu core basis. 6681ad6265SDimitry Andric /// 6781ad6265SDimitry Andric /// \param[out] decoded_thread 6881ad6265SDimitry Andric /// All decoded instructions, errors and events will be appended to this 6981ad6265SDimitry Andric /// object. 7081ad6265SDimitry Andric /// 7181ad6265SDimitry Andric /// \param[in] trace_intel_pt 7281ad6265SDimitry Andric /// The main Trace object that contains all the information related to the 7381ad6265SDimitry Andric /// trace session. 7481ad6265SDimitry Andric /// 7581ad6265SDimitry Andric /// \param[in] buffers 7681ad6265SDimitry Andric /// A map from cpu core id to raw intel pt buffers. 7781ad6265SDimitry Andric /// 7881ad6265SDimitry Andric /// \param[in] executions 7981ad6265SDimitry Andric /// A list of chunks of timed executions of the same given thread. It is used 8081ad6265SDimitry Andric /// to identify if some executions have missing intel pt data and also to 8181ad6265SDimitry Andric /// determine in which core a certain part of the execution ocurred. 8281ad6265SDimitry Andric /// 8381ad6265SDimitry Andric /// \return 8481ad6265SDimitry Andric /// An \a llvm::Error if the decoder couldn't be properly set up, i.e. no 8581ad6265SDimitry Andric /// instructions were attempted to be decoded. 8681ad6265SDimitry Andric llvm::Error DecodeSystemWideTraceForThread( 8781ad6265SDimitry Andric DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, 8881ad6265SDimitry Andric const llvm::DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers, 8981ad6265SDimitry Andric const std::vector<IntelPTThreadContinousExecution> &executions); 9081ad6265SDimitry Andric 91*bdd1243dSDimitry Andric /// Given an intel pt trace, split it in chunks delimited by PSB packets. Each 92*bdd1243dSDimitry Andric /// of these chunks is guaranteed to have been executed continuously. 9381ad6265SDimitry Andric /// 9481ad6265SDimitry Andric /// \param[in] trace_intel_pt 95*bdd1243dSDimitry Andric /// The main Trace object that contains all the information related to the 96*bdd1243dSDimitry Andric /// trace session. 9781ad6265SDimitry Andric /// 9881ad6265SDimitry Andric /// \param[in] buffer 99*bdd1243dSDimitry Andric /// The intel pt buffer that belongs to a single thread or to a single cpu 100*bdd1243dSDimitry Andric /// core. 101*bdd1243dSDimitry Andric /// 102*bdd1243dSDimitry Andric /// \param[in] expect_tscs 103*bdd1243dSDimitry Andric /// If \b true, an error is return if a packet without TSC is found. 10481ad6265SDimitry Andric /// 10581ad6265SDimitry Andric /// \return 106*bdd1243dSDimitry Andric /// A list of continuous executions sorted by time, or an \a llvm::Error in 107*bdd1243dSDimitry Andric /// case of failures. 108*bdd1243dSDimitry Andric llvm::Expected<std::vector<PSBBlock>> 109*bdd1243dSDimitry Andric SplitTraceIntoPSBBlock(TraceIntelPT &trace_intel_pt, 110*bdd1243dSDimitry Andric llvm::ArrayRef<uint8_t> buffer, bool expect_tscs); 11181ad6265SDimitry Andric 112972a253aSDimitry Andric /// Find the lowest TSC in the given trace. 113972a253aSDimitry Andric /// 114972a253aSDimitry Andric /// \return 115*bdd1243dSDimitry Andric /// The lowest TSC value in this trace if available, \a std::nullopt if the 116972a253aSDimitry Andric /// trace is empty or the trace contains no timing information, or an \a 117972a253aSDimitry Andric /// llvm::Error if it was not possible to set up the decoder. 118*bdd1243dSDimitry Andric llvm::Expected<std::optional<uint64_t>> 119972a253aSDimitry Andric FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt, 120972a253aSDimitry Andric llvm::ArrayRef<uint8_t> buffer); 121972a253aSDimitry Andric 12281ad6265SDimitry Andric } // namespace trace_intel_pt 12381ad6265SDimitry Andric } // namespace lldb_private 12481ad6265SDimitry Andric 12581ad6265SDimitry Andric #endif // LLDB_SOURCE_PLUGINS_TRACE_LIBIPT_DECODER_H 126