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