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