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 101 /// An optional offset to a given PSB. Decoding stops if a different PSB is 102 /// reached. 103 void DecodeInstructionsAndEvents(int status, 104 bool stop_on_psb_change = false) { 105 uint64_t psb_offset; 106 pt_insn_get_sync_offset(&m_decoder, 107 &psb_offset); // this can't fail because we got here 108 109 while (true) { 110 DecodedInstruction insn = ProcessPTEvents(status); 111 if (!insn) { 112 m_decoded_thread.Append(insn); 113 break; 114 } 115 116 if (stop_on_psb_change) { 117 uint64_t cur_psb_offset; 118 pt_insn_get_sync_offset( 119 &m_decoder, &cur_psb_offset); // this can't fail because we got here 120 if (cur_psb_offset != psb_offset) 121 break; 122 } 123 124 // The status returned by DecodeNextInstruction will need to be processed 125 // by ProcessPTEvents in the next loop if it is not an error. 126 if (IsLibiptError(status = DecodeNextInstruction(insn))) { 127 insn.libipt_error = status; 128 m_decoded_thread.Append(insn); 129 break; 130 } 131 m_decoded_thread.Append(insn); 132 } 133 } 134 135 /// Move the decoder forward to the next synchronization point (i.e. next PSB 136 /// packet). 137 /// 138 /// Once the decoder is at that synchronization point, it can start decoding 139 /// instructions. 140 /// 141 /// If errors are found, they will be appended to the trace. 142 /// 143 /// \return 144 /// The libipt decoder status after moving to the next PSB. Negative if 145 /// no PSB was found. 146 int FindNextSynchronizationPoint() { 147 // Try to sync the decoder. If it fails, then get the decoder_offset and 148 // try to sync again from the next synchronization point. If the 149 // new_decoder_offset is same as decoder_offset then we can't move to the 150 // next synchronization point. Otherwise, keep resyncing until either end 151 // of trace stream (eos) is reached or pt_insn_sync_forward() passes. 152 int status = pt_insn_sync_forward(&m_decoder); 153 154 // We make this call to record any synchronization errors. 155 if (IsLibiptError(status)) 156 m_decoded_thread.Append(DecodedInstruction(status)); 157 158 return status; 159 } 160 161 /// Before querying instructions, we need to query the events associated that 162 /// instruction e.g. timing events like ptev_tick, or paging events like 163 /// ptev_paging. 164 /// 165 /// \param[in] status 166 /// The status gotten from the previous instruction decoding or PSB 167 /// synchronization. 168 /// 169 /// \return 170 /// A \a DecodedInstruction with event, tsc and error information. 171 DecodedInstruction ProcessPTEvents(int status) { 172 DecodedInstruction insn; 173 while (status & pts_event_pending) { 174 pt_event event; 175 status = pt_insn_event(&m_decoder, &event, sizeof(event)); 176 if (IsLibiptError(status)) { 177 insn.libipt_error = status; 178 break; 179 } 180 181 switch (event.type) { 182 case ptev_enabled: 183 // The kernel started or resumed tracing the program. 184 break; 185 case ptev_disabled: 186 // The CPU paused tracing the program, e.g. due to ip filtering. 187 case ptev_async_disabled: 188 // The kernel or user code paused tracing the program, e.g. 189 // a breakpoint or a ioctl invocation pausing the trace, or a 190 // context switch happened. 191 192 if (m_decoded_thread.GetInstructionsCount() > 0) { 193 // A paused event before the first instruction can be safely 194 // discarded. 195 insn.events |= eTraceEventPaused; 196 } 197 break; 198 case ptev_overflow: 199 // The CPU internal buffer had an overflow error and some instructions 200 // were lost. 201 insn.libipt_error = -pte_overflow; 202 break; 203 default: 204 break; 205 } 206 } 207 208 // We refresh the TSC that might have changed after processing the events. 209 // See 210 // https://github.com/intel/libipt/blob/master/doc/man/pt_evt_next.3.md 211 RefreshTscInfo(); 212 if (m_tsc_info) 213 insn.tsc = m_tsc_info.tsc; 214 return insn; 215 } 216 217 /// Query the decoder for the most recent TSC timestamp and update 218 /// the inner tsc information accordingly. 219 void RefreshTscInfo() { 220 if (m_tsc_info.has_tsc == eLazyBoolNo) 221 return; 222 223 uint64_t new_tsc; 224 int tsc_status; 225 if (IsLibiptError(tsc_status = pt_insn_time(&m_decoder, &new_tsc, nullptr, 226 nullptr))) { 227 if (IsTscUnavailable(tsc_status)) { 228 // We now know that the trace doesn't support TSC, so we won't try 229 // again. 230 // See 231 // https://github.com/intel/libipt/blob/master/doc/man/pt_qry_time.3.md 232 m_tsc_info.has_tsc = eLazyBoolNo; 233 } else { 234 // We don't add TSC decoding errors in the decoded trace itself to 235 // prevent creating unnecessary gaps, but we can count how many of 236 // these errors happened. In this case we reuse the previous correct 237 // TSC we saw, as it's better than no TSC at all. 238 m_decoded_thread.RecordTscError(tsc_status); 239 } 240 } else { 241 m_tsc_info.tsc = new_tsc; 242 m_tsc_info.has_tsc = eLazyBoolYes; 243 } 244 } 245 246 private: 247 pt_insn_decoder &m_decoder; 248 DecodedThread &m_decoded_thread; 249 TscInfo m_tsc_info; 250 }; 251 252 /// Callback used by libipt for reading the process memory. 253 /// 254 /// More information can be found in 255 /// https://github.com/intel/libipt/blob/master/doc/man/pt_image_set_callback.3.md 256 static int ReadProcessMemory(uint8_t *buffer, size_t size, 257 const pt_asid * /* unused */, uint64_t pc, 258 void *context) { 259 Process *process = static_cast<Process *>(context); 260 261 Status error; 262 int bytes_read = process->ReadMemory(pc, buffer, size, error); 263 if (error.Fail()) 264 return -pte_nomap; 265 return bytes_read; 266 } 267 268 // RAII deleter for libipt's decoder 269 auto DecoderDeleter = [](pt_insn_decoder *decoder) { 270 pt_insn_free_decoder(decoder); 271 }; 272 273 using PtInsnDecoderUP = 274 std::unique_ptr<pt_insn_decoder, decltype(DecoderDeleter)>; 275 276 static Expected<PtInsnDecoderUP> 277 CreateInstructionDecoder(TraceIntelPT &trace_intel_pt, 278 ArrayRef<uint8_t> buffer) { 279 Expected<pt_cpu> cpu_info = trace_intel_pt.GetCPUInfo(); 280 if (!cpu_info) 281 return cpu_info.takeError(); 282 283 pt_config config; 284 pt_config_init(&config); 285 config.cpu = *cpu_info; 286 int status = pte_ok; 287 288 if (IsLibiptError(status = pt_cpu_errata(&config.errata, &config.cpu))) 289 return make_error<IntelPTError>(status); 290 291 // The libipt library does not modify the trace buffer, hence the 292 // following casts are safe. 293 config.begin = const_cast<uint8_t *>(buffer.data()); 294 config.end = const_cast<uint8_t *>(buffer.data() + buffer.size()); 295 296 pt_insn_decoder *decoder_ptr = pt_insn_alloc_decoder(&config); 297 if (!decoder_ptr) 298 return make_error<IntelPTError>(-pte_nomem); 299 300 return PtInsnDecoderUP(decoder_ptr, DecoderDeleter); 301 } 302 303 static Error SetupMemoryImage(PtInsnDecoderUP &decoder_up, Process &process) { 304 pt_image *image = pt_insn_get_image(decoder_up.get()); 305 306 int status = pte_ok; 307 if (IsLibiptError( 308 status = pt_image_set_callback(image, ReadProcessMemory, &process))) 309 return make_error<IntelPTError>(status); 310 return Error::success(); 311 } 312 313 void lldb_private::trace_intel_pt::DecodeTrace(DecodedThread &decoded_thread, 314 TraceIntelPT &trace_intel_pt, 315 ArrayRef<uint8_t> buffer) { 316 Expected<PtInsnDecoderUP> decoder_up = 317 CreateInstructionDecoder(trace_intel_pt, buffer); 318 if (!decoder_up) 319 return decoded_thread.SetAsFailed(decoder_up.takeError()); 320 321 if (Error err = SetupMemoryImage(*decoder_up, 322 *decoded_thread.GetThread()->GetProcess())) 323 return decoded_thread.SetAsFailed(std::move(err)); 324 325 LibiptDecoder libipt_decoder(*decoder_up.get(), decoded_thread); 326 libipt_decoder.DecodeUntilEndOfTrace(); 327 } 328 329 void lldb_private::trace_intel_pt::DecodeTrace( 330 DecodedThread &decoded_thread, TraceIntelPT &trace_intel_pt, 331 const DenseMap<lldb::core_id_t, llvm::ArrayRef<uint8_t>> &buffers, 332 const std::vector<IntelPTThreadContinousExecution> &executions) { 333 DenseMap<lldb::core_id_t, LibiptDecoder> decoders; 334 for (auto &core_id_buffer : buffers) { 335 Expected<PtInsnDecoderUP> decoder_up = 336 CreateInstructionDecoder(trace_intel_pt, core_id_buffer.second); 337 if (!decoder_up) 338 return decoded_thread.SetAsFailed(decoder_up.takeError()); 339 340 if (Error err = SetupMemoryImage(*decoder_up, 341 *decoded_thread.GetThread()->GetProcess())) 342 return decoded_thread.SetAsFailed(std::move(err)); 343 344 decoders.try_emplace(core_id_buffer.first, 345 LibiptDecoder(*decoder_up->release(), decoded_thread)); 346 } 347 348 bool has_seen_psbs = false; 349 for (size_t i = 0; i < executions.size(); i++) { 350 const IntelPTThreadContinousExecution &execution = executions[i]; 351 352 auto variant = execution.thread_execution.variant; 353 // If we haven't seen a PSB yet, then it's fine not to show errors 354 if (has_seen_psbs) { 355 if (execution.intelpt_subtraces.empty()) { 356 decoded_thread.AppendError(createStringError( 357 inconvertibleErrorCode(), 358 formatv("Unable to find intel pt data for thread execution with " 359 "tsc = {0} on core id = {1}", 360 execution.thread_execution.GetLowestKnownTSC(), 361 execution.thread_execution.core_id))); 362 } 363 364 // If the first execution is incomplete because it doesn't have a previous 365 // context switch in its cpu, all good. 366 if (variant == ThreadContinuousExecution::Variant::OnlyEnd || 367 variant == ThreadContinuousExecution::Variant::HintedStart) { 368 decoded_thread.AppendError(createStringError( 369 inconvertibleErrorCode(), 370 formatv("Thread execution starting at tsc = {0} on core id = {1} " 371 "doesn't have a matching context switch in.", 372 execution.thread_execution.GetLowestKnownTSC(), 373 execution.thread_execution.core_id))); 374 } 375 } 376 377 LibiptDecoder &decoder = 378 decoders.find(execution.thread_execution.core_id)->second; 379 for (const IntelPTThreadSubtrace &intel_pt_execution : 380 execution.intelpt_subtraces) { 381 has_seen_psbs = true; 382 decoder.DecodePSB(intel_pt_execution.psb_offset); 383 } 384 385 // If we haven't seen a PSB yet, then it's fine not to show errors 386 if (has_seen_psbs) { 387 // If the last execution is incomplete because it doesn't have a following 388 // context switch in its cpu, all good. 389 if ((variant == ThreadContinuousExecution::Variant::OnlyStart && 390 i + 1 != executions.size()) || 391 variant == ThreadContinuousExecution::Variant::HintedEnd) { 392 decoded_thread.AppendError(createStringError( 393 inconvertibleErrorCode(), 394 formatv("Thread execution starting at tsc = {0} on core id = {1} " 395 "doesn't have a matching context switch out", 396 execution.thread_execution.GetLowestKnownTSC(), 397 execution.thread_execution.core_id))); 398 } 399 } 400 } 401 } 402 403 bool IntelPTThreadContinousExecution::operator<( 404 const IntelPTThreadContinousExecution &o) const { 405 // As the context switch might be incomplete, we look first for the first real 406 // PSB packet, which is a valid TSC. Otherwise, We query the thread execution 407 // itself for some tsc. 408 auto get_tsc = [](const IntelPTThreadContinousExecution &exec) { 409 return exec.intelpt_subtraces.empty() 410 ? exec.thread_execution.GetLowestKnownTSC() 411 : exec.intelpt_subtraces.front().tsc; 412 }; 413 414 return get_tsc(*this) < get_tsc(o); 415 } 416 417 Expected<std::vector<IntelPTThreadSubtrace>> 418 lldb_private::trace_intel_pt::SplitTraceInContinuousExecutions( 419 TraceIntelPT &trace_intel_pt, llvm::ArrayRef<uint8_t> buffer) { 420 Expected<PtInsnDecoderUP> decoder_up = 421 CreateInstructionDecoder(trace_intel_pt, buffer); 422 if (!decoder_up) 423 return decoder_up.takeError(); 424 425 pt_insn_decoder *decoder = decoder_up.get().get(); 426 427 std::vector<IntelPTThreadSubtrace> executions; 428 429 int status = pte_ok; 430 while (!IsLibiptError(status = pt_insn_sync_forward(decoder))) { 431 uint64_t tsc; 432 if (IsLibiptError(pt_insn_time(decoder, &tsc, nullptr, nullptr))) 433 return createStringError(inconvertibleErrorCode(), 434 "intel pt trace doesn't have TSC timestamps"); 435 436 uint64_t psb_offset; 437 pt_insn_get_sync_offset(decoder, 438 &psb_offset); // this can't fail because we got here 439 440 executions.push_back({ 441 tsc, 442 psb_offset, 443 }); 444 } 445 return executions; 446 } 447