181ad6265SDimitry Andric //===-- LibiptDecoder.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 "LibiptDecoder.h" 981ad6265SDimitry Andric #include "TraceIntelPT.h" 1081ad6265SDimitry Andric #include "lldb/Target/Process.h" 11*bdd1243dSDimitry Andric #include <optional> 1281ad6265SDimitry Andric 1381ad6265SDimitry Andric using namespace lldb; 1481ad6265SDimitry Andric using namespace lldb_private; 1581ad6265SDimitry Andric using namespace lldb_private::trace_intel_pt; 1681ad6265SDimitry Andric using namespace llvm; 1781ad6265SDimitry Andric 18*bdd1243dSDimitry Andric bool IsLibiptError(int status) { return status < 0; } 1981ad6265SDimitry Andric 20*bdd1243dSDimitry Andric bool IsEndOfStream(int status) { 21*bdd1243dSDimitry Andric assert(status >= 0 && "We can't check if we reached the end of the stream if " 22*bdd1243dSDimitry Andric "we got a failed status"); 23*bdd1243dSDimitry Andric return status & pts_eos; 2481ad6265SDimitry Andric } 2581ad6265SDimitry Andric 26*bdd1243dSDimitry Andric bool HasEvents(int status) { 27*bdd1243dSDimitry Andric assert(status >= 0 && "We can't check for events if we got a failed status"); 28*bdd1243dSDimitry Andric return status & pts_event_pending; 2981ad6265SDimitry Andric } 3081ad6265SDimitry Andric 31*bdd1243dSDimitry Andric // RAII deleter for libipt's decoders 32*bdd1243dSDimitry Andric auto InsnDecoderDeleter = [](pt_insn_decoder *decoder) { 33*bdd1243dSDimitry Andric pt_insn_free_decoder(decoder); 3481ad6265SDimitry Andric }; 3581ad6265SDimitry Andric 36*bdd1243dSDimitry Andric auto QueryDecoderDeleter = [](pt_query_decoder *decoder) { 37*bdd1243dSDimitry Andric pt_qry_free_decoder(decoder); 38*bdd1243dSDimitry Andric }; 39*bdd1243dSDimitry Andric 40*bdd1243dSDimitry Andric using PtInsnDecoderUP = 41*bdd1243dSDimitry Andric std::unique_ptr<pt_insn_decoder, decltype(InsnDecoderDeleter)>; 42*bdd1243dSDimitry Andric 43*bdd1243dSDimitry Andric using PtQueryDecoderUP = 44*bdd1243dSDimitry Andric std::unique_ptr<pt_query_decoder, decltype(QueryDecoderDeleter)>; 45*bdd1243dSDimitry Andric 46*bdd1243dSDimitry Andric /// Create a basic configuration object limited to a given buffer that can be 47*bdd1243dSDimitry Andric /// used for many different decoders. 48*bdd1243dSDimitry Andric static Expected<pt_config> CreateBasicLibiptConfig(TraceIntelPT &trace_intel_pt, 49*bdd1243dSDimitry Andric ArrayRef<uint8_t> buffer) { 50*bdd1243dSDimitry Andric Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo(); 51*bdd1243dSDimitry Andric if (!cpu_info) 52*bdd1243dSDimitry Andric return cpu_info.takeError(); 53*bdd1243dSDimitry Andric 54*bdd1243dSDimitry Andric pt_config config; 55*bdd1243dSDimitry Andric pt_config_init(&config); 56*bdd1243dSDimitry Andric config.cpu = *cpu_info; 57*bdd1243dSDimitry Andric 58*bdd1243dSDimitry Andric int status = pt_cpu_errata(&config.errata, &config.cpu); 59*bdd1243dSDimitry Andric if (IsLibiptError(status)) 60*bdd1243dSDimitry Andric return make_error<IntelPTError>(status); 61*bdd1243dSDimitry Andric 62*bdd1243dSDimitry Andric // The libipt library does not modify the trace buffer, hence the 63*bdd1243dSDimitry Andric // following casts are safe. 64*bdd1243dSDimitry Andric config.begin = const_cast<uint8_t *>(buffer.data()); 65*bdd1243dSDimitry Andric config.end = const_cast<uint8_t *>(buffer.data() + buffer.size()); 66*bdd1243dSDimitry Andric return config; 67*bdd1243dSDimitry Andric } 68*bdd1243dSDimitry Andric 6981ad6265SDimitry Andric /// Callback used by libipt for reading the process memory. 7081ad6265SDimitry Andric /// 7181ad6265SDimitry Andric /// More information can be found in 7281ad6265SDimitry Andric /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md 7381ad6265SDimitry Andric static int ReadProcessMemory(uint8_t *buffer, size_t size, 7481ad6265SDimitry Andric const pt_asid * /* unused */, uint64_t pc, 7581ad6265SDimitry Andric void *context) { 7681ad6265SDimitry Andric Process *process = static_cast<Process *>(context); 7781ad6265SDimitry Andric 7881ad6265SDimitry Andric Status error; 7981ad6265SDimitry Andric int bytes_read = process->ReadMemory(pc, buffer, size, error); 8081ad6265SDimitry Andric if (error.Fail()) 8181ad6265SDimitry Andric return -pte_nomap; 8281ad6265SDimitry Andric return bytes_read; 8381ad6265SDimitry Andric } 8481ad6265SDimitry Andric 85*bdd1243dSDimitry Andric /// Set up the memory image callback for the given decoder. 86*bdd1243dSDimitry Andric static Error SetupMemoryImage(pt_insn_decoder *decoder, Process &process) { 87*bdd1243dSDimitry Andric pt_image *image = pt_insn_get_image(decoder); 8881ad6265SDimitry Andric 89*bdd1243dSDimitry Andric int status = pt_image_set_callback(image, ReadProcessMemory, &process); 90*bdd1243dSDimitry Andric if (IsLibiptError(status)) 9181ad6265SDimitry Andric return make_error<IntelPTError>(status); 9281ad6265SDimitry Andric return Error::success(); 9381ad6265SDimitry Andric } 9481ad6265SDimitry Andric 95*bdd1243dSDimitry Andric /// Create an instruction decoder for the given buffer and the given process. 96*bdd1243dSDimitry Andric static Expected<PtInsnDecoderUP> 97*bdd1243dSDimitry Andric CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer, 98*bdd1243dSDimitry Andric Process &process) { 99*bdd1243dSDimitry Andric Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer); 100*bdd1243dSDimitry Andric if (!config) 101*bdd1243dSDimitry Andric return config.takeError(); 102*bdd1243dSDimitry Andric 103*bdd1243dSDimitry Andric pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&*config); 104*bdd1243dSDimitry Andric if (!decoder_ptr) 105*bdd1243dSDimitry Andric return make_error<IntelPTError>(-pte_nomem); 106*bdd1243dSDimitry Andric 107*bdd1243dSDimitry Andric PtInsnDecoderUP decoder_up(decoder_ptr, InsnDecoderDeleter); 108*bdd1243dSDimitry Andric 109*bdd1243dSDimitry Andric if (Error err = SetupMemoryImage(decoder_ptr, process)) 110*bdd1243dSDimitry Andric return std::move(err); 111*bdd1243dSDimitry Andric 112*bdd1243dSDimitry Andric return decoder_up; 113*bdd1243dSDimitry Andric } 114*bdd1243dSDimitry Andric 115*bdd1243dSDimitry Andric /// Create a query decoder for the given buffer. The query decoder is the 116*bdd1243dSDimitry Andric /// highest level decoder that operates directly on packets and doesn't perform 117*bdd1243dSDimitry Andric /// actual instruction decoding. That's why it can be useful for inspecting a 118*bdd1243dSDimitry Andric /// raw trace without pinning it to a particular process. 119*bdd1243dSDimitry Andric static Expected<PtQueryDecoderUP> 120*bdd1243dSDimitry Andric CreateQueryDecoder(TraceIntelPT &trace_intel_pt, ArrayRef<uint8_t> buffer) { 121*bdd1243dSDimitry Andric Expected<pt_config> config = CreateBasicLibiptConfig(trace_intel_pt, buffer); 122*bdd1243dSDimitry Andric if (!config) 123*bdd1243dSDimitry Andric return config.takeError(); 124*bdd1243dSDimitry Andric 125*bdd1243dSDimitry Andric pt_query_decoder *decoder_ptr = pt_qry_alloc_decoder(&*config); 126*bdd1243dSDimitry Andric if (!decoder_ptr) 127*bdd1243dSDimitry Andric return make_error<IntelPTError>(-pte_nomem); 128*bdd1243dSDimitry Andric 129*bdd1243dSDimitry Andric return PtQueryDecoderUP(decoder_ptr, QueryDecoderDeleter); 130*bdd1243dSDimitry Andric } 131*bdd1243dSDimitry Andric 132*bdd1243dSDimitry Andric /// Class used to identify anomalies in traces, which should often indicate a 133*bdd1243dSDimitry Andric /// fatal error in the trace. 134*bdd1243dSDimitry Andric class PSBBlockAnomalyDetector { 135*bdd1243dSDimitry Andric public: 136*bdd1243dSDimitry Andric PSBBlockAnomalyDetector(pt_insn_decoder &decoder, 137*bdd1243dSDimitry Andric TraceIntelPT &trace_intel_pt, 138*bdd1243dSDimitry Andric DecodedThread &decoded_thread) 139*bdd1243dSDimitry Andric : m_decoder(decoder), m_decoded_thread(decoded_thread) { 140*bdd1243dSDimitry Andric m_infinite_decoding_loop_threshold = 141*bdd1243dSDimitry Andric trace_intel_pt.GetGlobalProperties() 142*bdd1243dSDimitry Andric .GetInfiniteDecodingLoopVerificationThreshold(); 143*bdd1243dSDimitry Andric m_extremely_large_decoding_threshold = 144*bdd1243dSDimitry Andric trace_intel_pt.GetGlobalProperties() 145*bdd1243dSDimitry Andric .GetExtremelyLargeDecodingThreshold(); 146*bdd1243dSDimitry Andric m_next_infinite_decoding_loop_threshold = 147*bdd1243dSDimitry Andric m_infinite_decoding_loop_threshold; 148*bdd1243dSDimitry Andric } 149*bdd1243dSDimitry Andric 150*bdd1243dSDimitry Andric /// \return 151*bdd1243dSDimitry Andric /// An \a llvm::Error if an anomaly that includes the last instruction item 152*bdd1243dSDimitry Andric /// in the trace, or \a llvm::Error::success otherwise. 153*bdd1243dSDimitry Andric Error DetectAnomaly() { 154*bdd1243dSDimitry Andric RefreshPacketOffset(); 155*bdd1243dSDimitry Andric uint64_t insn_added_since_last_packet_offset = 156*bdd1243dSDimitry Andric m_decoded_thread.GetTotalInstructionCount() - 157*bdd1243dSDimitry Andric m_insn_count_at_last_packet_offset; 158*bdd1243dSDimitry Andric 159*bdd1243dSDimitry Andric // We want to check if we might have fallen in an infinite loop. As this 160*bdd1243dSDimitry Andric // check is not a no-op, we want to do it when we have a strong suggestion 161*bdd1243dSDimitry Andric // that things went wrong. First, we check how many instructions we have 162*bdd1243dSDimitry Andric // decoded since we processed an Intel PT packet for the last time. This 163*bdd1243dSDimitry Andric // number should be low, because at some point we should see branches, jumps 164*bdd1243dSDimitry Andric // or interrupts that require a new packet to be processed. Once we reach 165*bdd1243dSDimitry Andric // certain threshold we start analyzing the trace. 166*bdd1243dSDimitry Andric // 167*bdd1243dSDimitry Andric // We use the number of decoded instructions since the last Intel PT packet 168*bdd1243dSDimitry Andric // as a proxy because, in fact, we don't expect a single packet to give, 169*bdd1243dSDimitry Andric // say, 100k instructions. That would mean that there are 100k sequential 170*bdd1243dSDimitry Andric // instructions without any single branch, which is highly unlikely, or that 171*bdd1243dSDimitry Andric // we found an infinite loop using direct jumps, e.g. 172*bdd1243dSDimitry Andric // 173*bdd1243dSDimitry Andric // 0x0A: nop or pause 174*bdd1243dSDimitry Andric // 0x0C: jump to 0x0A 175*bdd1243dSDimitry Andric // 176*bdd1243dSDimitry Andric // which is indeed code that is found in the kernel. I presume we reach 177*bdd1243dSDimitry Andric // this kind of code in the decoder because we don't handle self-modified 178*bdd1243dSDimitry Andric // code in post-mortem kernel traces. 179*bdd1243dSDimitry Andric // 180*bdd1243dSDimitry Andric // We are right now only signaling the anomaly as a trace error, but it 181*bdd1243dSDimitry Andric // would be more conservative to also discard all the trace items found in 182*bdd1243dSDimitry Andric // this PSB. I prefer not to do that for the time being to give more 183*bdd1243dSDimitry Andric // exposure to this kind of anomalies and help debugging. Discarding the 184*bdd1243dSDimitry Andric // trace items would just make investigation harded. 185*bdd1243dSDimitry Andric // 186*bdd1243dSDimitry Andric // Finally, if the user wants to see if a specific thread has an anomaly, 187*bdd1243dSDimitry Andric // it's enough to run the `thread trace dump info` command and look for the 188*bdd1243dSDimitry Andric // count of this kind of errors. 189*bdd1243dSDimitry Andric 190*bdd1243dSDimitry Andric if (insn_added_since_last_packet_offset >= 191*bdd1243dSDimitry Andric m_extremely_large_decoding_threshold) { 192*bdd1243dSDimitry Andric // In this case, we have decoded a massive amount of sequential 193*bdd1243dSDimitry Andric // instructions that don't loop. Honestly I wonder if this will ever 194*bdd1243dSDimitry Andric // happen, but better safe than sorry. 195*bdd1243dSDimitry Andric return createStringError( 196*bdd1243dSDimitry Andric inconvertibleErrorCode(), 197*bdd1243dSDimitry Andric "anomalous trace: possible infinite trace detected"); 198*bdd1243dSDimitry Andric } 199*bdd1243dSDimitry Andric if (insn_added_since_last_packet_offset == 200*bdd1243dSDimitry Andric m_next_infinite_decoding_loop_threshold) { 201*bdd1243dSDimitry Andric if (std::optional<uint64_t> loop_size = TryIdentifyInfiniteLoop()) { 202*bdd1243dSDimitry Andric return createStringError( 203*bdd1243dSDimitry Andric inconvertibleErrorCode(), 204*bdd1243dSDimitry Andric "anomalous trace: possible infinite loop detected of size %" PRIu64, 205*bdd1243dSDimitry Andric *loop_size); 206*bdd1243dSDimitry Andric } 207*bdd1243dSDimitry Andric m_next_infinite_decoding_loop_threshold *= 2; 208*bdd1243dSDimitry Andric } 209*bdd1243dSDimitry Andric return Error::success(); 210*bdd1243dSDimitry Andric } 211*bdd1243dSDimitry Andric 212*bdd1243dSDimitry Andric private: 213*bdd1243dSDimitry Andric std::optional<uint64_t> TryIdentifyInfiniteLoop() { 214*bdd1243dSDimitry Andric // The infinite decoding loops we'll encounter are due to sequential 215*bdd1243dSDimitry Andric // instructions that repeat themselves due to direct jumps, therefore in a 216*bdd1243dSDimitry Andric // cycle each individual address will only appear once. We use this 217*bdd1243dSDimitry Andric // information to detect cycles by finding the last 2 ocurrences of the last 218*bdd1243dSDimitry Andric // instruction added to the trace. Then we traverse the trace making sure 219*bdd1243dSDimitry Andric // that these two instructions where the ends of a repeating loop. 220*bdd1243dSDimitry Andric 221*bdd1243dSDimitry Andric // This is a utility that returns the most recent instruction index given a 222*bdd1243dSDimitry Andric // position in the trace. If the given position is an instruction, that 223*bdd1243dSDimitry Andric // position is returned. It skips non-instruction items. 224*bdd1243dSDimitry Andric auto most_recent_insn_index = 225*bdd1243dSDimitry Andric [&](uint64_t item_index) -> std::optional<uint64_t> { 226*bdd1243dSDimitry Andric while (true) { 227*bdd1243dSDimitry Andric if (m_decoded_thread.GetItemKindByIndex(item_index) == 228*bdd1243dSDimitry Andric lldb::eTraceItemKindInstruction) { 229*bdd1243dSDimitry Andric return item_index; 230*bdd1243dSDimitry Andric } 231*bdd1243dSDimitry Andric if (item_index == 0) 232*bdd1243dSDimitry Andric return std::nullopt; 233*bdd1243dSDimitry Andric item_index--; 234*bdd1243dSDimitry Andric } 235*bdd1243dSDimitry Andric return std::nullopt; 236*bdd1243dSDimitry Andric }; 237*bdd1243dSDimitry Andric // Similar to most_recent_insn_index but skips the starting position. 238*bdd1243dSDimitry Andric auto prev_insn_index = [&](uint64_t item_index) -> std::optional<uint64_t> { 239*bdd1243dSDimitry Andric if (item_index == 0) 240*bdd1243dSDimitry Andric return std::nullopt; 241*bdd1243dSDimitry Andric return most_recent_insn_index(item_index - 1); 242*bdd1243dSDimitry Andric }; 243*bdd1243dSDimitry Andric 244*bdd1243dSDimitry Andric // We first find the most recent instruction. 245*bdd1243dSDimitry Andric std::optional<uint64_t> last_insn_index_opt = 246*bdd1243dSDimitry Andric *prev_insn_index(m_decoded_thread.GetItemsCount()); 247*bdd1243dSDimitry Andric if (!last_insn_index_opt) 248*bdd1243dSDimitry Andric return std::nullopt; 249*bdd1243dSDimitry Andric uint64_t last_insn_index = *last_insn_index_opt; 250*bdd1243dSDimitry Andric 251*bdd1243dSDimitry Andric // We then find the most recent previous occurrence of that last 252*bdd1243dSDimitry Andric // instruction. 253*bdd1243dSDimitry Andric std::optional<uint64_t> last_insn_copy_index = 254*bdd1243dSDimitry Andric prev_insn_index(last_insn_index); 255*bdd1243dSDimitry Andric uint64_t loop_size = 1; 256*bdd1243dSDimitry Andric while (last_insn_copy_index && 257*bdd1243dSDimitry Andric m_decoded_thread.GetInstructionLoadAddress(*last_insn_copy_index) != 258*bdd1243dSDimitry Andric m_decoded_thread.GetInstructionLoadAddress(last_insn_index)) { 259*bdd1243dSDimitry Andric last_insn_copy_index = prev_insn_index(*last_insn_copy_index); 260*bdd1243dSDimitry Andric loop_size++; 261*bdd1243dSDimitry Andric } 262*bdd1243dSDimitry Andric if (!last_insn_copy_index) 263*bdd1243dSDimitry Andric return std::nullopt; 264*bdd1243dSDimitry Andric 265*bdd1243dSDimitry Andric // Now we check if the segment between these last positions of the last 266*bdd1243dSDimitry Andric // instruction address is in fact a repeating loop. 267*bdd1243dSDimitry Andric uint64_t loop_elements_visited = 1; 268*bdd1243dSDimitry Andric uint64_t insn_index_a = last_insn_index, 269*bdd1243dSDimitry Andric insn_index_b = *last_insn_copy_index; 270*bdd1243dSDimitry Andric while (loop_elements_visited < loop_size) { 271*bdd1243dSDimitry Andric if (std::optional<uint64_t> prev = prev_insn_index(insn_index_a)) 272*bdd1243dSDimitry Andric insn_index_a = *prev; 273*bdd1243dSDimitry Andric else 274*bdd1243dSDimitry Andric return std::nullopt; 275*bdd1243dSDimitry Andric if (std::optional<uint64_t> prev = prev_insn_index(insn_index_b)) 276*bdd1243dSDimitry Andric insn_index_b = *prev; 277*bdd1243dSDimitry Andric else 278*bdd1243dSDimitry Andric return std::nullopt; 279*bdd1243dSDimitry Andric if (m_decoded_thread.GetInstructionLoadAddress(insn_index_a) != 280*bdd1243dSDimitry Andric m_decoded_thread.GetInstructionLoadAddress(insn_index_b)) 281*bdd1243dSDimitry Andric return std::nullopt; 282*bdd1243dSDimitry Andric loop_elements_visited++; 283*bdd1243dSDimitry Andric } 284*bdd1243dSDimitry Andric return loop_size; 285*bdd1243dSDimitry Andric } 286*bdd1243dSDimitry Andric 287*bdd1243dSDimitry Andric // Refresh the internal counters if a new packet offset has been visited 288*bdd1243dSDimitry Andric void RefreshPacketOffset() { 289*bdd1243dSDimitry Andric lldb::addr_t new_packet_offset; 290*bdd1243dSDimitry Andric if (!IsLibiptError(pt_insn_get_offset(&m_decoder, &new_packet_offset)) && 291*bdd1243dSDimitry Andric new_packet_offset != m_last_packet_offset) { 292*bdd1243dSDimitry Andric m_last_packet_offset = new_packet_offset; 293*bdd1243dSDimitry Andric m_next_infinite_decoding_loop_threshold = 294*bdd1243dSDimitry Andric m_infinite_decoding_loop_threshold; 295*bdd1243dSDimitry Andric m_insn_count_at_last_packet_offset = 296*bdd1243dSDimitry Andric m_decoded_thread.GetTotalInstructionCount(); 297*bdd1243dSDimitry Andric } 298*bdd1243dSDimitry Andric } 299*bdd1243dSDimitry Andric 300*bdd1243dSDimitry Andric pt_insn_decoder &m_decoder; 301*bdd1243dSDimitry Andric DecodedThread &m_decoded_thread; 302*bdd1243dSDimitry Andric lldb::addr_t m_last_packet_offset = LLDB_INVALID_ADDRESS; 303*bdd1243dSDimitry Andric uint64_t m_insn_count_at_last_packet_offset = 0; 304*bdd1243dSDimitry Andric uint64_t m_infinite_decoding_loop_threshold; 305*bdd1243dSDimitry Andric uint64_t m_next_infinite_decoding_loop_threshold; 306*bdd1243dSDimitry Andric uint64_t m_extremely_large_decoding_threshold; 307*bdd1243dSDimitry Andric }; 308*bdd1243dSDimitry Andric 309*bdd1243dSDimitry Andric /// Class that decodes a raw buffer for a single PSB block using the low level 310*bdd1243dSDimitry Andric /// libipt library. It assumes that kernel and user mode instructions are not 311*bdd1243dSDimitry Andric /// mixed in the same PSB block. 312*bdd1243dSDimitry Andric /// 313*bdd1243dSDimitry Andric /// Throughout this code, the status of the decoder will be used to identify 314*bdd1243dSDimitry Andric /// events needed to be processed or errors in the decoder. The values can be 315*bdd1243dSDimitry Andric /// - negative: actual errors 316*bdd1243dSDimitry Andric /// - positive or zero: not an error, but a list of bits signaling the status 317*bdd1243dSDimitry Andric /// of the decoder, e.g. whether there are events that need to be decoded or 318*bdd1243dSDimitry Andric /// not. 319*bdd1243dSDimitry Andric class PSBBlockDecoder { 320*bdd1243dSDimitry Andric public: 321*bdd1243dSDimitry Andric /// \param[in] decoder 322*bdd1243dSDimitry Andric /// A decoder configured to start and end within the boundaries of the 323*bdd1243dSDimitry Andric /// given \p psb_block. 324*bdd1243dSDimitry Andric /// 325*bdd1243dSDimitry Andric /// \param[in] psb_block 326*bdd1243dSDimitry Andric /// The PSB block to decode. 327*bdd1243dSDimitry Andric /// 328*bdd1243dSDimitry Andric /// \param[in] next_block_ip 329*bdd1243dSDimitry Andric /// The starting ip at the next PSB block of the same thread if available. 330*bdd1243dSDimitry Andric /// 331*bdd1243dSDimitry Andric /// \param[in] decoded_thread 332*bdd1243dSDimitry Andric /// A \a DecodedThread object where the decoded instructions will be 333*bdd1243dSDimitry Andric /// appended to. It might have already some instructions. 334*bdd1243dSDimitry Andric /// 335*bdd1243dSDimitry Andric /// \param[in] tsc_upper_bound 336*bdd1243dSDimitry Andric /// Maximum allowed value of TSCs decoded from this PSB block. 337*bdd1243dSDimitry Andric /// Any of this PSB's data occurring after this TSC will be excluded. 338*bdd1243dSDimitry Andric PSBBlockDecoder(PtInsnDecoderUP &&decoder_up, const PSBBlock &psb_block, 339*bdd1243dSDimitry Andric std::optional<lldb::addr_t> next_block_ip, 34081ad6265SDimitry Andric DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, 341*bdd1243dSDimitry Andric std::optional<DecodedThread::TSC> tsc_upper_bound) 342*bdd1243dSDimitry Andric : m_decoder_up(std::move(decoder_up)), m_psb_block(psb_block), 343*bdd1243dSDimitry Andric m_next_block_ip(next_block_ip), m_decoded_thread(decoded_thread), 344*bdd1243dSDimitry Andric m_anomaly_detector(*m_decoder_up, trace_intel_pt, decoded_thread), 345*bdd1243dSDimitry Andric m_tsc_upper_bound(tsc_upper_bound) {} 346*bdd1243dSDimitry Andric 347*bdd1243dSDimitry Andric /// \param[in] trace_intel_pt 348*bdd1243dSDimitry Andric /// The main Trace object that own the PSB block. 349*bdd1243dSDimitry Andric /// 350*bdd1243dSDimitry Andric /// \param[in] decoder 351*bdd1243dSDimitry Andric /// A decoder configured to start and end within the boundaries of the 352*bdd1243dSDimitry Andric /// given \p psb_block. 353*bdd1243dSDimitry Andric /// 354*bdd1243dSDimitry Andric /// \param[in] psb_block 355*bdd1243dSDimitry Andric /// The PSB block to decode. 356*bdd1243dSDimitry Andric /// 357*bdd1243dSDimitry Andric /// \param[in] buffer 358*bdd1243dSDimitry Andric /// The raw intel pt trace for this block. 359*bdd1243dSDimitry Andric /// 360*bdd1243dSDimitry Andric /// \param[in] process 361*bdd1243dSDimitry Andric /// The process to decode. It provides the memory image to use for 362*bdd1243dSDimitry Andric /// decoding. 363*bdd1243dSDimitry Andric /// 364*bdd1243dSDimitry Andric /// \param[in] next_block_ip 365*bdd1243dSDimitry Andric /// The starting ip at the next PSB block of the same thread if available. 366*bdd1243dSDimitry Andric /// 367*bdd1243dSDimitry Andric /// \param[in] decoded_thread 368*bdd1243dSDimitry Andric /// A \a DecodedThread object where the decoded instructions will be 369*bdd1243dSDimitry Andric /// appended to. It might have already some instructions. 370*bdd1243dSDimitry Andric static Expected<PSBBlockDecoder> 371*bdd1243dSDimitry Andric Create(TraceIntelPT &trace_intel_pt, const PSBBlock &psb_block, 372*bdd1243dSDimitry Andric ArrayRef<uint8_t> buffer, Process &process, 373*bdd1243dSDimitry Andric std::optional<lldb::addr_t> next_block_ip, 374*bdd1243dSDimitry Andric DecodedThread &decoded_thread, 375*bdd1243dSDimitry Andric std::optional<DecodedThread::TSC> tsc_upper_bound) { 37681ad6265SDimitry Andric Expected<PtInsnDecoderUP> decoder_up = 377*bdd1243dSDimitry Andric CreateInstructionDecoder(trace_intel_pt, buffer, process); 37881ad6265SDimitry Andric if (!decoder_up) 37981ad6265SDimitry Andric return decoder_up.takeError(); 38081ad6265SDimitry Andric 381*bdd1243dSDimitry Andric return PSBBlockDecoder(std::move(*decoder_up), psb_block, next_block_ip, 382*bdd1243dSDimitry Andric decoded_thread, trace_intel_pt, tsc_upper_bound); 383*bdd1243dSDimitry Andric } 38481ad6265SDimitry Andric 385*bdd1243dSDimitry Andric void DecodePSBBlock() { 386*bdd1243dSDimitry Andric int status = pt_insn_sync_forward(m_decoder_up.get()); 387*bdd1243dSDimitry Andric assert(status >= 0 && 388*bdd1243dSDimitry Andric "Synchronization shouldn't fail because this PSB was previously " 389*bdd1243dSDimitry Andric "decoded correctly."); 390*bdd1243dSDimitry Andric 391*bdd1243dSDimitry Andric // We emit a TSC before a sync event to more easily associate a timestamp to 392*bdd1243dSDimitry Andric // the sync event. If present, the current block's TSC would be the first 393*bdd1243dSDimitry Andric // TSC we'll see when processing events. 394*bdd1243dSDimitry Andric if (m_psb_block.tsc) 395*bdd1243dSDimitry Andric m_decoded_thread.NotifyTsc(*m_psb_block.tsc); 396*bdd1243dSDimitry Andric 397*bdd1243dSDimitry Andric m_decoded_thread.NotifySyncPoint(m_psb_block.psb_offset); 398*bdd1243dSDimitry Andric 399*bdd1243dSDimitry Andric DecodeInstructionsAndEvents(status); 400*bdd1243dSDimitry Andric } 401*bdd1243dSDimitry Andric 402*bdd1243dSDimitry Andric private: 403*bdd1243dSDimitry Andric /// Append an instruction and return \b false if and only if a serious anomaly 404*bdd1243dSDimitry Andric /// has been detected. 405*bdd1243dSDimitry Andric bool AppendInstructionAndDetectAnomalies(const pt_insn &insn) { 406*bdd1243dSDimitry Andric m_decoded_thread.AppendInstruction(insn); 407*bdd1243dSDimitry Andric 408*bdd1243dSDimitry Andric if (Error err = m_anomaly_detector.DetectAnomaly()) { 409*bdd1243dSDimitry Andric m_decoded_thread.AppendCustomError(toString(std::move(err)), 410*bdd1243dSDimitry Andric /*fatal=*/true); 411*bdd1243dSDimitry Andric return false; 412*bdd1243dSDimitry Andric } 413*bdd1243dSDimitry Andric return true; 414*bdd1243dSDimitry Andric } 415*bdd1243dSDimitry Andric /// Decode all the instructions and events of the given PSB block. The 416*bdd1243dSDimitry Andric /// decoding loop might stop abruptly if an infinite decoding loop is 417*bdd1243dSDimitry Andric /// detected. 418*bdd1243dSDimitry Andric void DecodeInstructionsAndEvents(int status) { 419*bdd1243dSDimitry Andric pt_insn insn; 420*bdd1243dSDimitry Andric 421*bdd1243dSDimitry Andric while (true) { 422*bdd1243dSDimitry Andric status = ProcessPTEvents(status); 423*bdd1243dSDimitry Andric 424*bdd1243dSDimitry Andric if (IsLibiptError(status)) 425*bdd1243dSDimitry Andric return; 426*bdd1243dSDimitry Andric else if (IsEndOfStream(status)) 427*bdd1243dSDimitry Andric break; 428*bdd1243dSDimitry Andric 429*bdd1243dSDimitry Andric // The status returned by pt_insn_next will need to be processed 430*bdd1243dSDimitry Andric // by ProcessPTEvents in the next loop if it is not an error. 431*bdd1243dSDimitry Andric std::memset(&insn, 0, sizeof insn); 432*bdd1243dSDimitry Andric status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn)); 433*bdd1243dSDimitry Andric 434*bdd1243dSDimitry Andric if (IsLibiptError(status)) { 435*bdd1243dSDimitry Andric m_decoded_thread.AppendError(IntelPTError(status, insn.ip)); 436*bdd1243dSDimitry Andric return; 437*bdd1243dSDimitry Andric } else if (IsEndOfStream(status)) { 438*bdd1243dSDimitry Andric break; 439*bdd1243dSDimitry Andric } 440*bdd1243dSDimitry Andric 441*bdd1243dSDimitry Andric if (!AppendInstructionAndDetectAnomalies(insn)) 442*bdd1243dSDimitry Andric return; 443*bdd1243dSDimitry Andric } 444*bdd1243dSDimitry Andric 445*bdd1243dSDimitry Andric // We need to keep querying non-branching instructions until we hit the 446*bdd1243dSDimitry Andric // starting point of the next PSB. We won't see events at this point. This 447*bdd1243dSDimitry Andric // is based on 448*bdd1243dSDimitry Andric // https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode 449*bdd1243dSDimitry Andric if (m_next_block_ip && insn.ip != 0) { 450*bdd1243dSDimitry Andric while (insn.ip != *m_next_block_ip) { 451*bdd1243dSDimitry Andric if (!AppendInstructionAndDetectAnomalies(insn)) 452*bdd1243dSDimitry Andric return; 453*bdd1243dSDimitry Andric 454*bdd1243dSDimitry Andric status = pt_insn_next(m_decoder_up.get(), &insn, sizeof(insn)); 455*bdd1243dSDimitry Andric 456*bdd1243dSDimitry Andric if (IsLibiptError(status)) { 457*bdd1243dSDimitry Andric m_decoded_thread.AppendError(IntelPTError(status, insn.ip)); 458*bdd1243dSDimitry Andric return; 459*bdd1243dSDimitry Andric } 460*bdd1243dSDimitry Andric } 461*bdd1243dSDimitry Andric } 462*bdd1243dSDimitry Andric } 463*bdd1243dSDimitry Andric 464*bdd1243dSDimitry Andric /// Process the TSC of a decoded PT event. Specifically, check if this TSC 465*bdd1243dSDimitry Andric /// is below the TSC upper bound for this PSB. If the TSC exceeds the upper 466*bdd1243dSDimitry Andric /// bound, return an error to abort decoding. Otherwise add the it to the 467*bdd1243dSDimitry Andric /// underlying DecodedThread and decoding should continue as expected. 468*bdd1243dSDimitry Andric /// 469*bdd1243dSDimitry Andric /// \param[in] tsc 470*bdd1243dSDimitry Andric /// The TSC of the a decoded event. 471*bdd1243dSDimitry Andric Error ProcessPTEventTSC(DecodedThread::TSC tsc) { 472*bdd1243dSDimitry Andric if (m_tsc_upper_bound && tsc >= *m_tsc_upper_bound) { 473*bdd1243dSDimitry Andric // This event and all the remaining events of this PSB have a TSC 474*bdd1243dSDimitry Andric // outside the range of the "owning" ThreadContinuousExecution. For 475*bdd1243dSDimitry Andric // now we drop all of these events/instructions, future work can 476*bdd1243dSDimitry Andric // improve upon this by determining the "owning" 477*bdd1243dSDimitry Andric // ThreadContinuousExecution of the remaining PSB data. 478*bdd1243dSDimitry Andric std::string err_msg = formatv("decoding truncated: TSC {0} exceeds " 479*bdd1243dSDimitry Andric "maximum TSC value {1}, will skip decoding" 480*bdd1243dSDimitry Andric " the remaining data of the PSB", 481*bdd1243dSDimitry Andric tsc, *m_tsc_upper_bound) 482*bdd1243dSDimitry Andric .str(); 483*bdd1243dSDimitry Andric 484*bdd1243dSDimitry Andric uint64_t offset; 485*bdd1243dSDimitry Andric int status = pt_insn_get_offset(m_decoder_up.get(), &offset); 486*bdd1243dSDimitry Andric if (!IsLibiptError(status)) { 487*bdd1243dSDimitry Andric err_msg = formatv("{2} (skipping {0} of {1} bytes)", offset, 488*bdd1243dSDimitry Andric m_psb_block.size, err_msg) 489*bdd1243dSDimitry Andric .str(); 490*bdd1243dSDimitry Andric } 491*bdd1243dSDimitry Andric m_decoded_thread.AppendCustomError(err_msg); 492*bdd1243dSDimitry Andric return createStringError(inconvertibleErrorCode(), err_msg); 493*bdd1243dSDimitry Andric } else { 494*bdd1243dSDimitry Andric m_decoded_thread.NotifyTsc(tsc); 495*bdd1243dSDimitry Andric return Error::success(); 496*bdd1243dSDimitry Andric } 497*bdd1243dSDimitry Andric } 498*bdd1243dSDimitry Andric 499*bdd1243dSDimitry Andric /// Before querying instructions, we need to query the events associated with 500*bdd1243dSDimitry Andric /// that instruction, e.g. timing and trace disablement events. 501*bdd1243dSDimitry Andric /// 502*bdd1243dSDimitry Andric /// \param[in] status 503*bdd1243dSDimitry Andric /// The status gotten from the previous instruction decoding or PSB 504*bdd1243dSDimitry Andric /// synchronization. 505*bdd1243dSDimitry Andric /// 506*bdd1243dSDimitry Andric /// \return 507*bdd1243dSDimitry Andric /// The pte_status after decoding events. 508*bdd1243dSDimitry Andric int ProcessPTEvents(int status) { 509*bdd1243dSDimitry Andric while (HasEvents(status)) { 510*bdd1243dSDimitry Andric pt_event event; 511*bdd1243dSDimitry Andric std::memset(&event, 0, sizeof event); 512*bdd1243dSDimitry Andric status = pt_insn_event(m_decoder_up.get(), &event, sizeof(event)); 513*bdd1243dSDimitry Andric 514*bdd1243dSDimitry Andric if (IsLibiptError(status)) { 515*bdd1243dSDimitry Andric m_decoded_thread.AppendError(IntelPTError(status)); 516*bdd1243dSDimitry Andric return status; 517*bdd1243dSDimitry Andric } 518*bdd1243dSDimitry Andric 519*bdd1243dSDimitry Andric if (event.has_tsc) { 520*bdd1243dSDimitry Andric if (Error err = ProcessPTEventTSC(event.tsc)) { 521*bdd1243dSDimitry Andric consumeError(std::move(err)); 522*bdd1243dSDimitry Andric return -pte_internal; 523*bdd1243dSDimitry Andric } 524*bdd1243dSDimitry Andric } 525*bdd1243dSDimitry Andric 526*bdd1243dSDimitry Andric switch (event.type) { 527*bdd1243dSDimitry Andric case ptev_disabled: 528*bdd1243dSDimitry Andric // The CPU paused tracing the program, e.g. due to ip filtering. 529*bdd1243dSDimitry Andric m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledHW); 530*bdd1243dSDimitry Andric break; 531*bdd1243dSDimitry Andric case ptev_async_disabled: 532*bdd1243dSDimitry Andric // The kernel or user code paused tracing the program, e.g. 533*bdd1243dSDimitry Andric // a breakpoint or a ioctl invocation pausing the trace, or a 534*bdd1243dSDimitry Andric // context switch happened. 535*bdd1243dSDimitry Andric m_decoded_thread.AppendEvent(lldb::eTraceEventDisabledSW); 536*bdd1243dSDimitry Andric break; 537*bdd1243dSDimitry Andric case ptev_overflow: 538*bdd1243dSDimitry Andric // The CPU internal buffer had an overflow error and some instructions 539*bdd1243dSDimitry Andric // were lost. A OVF packet comes with an FUP packet (harcoded address) 540*bdd1243dSDimitry Andric // according to the documentation, so we'll continue seeing instructions 541*bdd1243dSDimitry Andric // after this event. 542*bdd1243dSDimitry Andric m_decoded_thread.AppendError(IntelPTError(-pte_overflow)); 543*bdd1243dSDimitry Andric break; 544*bdd1243dSDimitry Andric default: 545*bdd1243dSDimitry Andric break; 546*bdd1243dSDimitry Andric } 547*bdd1243dSDimitry Andric } 548*bdd1243dSDimitry Andric 549*bdd1243dSDimitry Andric return status; 550*bdd1243dSDimitry Andric } 551*bdd1243dSDimitry Andric 552*bdd1243dSDimitry Andric private: 553*bdd1243dSDimitry Andric PtInsnDecoderUP m_decoder_up; 554*bdd1243dSDimitry Andric PSBBlock m_psb_block; 555*bdd1243dSDimitry Andric std::optional<lldb::addr_t> m_next_block_ip; 556*bdd1243dSDimitry Andric DecodedThread &m_decoded_thread; 557*bdd1243dSDimitry Andric PSBBlockAnomalyDetector m_anomaly_detector; 558*bdd1243dSDimitry Andric std::optional<DecodedThread::TSC> m_tsc_upper_bound; 559*bdd1243dSDimitry Andric }; 560*bdd1243dSDimitry Andric 561*bdd1243dSDimitry Andric Error lldb_private::trace_intel_pt::DecodeSingleTraceForThread( 562*bdd1243dSDimitry Andric DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, 563*bdd1243dSDimitry Andric ArrayRef<uint8_t> buffer) { 564*bdd1243dSDimitry Andric Expected<std::vector<PSBBlock>> blocks = 565*bdd1243dSDimitry Andric SplitTraceIntoPSBBlock(trace_intel_pt, buffer, /*expect_tscs=*/false); 566*bdd1243dSDimitry Andric if (!blocks) 567*bdd1243dSDimitry Andric return blocks.takeError(); 568*bdd1243dSDimitry Andric 569*bdd1243dSDimitry Andric for (size_t i = 0; i < blocks->size(); i++) { 570*bdd1243dSDimitry Andric PSBBlock &block = blocks->at(i); 571*bdd1243dSDimitry Andric 572*bdd1243dSDimitry Andric Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create( 573*bdd1243dSDimitry Andric trace_intel_pt, block, buffer.slice(block.psb_offset, block.size), 574*bdd1243dSDimitry Andric *decoded_thread.GetThread()->GetProcess(), 575*bdd1243dSDimitry Andric i + 1 < blocks->size() ? blocks->at(i + 1).starting_ip : None, 576*bdd1243dSDimitry Andric decoded_thread, std::nullopt); 577*bdd1243dSDimitry Andric if (!decoder) 578*bdd1243dSDimitry Andric return decoder.takeError(); 579*bdd1243dSDimitry Andric 580*bdd1243dSDimitry Andric decoder->DecodePSBBlock(); 581*bdd1243dSDimitry Andric } 582*bdd1243dSDimitry Andric 58381ad6265SDimitry Andric return Error::success(); 58481ad6265SDimitry Andric } 58581ad6265SDimitry Andric 58681ad6265SDimitry Andric Error lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread( 58781ad6265SDimitry Andric DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, 58881ad6265SDimitry Andric const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers, 58981ad6265SDimitry Andric const std::vector<IntelPTThreadContinousExecution> &executions) { 59081ad6265SDimitry Andric bool has_seen_psbs = false; 59181ad6265SDimitry Andric for (size_t i = 0; i < executions.size(); i++) { 59281ad6265SDimitry Andric const IntelPTThreadContinousExecution &execution = executions[i]; 59381ad6265SDimitry Andric 59481ad6265SDimitry Andric auto variant = execution.thread_execution.variant; 595*bdd1243dSDimitry Andric 596*bdd1243dSDimitry Andric // We emit the first valid tsc 597*bdd1243dSDimitry Andric if (execution.psb_blocks.empty()) { 598*bdd1243dSDimitry Andric decoded_thread.NotifyTsc(execution.thread_execution.GetLowestKnownTSC()); 599*bdd1243dSDimitry Andric } else { 600*bdd1243dSDimitry Andric assert(execution.psb_blocks.front().tsc && 601*bdd1243dSDimitry Andric "per cpu decoding expects TSCs"); 602972a253aSDimitry Andric decoded_thread.NotifyTsc( 603*bdd1243dSDimitry Andric std::min(execution.thread_execution.GetLowestKnownTSC(), 604*bdd1243dSDimitry Andric *execution.psb_blocks.front().tsc)); 605972a253aSDimitry Andric } 606972a253aSDimitry Andric 607*bdd1243dSDimitry Andric // We then emit the CPU, which will be correctly associated with a tsc. 608972a253aSDimitry Andric decoded_thread.NotifyCPU(execution.thread_execution.cpu_id); 609972a253aSDimitry Andric 61081ad6265SDimitry Andric // If we haven't seen a PSB yet, then it's fine not to show errors 61181ad6265SDimitry Andric if (has_seen_psbs) { 612*bdd1243dSDimitry Andric if (execution.psb_blocks.empty()) { 61381ad6265SDimitry Andric decoded_thread.AppendCustomError( 614*bdd1243dSDimitry Andric formatv("Unable to find intel pt data a thread " 61581ad6265SDimitry Andric "execution on cpu id = {0}", 61681ad6265SDimitry Andric execution.thread_execution.cpu_id) 61781ad6265SDimitry Andric .str()); 61881ad6265SDimitry Andric } 61981ad6265SDimitry Andric 620*bdd1243dSDimitry Andric // A hinted start is a non-initial execution that doesn't have a switch 621*bdd1243dSDimitry Andric // in. An only end is an initial execution that doesn't have a switch in. 622*bdd1243dSDimitry Andric // Any of those cases represent a gap because we have seen a PSB before. 623*bdd1243dSDimitry Andric if (variant == ThreadContinuousExecution::Variant::HintedStart || 624*bdd1243dSDimitry Andric variant == ThreadContinuousExecution::Variant::OnlyEnd) { 62581ad6265SDimitry Andric decoded_thread.AppendCustomError( 626*bdd1243dSDimitry Andric formatv("Unable to find the context switch in for a thread " 627*bdd1243dSDimitry Andric "execution on cpu id = {0}", 62881ad6265SDimitry Andric execution.thread_execution.cpu_id) 62981ad6265SDimitry Andric .str()); 63081ad6265SDimitry Andric } 63181ad6265SDimitry Andric } 63281ad6265SDimitry Andric 633*bdd1243dSDimitry Andric for (size_t j = 0; j < execution.psb_blocks.size(); j++) { 634*bdd1243dSDimitry Andric const PSBBlock &psb_block = execution.psb_blocks[j]; 63581ad6265SDimitry Andric 636*bdd1243dSDimitry Andric Expected<PSBBlockDecoder> decoder = PSBBlockDecoder::Create( 637*bdd1243dSDimitry Andric trace_intel_pt, psb_block, 638*bdd1243dSDimitry Andric buffers.lookup(execution.thread_execution.cpu_id) 639*bdd1243dSDimitry Andric .slice(psb_block.psb_offset, psb_block.size), 640*bdd1243dSDimitry Andric *decoded_thread.GetThread()->GetProcess(), 641*bdd1243dSDimitry Andric j + 1 < execution.psb_blocks.size() 642*bdd1243dSDimitry Andric ? execution.psb_blocks[j + 1].starting_ip 643*bdd1243dSDimitry Andric : None, 644*bdd1243dSDimitry Andric decoded_thread, execution.thread_execution.GetEndTSC()); 645*bdd1243dSDimitry Andric if (!decoder) 646*bdd1243dSDimitry Andric return decoder.takeError(); 647*bdd1243dSDimitry Andric 648*bdd1243dSDimitry Andric has_seen_psbs = true; 649*bdd1243dSDimitry Andric decoder->DecodePSBBlock(); 650972a253aSDimitry Andric } 651972a253aSDimitry Andric 65281ad6265SDimitry Andric // If we haven't seen a PSB yet, then it's fine not to show errors 65381ad6265SDimitry Andric if (has_seen_psbs) { 654*bdd1243dSDimitry Andric // A hinted end is a non-ending execution that doesn't have a switch out. 655*bdd1243dSDimitry Andric // An only start is an ending execution that doesn't have a switch out. 656*bdd1243dSDimitry Andric // Any of those cases represent a gap if we still have executions to 657*bdd1243dSDimitry Andric // process and we have seen a PSB before. 658*bdd1243dSDimitry Andric if (i + 1 != executions.size() && 659*bdd1243dSDimitry Andric (variant == ThreadContinuousExecution::Variant::OnlyStart || 660*bdd1243dSDimitry Andric variant == ThreadContinuousExecution::Variant::HintedEnd)) { 66181ad6265SDimitry Andric decoded_thread.AppendCustomError( 662*bdd1243dSDimitry Andric formatv("Unable to find the context switch out for a thread " 663972a253aSDimitry Andric "execution on cpu id = {0}", 66481ad6265SDimitry Andric execution.thread_execution.cpu_id) 66581ad6265SDimitry Andric .str()); 66681ad6265SDimitry Andric } 66781ad6265SDimitry Andric } 66881ad6265SDimitry Andric } 66981ad6265SDimitry Andric return Error::success(); 67081ad6265SDimitry Andric } 67181ad6265SDimitry Andric 67281ad6265SDimitry Andric bool IntelPTThreadContinousExecution::operator<( 67381ad6265SDimitry Andric const IntelPTThreadContinousExecution &o) const { 67481ad6265SDimitry Andric // As the context switch might be incomplete, we look first for the first real 67581ad6265SDimitry Andric // PSB packet, which is a valid TSC. Otherwise, We query the thread execution 67681ad6265SDimitry Andric // itself for some tsc. 67781ad6265SDimitry Andric auto get_tsc = [](const IntelPTThreadContinousExecution &exec) { 678*bdd1243dSDimitry Andric return exec.psb_blocks.empty() ? exec.thread_execution.GetLowestKnownTSC() 679*bdd1243dSDimitry Andric : exec.psb_blocks.front().tsc; 68081ad6265SDimitry Andric }; 68181ad6265SDimitry Andric 68281ad6265SDimitry Andric return get_tsc(*this) < get_tsc(o); 68381ad6265SDimitry Andric } 68481ad6265SDimitry Andric 685*bdd1243dSDimitry Andric Expected<std::vector<PSBBlock>> 686*bdd1243dSDimitry Andric lldb_private::trace_intel_pt::SplitTraceIntoPSBBlock( 687*bdd1243dSDimitry Andric TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer, 688*bdd1243dSDimitry Andric bool expect_tscs) { 689*bdd1243dSDimitry Andric // This follows 690*bdd1243dSDimitry Andric // https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#parallel-decode 691*bdd1243dSDimitry Andric 692*bdd1243dSDimitry Andric Expected<PtQueryDecoderUP> decoder_up = 693*bdd1243dSDimitry Andric CreateQueryDecoder(trace_intel_pt, buffer); 69481ad6265SDimitry Andric if (!decoder_up) 69581ad6265SDimitry Andric return decoder_up.takeError(); 69681ad6265SDimitry Andric 697*bdd1243dSDimitry Andric pt_query_decoder *decoder = decoder_up.get().get(); 69881ad6265SDimitry Andric 699*bdd1243dSDimitry Andric std::vector<PSBBlock> executions; 70081ad6265SDimitry Andric 701*bdd1243dSDimitry Andric while (true) { 702*bdd1243dSDimitry Andric uint64_t maybe_ip = LLDB_INVALID_ADDRESS; 703*bdd1243dSDimitry Andric int decoding_status = pt_qry_sync_forward(decoder, &maybe_ip); 704*bdd1243dSDimitry Andric if (IsLibiptError(decoding_status)) 705*bdd1243dSDimitry Andric break; 70681ad6265SDimitry Andric 70781ad6265SDimitry Andric uint64_t psb_offset; 708*bdd1243dSDimitry Andric int offset_status = pt_qry_get_sync_offset(decoder, &psb_offset); 709*bdd1243dSDimitry Andric assert(offset_status >= 0 && 710*bdd1243dSDimitry Andric "This can't fail because we were able to synchronize"); 711*bdd1243dSDimitry Andric 712*bdd1243dSDimitry Andric std::optional<uint64_t> ip; 713*bdd1243dSDimitry Andric if (!(pts_ip_suppressed & decoding_status)) 714*bdd1243dSDimitry Andric ip = maybe_ip; 715*bdd1243dSDimitry Andric 716*bdd1243dSDimitry Andric std::optional<uint64_t> tsc; 717*bdd1243dSDimitry Andric // Now we fetch the first TSC that comes after the PSB. 718*bdd1243dSDimitry Andric while (HasEvents(decoding_status)) { 719*bdd1243dSDimitry Andric pt_event event; 720*bdd1243dSDimitry Andric decoding_status = pt_qry_event(decoder, &event, sizeof(event)); 721*bdd1243dSDimitry Andric if (IsLibiptError(decoding_status)) 722*bdd1243dSDimitry Andric break; 723*bdd1243dSDimitry Andric if (event.has_tsc) { 724*bdd1243dSDimitry Andric tsc = event.tsc; 725*bdd1243dSDimitry Andric break; 726*bdd1243dSDimitry Andric } 727*bdd1243dSDimitry Andric } 728*bdd1243dSDimitry Andric if (IsLibiptError(decoding_status)) { 729*bdd1243dSDimitry Andric // We continue to the next PSB. This effectively merges this PSB with the 730*bdd1243dSDimitry Andric // previous one, and that should be fine because this PSB might be the 731*bdd1243dSDimitry Andric // direct continuation of the previous thread and it's better to show an 732*bdd1243dSDimitry Andric // error in the decoded thread than to hide it. If this is the first PSB, 733*bdd1243dSDimitry Andric // we are okay losing it. Besides that, an error at processing events 734*bdd1243dSDimitry Andric // means that we wouldn't be able to get any instruction out of it. 735*bdd1243dSDimitry Andric continue; 736*bdd1243dSDimitry Andric } 737*bdd1243dSDimitry Andric 738*bdd1243dSDimitry Andric if (expect_tscs && !tsc) 739*bdd1243dSDimitry Andric return createStringError(inconvertibleErrorCode(), 740*bdd1243dSDimitry Andric "Found a PSB without TSC."); 74181ad6265SDimitry Andric 74281ad6265SDimitry Andric executions.push_back({ 74381ad6265SDimitry Andric psb_offset, 74481ad6265SDimitry Andric tsc, 745*bdd1243dSDimitry Andric 0, 746*bdd1243dSDimitry Andric ip, 74781ad6265SDimitry Andric }); 74881ad6265SDimitry Andric } 749*bdd1243dSDimitry Andric if (!executions.empty()) { 750*bdd1243dSDimitry Andric // We now adjust the sizes of each block 751*bdd1243dSDimitry Andric executions.back().size = buffer.size() - executions.back().psb_offset; 752*bdd1243dSDimitry Andric for (int i = (int)executions.size() - 2; i >= 0; i--) { 753*bdd1243dSDimitry Andric executions[i].size = 754*bdd1243dSDimitry Andric executions[i + 1].psb_offset - executions[i].psb_offset; 755*bdd1243dSDimitry Andric } 756*bdd1243dSDimitry Andric } 75781ad6265SDimitry Andric return executions; 75881ad6265SDimitry Andric } 759972a253aSDimitry Andric 760*bdd1243dSDimitry Andric Expected<std::optional<uint64_t>> 761972a253aSDimitry Andric lldb_private::trace_intel_pt::FindLowestTSCInTrace(TraceIntelPT &trace_intel_pt, 762972a253aSDimitry Andric ArrayRef<uint8_t> buffer) { 763*bdd1243dSDimitry Andric Expected<PtQueryDecoderUP> decoder_up = 764*bdd1243dSDimitry Andric CreateQueryDecoder(trace_intel_pt, buffer); 765972a253aSDimitry Andric if (!decoder_up) 766972a253aSDimitry Andric return decoder_up.takeError(); 767972a253aSDimitry Andric 768*bdd1243dSDimitry Andric pt_query_decoder *decoder = decoder_up.get().get(); 769*bdd1243dSDimitry Andric uint64_t ip = LLDB_INVALID_ADDRESS; 770*bdd1243dSDimitry Andric int status = pt_qry_sync_forward(decoder, &ip); 771*bdd1243dSDimitry Andric if (IsLibiptError(status)) 772*bdd1243dSDimitry Andric return std::nullopt; 773972a253aSDimitry Andric 774*bdd1243dSDimitry Andric while (HasEvents(status)) { 775*bdd1243dSDimitry Andric pt_event event; 776*bdd1243dSDimitry Andric status = pt_qry_event(decoder, &event, sizeof(event)); 777*bdd1243dSDimitry Andric if (IsLibiptError(status)) 778*bdd1243dSDimitry Andric return std::nullopt; 779*bdd1243dSDimitry Andric if (event.has_tsc) 780*bdd1243dSDimitry Andric return event.tsc; 781*bdd1243dSDimitry Andric } 782*bdd1243dSDimitry Andric return std::nullopt; 783972a253aSDimitry Andric } 784