1 //===-- LibiptDecoder.cpp --======-----------------------------------------===// 2 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 3 // See https://llvm.org/LICENSE.txt for license information. 4 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 5 // 6 //===----------------------------------------------------------------------===// 7 8 #include "LibiptDecoder.h" 9 10 #include "TraceIntelPT.h" 11 12 #include "lldb/Target/Process.h" 13 14 using namespace lldb; 15 using namespace lldb_private; 16 using namespace lldb_private::trace_intel_pt; 17 using namespace llvm; 18 19 // Simple struct used by the decoder to keep the state of the most 20 // recent TSC and a flag indicating whether TSCs are enabled, not enabled 21 // or we just don't yet. 22 struct TscInfo { 23 uint64_t tsc = 0; 24 LazyBool has_tsc = eLazyBoolCalculate; 25 26 explicit operator bool() const { return has_tsc == eLazyBoolYes; } 27 }; 28 29 /// Class that decodes a raw buffer for a single thread using the low level 30 /// libipt library. 31 /// 32 /// Throughout this code, the status of the decoder will be used to identify 33 /// events needed to be processed or errors in the decoder. The values can be 34 /// - negative: actual errors 35 /// - positive or zero: not an error, but a list of bits signaling the status 36 /// of the decoder, e.g. whether there are events that need to be decoded or 37 /// not. 38 class LibiptDecoder { 39 public: 40 /// \param[in] decoder 41 /// A well configured decoder. Using the current state of that decoder, 42 /// decoding will start at its next valid PSB. It's not assumed that the 43 /// decoder is already pointing at a valid PSB. 44 /// 45 /// \param[in] decoded_thread 46 /// A \a DecodedThread object where the decoded instructions will be 47 /// appended to. It might have already some instructions. 48 LibiptDecoder(pt_insn_decoder &decoder, DecodedThread &decoded_thread) 49 : m_decoder(decoder), m_decoded_thread(decoded_thread) {} 50 51 /// Decode all the instructions until the end of the trace. 52 /// The decoding flow is based on 53 /// https://github.com/intel/libipt/blob/master/doc/howto_libipt.md#the-instruction-flow-decode-loop. 54 void DecodeUntilEndOfTrace() { 55 // Multiple loops indicate gaps in the trace, which are found by the inner 56 // call to DecodeInstructionsAndEvents. 57 while (true) { 58 int status = pt_insn_sync_forward(&m_decoder); 59 60 if (IsLibiptError(status)) { 61 m_decoded_thread.Append(DecodedInstruction(status)); 62 break; 63 } 64 65 DecodeInstructionsAndEvents(status); 66 } 67 } 68 69 /// Decode all the instructions that belong to the same PSB packet given its 70 /// offset. 71 void DecodePSB(uint64_t psb_offset) { 72 int status = pt_insn_sync_set(&m_decoder, psb_offset); 73 if (IsLibiptError(status)) { 74 m_decoded_thread.Append(DecodedInstruction(status)); 75 return; 76 } 77 DecodeInstructionsAndEvents(status, /*stop_on_psb_change=*/true); 78 } 79 80 private: 81 /// Invoke the low level function \a pt_insn_next and store the decoded 82 /// instruction in the given \a DecodedInstruction. 83 /// 84 /// \param[out] insn 85 /// The instruction builder where the pt_insn information will be stored. 86 /// 87 /// \return 88 /// The status returned by pt_insn_next. 89 int DecodeNextInstruction(DecodedInstruction &insn) { 90 return pt_insn_next(&m_decoder, &insn.pt_insn, sizeof(insn.pt_insn)); 91 } 92 93 /// Decode all the instructions and events until an error is found, the end 94 /// of the trace is reached, or optionally a new PSB is reached. 95 /// 96 /// \param[in] status 97 /// The status that was result of synchronizing to the most recent PSB. 98 /// 99 /// \param[in] stop_on_psb_change 100 /// If \b true, decoding stops if a different PSB is reached. 101 void DecodeInstructionsAndEvents(int status, 102 bool stop_on_psb_change = false) { 103 uint64_t psb_offset; 104 pt_insn_get_sync_offset(&m_decoder, 105 &psb_offset); // this can't fail because we got here 106 107 while (true) { 108 DecodedInstruction insn = ProcessPTEvents(status); 109 if (!insn) { 110 m_decoded_thread.Append(insn); 111 break; 112 } 113 114 if (stop_on_psb_change) { 115 uint64_t cur_psb_offset; 116 pt_insn_get_sync_offset( 117 &m_decoder, &cur_psb_offset); // this can't fail because we got here 118 if (cur_psb_offset != psb_offset) 119 break; 120 } 121 122 // The status returned by DecodeNextInstruction will need to be processed 123 // by ProcessPTEvents in the next loop if it is not an error. 124 if (IsLibiptError(status = DecodeNextInstruction(insn))) { 125 insn.libipt_error = status; 126 m_decoded_thread.Append(insn); 127 break; 128 } 129 m_decoded_thread.Append(insn); 130 } 131 } 132 133 /// Move the decoder forward to the next synchronization point (i.e. next PSB 134 /// packet). 135 /// 136 /// Once the decoder is at that synchronization point, it can start decoding 137 /// instructions. 138 /// 139 /// If errors are found, they will be appended to the trace. 140 /// 141 /// \return 142 /// The libipt decoder status after moving to the next PSB. Negative if 143 /// no PSB was found. 144 int FindNextSynchronizationPoint() { 145 // Try to sync the decoder. If it fails, then get the decoder_offset and 146 // try to sync again from the next synchronization point. If the 147 // new_decoder_offset is same as decoder_offset then we can't move to the 148 // next synchronization point. Otherwise, keep resyncing until either end 149 // of trace stream (eos) is reached or pt_insn_sync_forward() passes. 150 int status = pt_insn_sync_forward(&m_decoder); 151 152 // We make this call to record any synchronization errors. 153 if (IsLibiptError(status)) 154 m_decoded_thread.Append(DecodedInstruction(status)); 155 156 return status; 157 } 158 159 /// Before querying instructions, we need to query the events associated that 160 /// instruction e.g. timing events like ptev_tick, or paging events like 161 /// ptev_paging. 162 /// 163 /// \param[in] status 164 /// The status gotten from the previous instruction decoding or PSB 165 /// synchronization. 166 /// 167 /// \return 168 /// A \a DecodedInstruction with event, tsc and error information. 169 DecodedInstruction ProcessPTEvents(int status) { 170 DecodedInstruction insn; 171 while (status & pts_event_pending) { 172 pt_event event; 173 status = pt_insn_event(&m_decoder, &event, sizeof(event)); 174 if (IsLibiptError(status)) { 175 insn.libipt_error = status; 176 break; 177 } 178 179 switch (event.type) { 180 case ptev_enabled: 181 // The kernel started or resumed tracing the program. 182 break; 183 case ptev_disabled: 184 // The CPU paused tracing the program, e.g. due to ip filtering. 185 case ptev_async_disabled: 186 // The kernel or user code paused tracing the program, e.g. 187 // a breakpoint or a ioctl invocation pausing the trace, or a 188 // context switch happened. 189 190 if (m_decoded_thread.GetInstructionsCount() > 0) { 191 // A paused event before the first instruction can be safely 192 // discarded. 193 insn.events |= eTraceEventPaused; 194 } 195 break; 196 case ptev_overflow: 197 // The CPU internal buffer had an overflow error and some instructions 198 // were lost. 199 insn.libipt_error = -pte_overflow; 200 break; 201 default: 202 break; 203 } 204 } 205 206 // We refresh the TSC that might have changed after processing the events. 207 // See 208 // https://github.com/intel/libipt/blob/master/doc/man/pt_evt_next.3.md 209 RefreshTscInfo(); 210 if (m_tsc_info) 211 insn.tsc = m_tsc_info.tsc; 212 return insn; 213 } 214 215 /// Query the decoder for the most recent TSC timestamp and update 216 /// the inner tsc information accordingly. 217 void RefreshTscInfo() { 218 if (m_tsc_info.has_tsc == eLazyBoolNo) 219 return; 220 221 uint64_t new_tsc; 222 int tsc_status; 223 if (IsLibiptError(tsc_status = pt_insn_time(&m_decoder, &new_tsc, nullptr, 224 nullptr))) { 225 if (IsTscUnavailable(tsc_status)) { 226 // We now know that the trace doesn't support TSC, so we won't try 227 // again. 228 // See 229 // https://github.com/intel/libipt/blob/master/doc/man/pt_qry_time.3.md 230 m_tsc_info.has_tsc = eLazyBoolNo; 231 } else { 232 // We don't add TSC decoding errors in the decoded trace itself to 233 // prevent creating unnecessary gaps, but we can count how many of 234 // these errors happened. In this case we reuse the previous correct 235 // TSC we saw, as it's better than no TSC at all. 236 m_decoded_thread.RecordTscError(tsc_status); 237 } 238 } else { 239 m_tsc_info.tsc = new_tsc; 240 m_tsc_info.has_tsc = eLazyBoolYes; 241 } 242 } 243 244 private: 245 pt_insn_decoder &m_decoder; 246 DecodedThread &m_decoded_thread; 247 TscInfo m_tsc_info; 248 }; 249 250 /// Callback used by libipt for reading the process memory. 251 /// 252 /// More information can be found in 253 /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md 254 static int ReadProcessMemory(uint8_t *buffer, size_t size, 255 const pt_asid * /* unused */, uint64_t pc, 256 void *context) { 257 Process *process = static_cast<Process *>(context); 258 259 Status error; 260 int bytes_read = process->ReadMemory(pc, buffer, size, error); 261 if (error.Fail()) 262 return -pte_nomap; 263 return bytes_read; 264 } 265 266 // RAII deleter for libipt's decoder 267 auto DecoderDeleter = [](pt_insn_decoder *decoder) { 268 pt_insn_free_decoder(decoder); 269 }; 270 271 using PtInsnDecoderUP = 272 std::unique_ptr<pt_insn_decoder, decltype(DecoderDeleter)>; 273 274 static Expected<PtInsnDecoderUP> 275 CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, 276 ArrayRef<uint8_t> buffer) { 277 Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo(); 278 if (!cpu_info) 279 return cpu_info.takeError(); 280 281 pt_config config; 282 pt_config_init(&config); 283 config.cpu = *cpu_info; 284 int status = pte_ok; 285 286 if (IsLibiptError(status = pt_cpu_errata(&config.errata, &config.cpu))) 287 return make_error<IntelPTError>(status); 288 289 // The libipt library does not modify the trace buffer, hence the 290 // following casts are safe. 291 config.begin = const_cast<uint8_t *>(buffer.data()); 292 config.end = const_cast<uint8_t *>(buffer.data() + buffer.size()); 293 294 pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&config); 295 if (!decoder_ptr) 296 return make_error<IntelPTError>(-pte_nomem); 297 298 return PtInsnDecoderUP(decoder_ptr, DecoderDeleter); 299 } 300 301 static Error SetupMemoryImage(PtInsnDecoderUP &decoder_up, Process &process) { 302 pt_image *image = pt_insn_get_image(decoder_up.get()); 303 304 int status = pte_ok; 305 if (IsLibiptError( 306 status = pt_image_set_callback(image, ReadProcessMemory, &process))) 307 return make_error<IntelPTError>(status); 308 return Error::success(); 309 } 310 311 void lldb_private::trace_intel_pt::DecodeSingleTraceForThread(DecodedThread &decoded_thread, 312 TraceIntelPT &trace_intel_pt, 313 ArrayRef<uint8_t> buffer) { 314 Expected<PtInsnDecoderUP> decoder_up = 315 CreateInstructionDecoder(trace_intel_pt, buffer); 316 if (!decoder_up) 317 return decoded_thread.SetAsFailed(decoder_up.takeError()); 318 319 if (Error err = SetupMemoryImage(*decoder_up, 320 *decoded_thread.GetThread()->GetProcess())) 321 return decoded_thread.SetAsFailed(std::move(err)); 322 323 LibiptDecoder libipt_decoder(*decoder_up.get(), decoded_thread); 324 libipt_decoder.DecodeUntilEndOfTrace(); 325 } 326 327 void lldb_private::trace_intel_pt::DecodeSystemWideTraceForThread( 328 DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, 329 const DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> &buffers, 330 const std::vector<IntelPTThreadContinousExecution> &executions) { 331 DenseMap<lldb::cpu_id_t, LibiptDecoder> decoders; 332 for (auto &cpu_id_buffer : buffers) { 333 Expected<PtInsnDecoderUP> decoder_up = 334 CreateInstructionDecoder(trace_intel_pt, cpu_id_buffer.second); 335 if (!decoder_up) 336 return decoded_thread.SetAsFailed(decoder_up.takeError()); 337 338 if (Error err = SetupMemoryImage(*decoder_up, 339 *decoded_thread.GetThread()->GetProcess())) 340 return decoded_thread.SetAsFailed(std::move(err)); 341 342 decoders.try_emplace(cpu_id_buffer.first, 343 LibiptDecoder(*decoder_up->release(), decoded_thread)); 344 } 345 346 bool has_seen_psbs = false; 347 for (size_t i = 0; i < executions.size(); i++) { 348 const IntelPTThreadContinousExecution &execution = executions[i]; 349 350 auto variant = execution.thread_execution.variant; 351 // If we haven't seen a PSB yet, then it's fine not to show errors 352 if (has_seen_psbs) { 353 if (execution.intelpt_subtraces.empty()) { 354 decoded_thread.AppendError(createStringError( 355 inconvertibleErrorCode(), 356 formatv("Unable to find intel pt data for thread execution with " 357 "tsc = {0} on cpu id = {1}", 358 execution.thread_execution.GetLowestKnownTSC(), 359 execution.thread_execution.cpu_id))); 360 } 361 362 // If the first execution is incomplete because it doesn't have a previous 363 // context switch in its cpu, all good. 364 if (variant == ThreadContinuousExecution::Variant::OnlyEnd || 365 variant == ThreadContinuousExecution::Variant::HintedStart) { 366 decoded_thread.AppendError(createStringError( 367 inconvertibleErrorCode(), 368 formatv("Thread execution starting at tsc = {0} on cpu id = {1} " 369 "doesn't have a matching context switch in.", 370 execution.thread_execution.GetLowestKnownTSC(), 371 execution.thread_execution.cpu_id))); 372 } 373 } 374 375 LibiptDecoder &decoder = 376 decoders.find(execution.thread_execution.cpu_id)->second; 377 for (const IntelPTThreadSubtrace &intel_pt_execution : 378 execution.intelpt_subtraces) { 379 has_seen_psbs = true; 380 decoder.DecodePSB(intel_pt_execution.psb_offset); 381 } 382 383 // If we haven't seen a PSB yet, then it's fine not to show errors 384 if (has_seen_psbs) { 385 // If the last execution is incomplete because it doesn't have a following 386 // context switch in its cpu, all good. 387 if ((variant == ThreadContinuousExecution::Variant::OnlyStart && 388 i + 1 != executions.size()) || 389 variant == ThreadContinuousExecution::Variant::HintedEnd) { 390 decoded_thread.AppendError(createStringError( 391 inconvertibleErrorCode(), 392 formatv("Thread execution starting at tsc = {0} on cpu id = {1} " 393 "doesn't have a matching context switch out", 394 execution.thread_execution.GetLowestKnownTSC(), 395 execution.thread_execution.cpu_id))); 396 } 397 } 398 } 399 } 400 401 bool IntelPTThreadContinousExecution::operator<( 402 const IntelPTThreadContinousExecution &o) const { 403 // As the context switch might be incomplete, we look first for the first real 404 // PSB packet, which is a valid TSC. Otherwise, We query the thread execution 405 // itself for some tsc. 406 auto get_tsc = [](const IntelPTThreadContinousExecution &exec) { 407 return exec.intelpt_subtraces.empty() 408 ? exec.thread_execution.GetLowestKnownTSC() 409 : exec.intelpt_subtraces.front().tsc; 410 }; 411 412 return get_tsc(*this) < get_tsc(o); 413 } 414 415 Expected<std::vector<IntelPTThreadSubtrace>> 416 lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions( 417 TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer) { 418 Expected<PtInsnDecoderUP> decoder_up = 419 CreateInstructionDecoder(trace_intel_pt, buffer); 420 if (!decoder_up) 421 return decoder_up.takeError(); 422 423 pt_insn_decoder *decoder = decoder_up.get().get(); 424 425 std::vector<IntelPTThreadSubtrace> executions; 426 427 int status = pte_ok; 428 while (!IsLibiptError(status = pt_insn_sync_forward(decoder))) { 429 uint64_t tsc; 430 if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr))) 431 return createStringError(inconvertibleErrorCode(), 432 "intel pt trace doesn't have TSC timestamps"); 433 434 uint64_t psb_offset; 435 pt_insn_get_sync_offset(decoder, 436 &psb_offset); // this can't fail because we got here 437 438 executions.push_back({ 439 psb_offset, 440 tsc, 441 }); 442 } 443 return executions; 444 } 445