1 //===-- DecodedThread.cpp -------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "DecodedThread.h" 10 11 #include <intel-pt.h> 12 13 #include "TraceCursorIntelPT.h" 14 15 #include <memory> 16 17 using namespace lldb; 18 using namespace lldb_private; 19 using namespace lldb_private::trace_intel_pt; 20 using namespace llvm; 21 22 char IntelPTError::ID; 23 24 IntelPTError::IntelPTError(int libipt_error_code, lldb::addr_t address) 25 : m_libipt_error_code(libipt_error_code), m_address(address) { 26 assert(libipt_error_code < 0); 27 } 28 29 void IntelPTError::log(llvm::raw_ostream &OS) const { 30 const char *libipt_error_message = pt_errstr(pt_errcode(m_libipt_error_code)); 31 if (m_address != LLDB_INVALID_ADDRESS && m_address > 0) { 32 write_hex(OS, m_address, HexPrintStyle::PrefixLower, 18); 33 OS << " "; 34 } 35 OS << "error: " << libipt_error_message; 36 } 37 38 Optional<size_t> DecodedThread::GetRawTraceSize() const { 39 return m_raw_trace_size; 40 } 41 42 size_t DecodedThread::GetInstructionsCount() const { 43 return m_instruction_ips.size(); 44 } 45 46 lldb::addr_t DecodedThread::GetInstructionLoadAddress(size_t insn_index) const { 47 return m_instruction_ips[insn_index]; 48 } 49 50 TraceInstructionControlFlowType 51 DecodedThread::GetInstructionControlFlowType(size_t insn_index) const { 52 if (IsInstructionAnError(insn_index)) 53 return (TraceInstructionControlFlowType)0; 54 55 TraceInstructionControlFlowType mask = 56 eTraceInstructionControlFlowTypeInstruction; 57 58 lldb::addr_t load_address = m_instruction_ips[insn_index]; 59 uint8_t insn_byte_size = m_instruction_sizes[insn_index]; 60 pt_insn_class iclass = m_instruction_classes[insn_index]; 61 62 switch (iclass) { 63 case ptic_cond_jump: 64 case ptic_jump: 65 case ptic_far_jump: 66 mask |= eTraceInstructionControlFlowTypeBranch; 67 if (insn_index + 1 < m_instruction_ips.size() && 68 load_address + insn_byte_size != m_instruction_ips[insn_index + 1]) 69 mask |= eTraceInstructionControlFlowTypeTakenBranch; 70 break; 71 case ptic_return: 72 case ptic_far_return: 73 mask |= eTraceInstructionControlFlowTypeReturn; 74 break; 75 case ptic_call: 76 case ptic_far_call: 77 mask |= eTraceInstructionControlFlowTypeCall; 78 break; 79 default: 80 break; 81 } 82 83 return mask; 84 } 85 86 ThreadSP DecodedThread::GetThread() { return m_thread_sp; } 87 88 void DecodedThread::RecordTscForLastInstruction(uint64_t tsc) { 89 if (!m_last_tsc || *m_last_tsc != tsc) { 90 // In case the first instructions are errors or did not have a TSC, we'll 91 // get a first valid TSC not in position 0. We can safely force these error 92 // instructions to use the first valid TSC, so that all the trace has TSCs. 93 size_t start_index = 94 m_instruction_timestamps.empty() ? 0 : m_instruction_ips.size() - 1; 95 m_instruction_timestamps.emplace(start_index, tsc); 96 m_last_tsc = tsc; 97 } 98 } 99 100 void DecodedThread::AppendInstruction(const pt_insn &insn) { 101 m_instruction_ips.emplace_back(insn.ip); 102 m_instruction_sizes.emplace_back(insn.size); 103 m_instruction_classes.emplace_back(insn.iclass); 104 } 105 106 void DecodedThread::AppendInstruction(const pt_insn &insn, uint64_t tsc) { 107 AppendInstruction(insn); 108 RecordTscForLastInstruction(tsc); 109 } 110 111 void DecodedThread::AppendError(llvm::Error &&error) { 112 m_errors.try_emplace(m_instruction_ips.size(), toString(std::move(error))); 113 m_instruction_ips.emplace_back(LLDB_INVALID_ADDRESS); 114 m_instruction_sizes.emplace_back(0); 115 m_instruction_classes.emplace_back(pt_insn_class::ptic_error); 116 } 117 118 void DecodedThread::AppendError(llvm::Error &&error, uint64_t tsc) { 119 AppendError(std::move(error)); 120 RecordTscForLastInstruction(tsc); 121 } 122 123 void DecodedThread::LibiptErrors::RecordError(int libipt_error_code) { 124 libipt_errors[pt_errstr(pt_errcode(libipt_error_code))]++; 125 total_count++; 126 } 127 128 void DecodedThread::RecordTscError(int libipt_error_code) { 129 m_tsc_errors.RecordError(libipt_error_code); 130 } 131 132 const DecodedThread::LibiptErrors &DecodedThread::GetTscErrors() const { 133 return m_tsc_errors; 134 } 135 136 Optional<DecodedThread::TscRange> DecodedThread::CalculateTscRange( 137 size_t insn_index, 138 const Optional<DecodedThread::TscRange> &hint_range) const { 139 // We first try to check the given hint range in case we are traversing the 140 // trace in short jumps. If that fails, then we do the more expensive 141 // arbitrary lookup. 142 if (hint_range) { 143 Optional<TscRange> candidate_range; 144 if (insn_index < hint_range->GetStartInstructionIndex()) 145 candidate_range = hint_range->Prev(); 146 else if (insn_index > hint_range->GetEndInstructionIndex()) 147 candidate_range = hint_range->Next(); 148 else 149 candidate_range = hint_range; 150 151 if (candidate_range && candidate_range->InRange(insn_index)) 152 return candidate_range; 153 } 154 // Now we do a more expensive lookup 155 auto it = m_instruction_timestamps.upper_bound(insn_index); 156 if (it == m_instruction_timestamps.begin()) 157 return None; 158 159 return TscRange(--it, *this); 160 } 161 162 bool DecodedThread::IsInstructionAnError(size_t insn_idx) const { 163 return m_instruction_ips[insn_idx] == LLDB_INVALID_ADDRESS; 164 } 165 166 const char *DecodedThread::GetErrorByInstructionIndex(size_t insn_idx) { 167 auto it = m_errors.find(insn_idx); 168 if (it == m_errors.end()) 169 return nullptr; 170 171 return it->second.c_str(); 172 } 173 174 DecodedThread::DecodedThread(ThreadSP thread_sp) : m_thread_sp(thread_sp) {} 175 176 DecodedThread::DecodedThread(ThreadSP thread_sp, Error &&error) 177 : m_thread_sp(thread_sp) { 178 AppendError(std::move(error)); 179 } 180 181 void DecodedThread::SetRawTraceSize(size_t size) { m_raw_trace_size = size; } 182 183 lldb::TraceCursorUP DecodedThread::GetCursor() { 184 // We insert a fake error signaling an empty trace if needed becasue the 185 // TraceCursor requires non-empty traces. 186 if (m_instruction_ips.empty()) 187 AppendError(createStringError(inconvertibleErrorCode(), "empty trace")); 188 return std::make_unique<TraceCursorIntelPT>(m_thread_sp, shared_from_this()); 189 } 190 191 size_t DecodedThread::CalculateApproximateMemoryUsage() const { 192 return sizeof(pt_insn::ip) * m_instruction_ips.size() + 193 sizeof(pt_insn::size) * m_instruction_sizes.size() + 194 sizeof(pt_insn::iclass) * m_instruction_classes.size() + 195 (sizeof(size_t) + sizeof(uint64_t)) * m_instruction_timestamps.size() + 196 m_errors.getMemorySize(); 197 } 198 199 DecodedThread::TscRange::TscRange(std::map<size_t, uint64_t>::const_iterator it, 200 const DecodedThread &decoded_thread) 201 : m_it(it), m_decoded_thread(&decoded_thread) { 202 auto next_it = m_it; 203 ++next_it; 204 m_end_index = (next_it == m_decoded_thread->m_instruction_timestamps.end()) 205 ? m_decoded_thread->GetInstructionsCount() - 1 206 : next_it->first - 1; 207 } 208 209 size_t DecodedThread::TscRange::GetTsc() const { return m_it->second; } 210 211 size_t DecodedThread::TscRange::GetStartInstructionIndex() const { 212 return m_it->first; 213 } 214 215 size_t DecodedThread::TscRange::GetEndInstructionIndex() const { 216 return m_end_index; 217 } 218 219 bool DecodedThread::TscRange::InRange(size_t insn_index) const { 220 return GetStartInstructionIndex() <= insn_index && 221 insn_index <= GetEndInstructionIndex(); 222 } 223 224 Optional<DecodedThread::TscRange> DecodedThread::TscRange::Next() const { 225 auto next_it = m_it; 226 ++next_it; 227 if (next_it == m_decoded_thread->m_instruction_timestamps.end()) 228 return None; 229 return TscRange(next_it, *m_decoded_thread); 230 } 231 232 Optional<DecodedThread::TscRange> DecodedThread::TscRange::Prev() const { 233 if (m_it == m_decoded_thread->m_instruction_timestamps.begin()) 234 return None; 235 auto prev_it = m_it; 236 --prev_it; 237 return TscRange(prev_it, *m_decoded_thread); 238 } 239