LLDB  mainline
DecodedThread.h
Go to the documentation of this file.
1 //===-- DecodedThread.h -----------------------------------------*- C++ -*-===//
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 #ifndef LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
10 #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
11 
12 #include "intel-pt.h"
13 #include "lldb/Target/Trace.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/Error.h"
17 #include <utility>
18 #include <vector>
19 
20 namespace lldb_private {
21 namespace trace_intel_pt {
22 
23 /// Class for representing a libipt decoding error.
24 class IntelPTError : public llvm::ErrorInfo<IntelPTError> {
25 public:
26  static char ID;
27 
28  /// \param[in] libipt_error_code
29  /// Negative number returned by libipt when decoding the trace and
30  /// signaling errors.
31  ///
32  /// \param[in] address
33  /// Optional instruction address. When decoding an individual instruction,
34  /// its address might be available in the \a pt_insn object, and should be
35  /// passed to this constructor. Other errors don't have an associated
36  /// address.
37  IntelPTError(int libipt_error_code,
39 
40  std::error_code convertToErrorCode() const override {
41  return llvm::errc::not_supported;
42  }
43 
44  int GetLibiptErrorCode() const { return m_libipt_error_code; }
45 
46  void log(llvm::raw_ostream &OS) const override;
47 
48 private:
51 };
52 
53 /// \class DecodedThread
54 /// Class holding the instructions and function call hierarchy obtained from
55 /// decoding a trace, as well as a position cursor used when reverse debugging
56 /// the trace.
57 ///
58 /// Each decoded thread contains a cursor to the current position the user is
59 /// stopped at. See \a Trace::GetCursorPosition for more information.
60 class DecodedThread : public std::enable_shared_from_this<DecodedThread> {
61 public:
62  using TSC = uint64_t;
63 
64  // Struct holding counts for libipts errors;
66  // libipt error -> count
67  llvm::DenseMap<const char *, int> libipt_errors_counts;
68  size_t total_count = 0;
69 
70  void RecordError(int libipt_error_code);
71  };
72 
73  /// A structure that represents a maximal range of trace items associated to
74  /// the same TSC value.
75  struct TSCRange {
77  /// Number of trace items in this range.
78  uint64_t items_count;
79  /// Index of the first trace item in this range.
80  uint64_t first_item_index;
81 
82  /// \return
83  /// \b true if and only if the given \p item_index is covered by this
84  /// range.
85  bool InRange(uint64_t item_index) const;
86  };
87 
88  /// A structure that represents a maximal range of trace items associated to
89  /// the same non-interpolated timestamps in nanoseconds.
91  /// The nanoseconds value for this range.
92  uint64_t nanos;
93  /// The corresponding TSC value for this range.
95  /// A nullable pointer to the next range.
97  /// Number of trace items in this range.
98  uint64_t items_count;
99  /// Index of the first trace item in this range.
101 
102  /// Calculate an interpolated timestamp in nanoseconds for the given item
103  /// index. It's guaranteed that two different item indices will produce
104  /// different interpolated values.
105  ///
106  /// \param[in] item_index
107  /// The index of the item whose timestamp will be estimated. It has to be
108  /// part of this range.
109  ///
110  /// \param[in] beginning_of_time_nanos
111  /// The timestamp at which tracing started.
112  ///
113  /// \param[in] tsc_conversion
114  /// The tsc -> nanos conversion utility
115  ///
116  /// \return
117  /// An interpolated timestamp value for the given trace item.
118  double
119  GetInterpolatedTime(uint64_t item_index, uint64_t beginning_of_time_nanos,
120  const LinuxPerfZeroTscConversion &tsc_conversion) const;
121 
122  /// \return
123  /// \b true if and only if the given \p item_index is covered by this
124  /// range.
125  bool InRange(uint64_t item_index) const;
126  };
127 
128  // Struct holding counts for events;
129  struct EventsStats {
130  /// A count for each individual event kind. We use an unordered map instead
131  /// of a DenseMap because DenseMap can't understand enums.
132  std::unordered_map<lldb::TraceEvent, size_t> events_counts;
133  size_t total_count = 0;
134 
135  void RecordEvent(lldb::TraceEvent event);
136  };
137 
139  lldb::ThreadSP thread_sp,
140  const llvm::Optional<LinuxPerfZeroTscConversion> &tsc_conversion);
141 
142  /// Get the total number of instruction, errors and events from the decoded
143  /// trace.
144  uint64_t GetItemsCount() const;
145 
146  /// \return
147  /// The error associated with a given trace item.
148  const char *GetErrorByIndex(uint64_t item_index) const;
149 
150  /// \return
151  /// The trace item kind given an item index.
152  lldb::TraceItemKind GetItemKindByIndex(uint64_t item_index) const;
153 
154  /// \return
155  /// The underlying event type for the given trace item index.
156  lldb::TraceEvent GetEventByIndex(int item_index) const;
157 
158  /// Get the most recent CPU id before or at the given trace item index.
159  ///
160  /// \param[in] item_index
161  /// The trace item index to compare with.
162  ///
163  /// \return
164  /// The requested cpu id, or \a LLDB_INVALID_CPU_ID if not available.
165  lldb::cpu_id_t GetCPUByIndex(uint64_t item_index) const;
166 
167  /// \return
168  /// The PSB offset associated with the given item index.
169  lldb::addr_t GetSyncPointOffsetByIndex(uint64_t item_index) const;
170 
171  /// Get a maximal range of trace items that include the given \p item_index
172  /// that have the same TSC value.
173  ///
174  /// \param[in] item_index
175  /// The trace item index to compare with.
176  ///
177  /// \return
178  /// The requested TSC range, or \a llvm::None if not available.
179  llvm::Optional<DecodedThread::TSCRange>
180  GetTSCRangeByIndex(uint64_t item_index) const;
181 
182  /// Get a maximal range of trace items that include the given \p item_index
183  /// that have the same nanoseconds timestamp without interpolation.
184  ///
185  /// \param[in] item_index
186  /// The trace item index to compare with.
187  ///
188  /// \return
189  /// The requested nanoseconds range, or \a llvm::None if not available.
190  llvm::Optional<DecodedThread::NanosecondsRange>
191  GetNanosecondsRangeByIndex(uint64_t item_index);
192 
193  /// \return
194  /// The load address of the instruction at the given index.
195  lldb::addr_t GetInstructionLoadAddress(uint64_t item_index) const;
196 
197  /// Return an object with statistics of the trace events that happened.
198  ///
199  /// \return
200  /// The stats object of all the events.
201  const EventsStats &GetEventsStats() const;
202 
203  /// The approximate size in bytes used by this instance,
204  /// including all the already decoded instructions.
205  size_t CalculateApproximateMemoryUsage() const;
206 
207  lldb::ThreadSP GetThread();
208 
209  /// Notify this object that a new tsc has been seen.
210  /// If this a new TSC, an event will be created.
211  void NotifyTsc(TSC tsc);
212 
213  /// Notify this object that a CPU has been seen.
214  /// If this a new CPU, an event will be created.
215  void NotifyCPU(lldb::cpu_id_t cpu_id);
216 
217  /// Notify this object that a new PSB has been seen.
218  void NotifySyncPoint(lldb::addr_t psb_offset);
219 
220  /// Append a decoding error.
221  void AppendError(const IntelPTError &error);
222 
223  /// Append a custom decoding.
224  void AppendCustomError(llvm::StringRef error);
225 
226  /// Append an event.
228 
229  /// Append an instruction.
230  void AppendInstruction(const pt_insn &insn);
231 
232 private:
233  /// When adding new members to this class, make sure
234  /// to update \a CalculateApproximateMemoryUsage() accordingly.
235  lldb::ThreadSP m_thread_sp;
236 
237  /// We use a union to optimize the memory usage for the different kinds of
238  /// trace items.
240  /// The load addresses of this item if it's an instruction.
241  uint64_t load_address;
242 
243  /// The event kind of this item if it's an event
245 
246  /// The string message of this item if it's an error
247  const char *error;
248  };
249 
250  /// Create a new trace item.
251  ///
252  /// \return
253  /// The index of the new item.
255 
256  /// Most of the trace data is stored here.
257  std::vector<TraceItemStorage> m_item_data;
258  /// The TraceItemKind for each trace item encoded as uint8_t. We don't include
259  /// it in TraceItemStorage to avoid padding.
260  std::vector<uint8_t> m_item_kinds;
261 
262  /// This map contains the TSCs of the decoded trace items. It maps
263  /// `item index -> TSC`, where `item index` is the first index
264  /// at which the mapped TSC first appears. We use this representation because
265  /// TSCs are sporadic and we can think of them as ranges.
266  std::map<uint64_t, TSCRange> m_tscs;
267  /// This is the chronologically last TSC that has been added.
268  llvm::Optional<std::map<uint64_t, TSCRange>::iterator> m_last_tsc =
269  llvm::None;
270  /// This map contains the non-interpolated nanoseconds timestamps of the
271  /// decoded trace items. It maps `item index -> nanoseconds`, where `item
272  /// index` is the first index at which the mapped nanoseconds first appears.
273  /// We use this representation because timestamps are sporadic and we think of
274  /// them as ranges.
275  std::map<uint64_t, NanosecondsRange> m_nanoseconds;
276  llvm::Optional<std::map<uint64_t, NanosecondsRange>::iterator>
277  m_last_nanoseconds = llvm::None;
278 
279  // The cpu information is stored as a map. It maps `item index -> CPU`.
280  // A CPU is associated with the next instructions that follow until the next
281  // cpu is seen.
282  std::map<uint64_t, lldb::cpu_id_t> m_cpus;
283  /// This is the chronologically last CPU ID.
284  llvm::Optional<uint64_t> m_last_cpu = llvm::None;
285 
286  // The PSB offsets are stored as a map. It maps `item index -> psb offset`.
287  llvm::DenseMap<uint64_t, lldb::addr_t> m_psb_offsets;
288 
289  /// TSC -> nanos conversion utility.
290  llvm::Optional<LinuxPerfZeroTscConversion> m_tsc_conversion;
291 
292  /// Statistics of all tracing events.
294  /// Total amount of time spent decoding.
295  std::chrono::milliseconds m_total_decoding_time{0};
296 };
297 
298 using DecodedThreadSP = std::shared_ptr<DecodedThread>;
299 
300 } // namespace trace_intel_pt
301 } // namespace lldb_private
302 
303 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_DECODEDTHREAD_H
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::first_item_index
uint64_t first_item_index
Index of the first trace item in this range.
Definition: DecodedThread.h:100
lldb::TraceItemKind
TraceItemKind
Definition: lldb-enumerations.h:1186
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::GetInterpolatedTime
double GetInterpolatedTime(uint64_t item_index, uint64_t beginning_of_time_nanos, const LinuxPerfZeroTscConversion &tsc_conversion) const
Calculate an interpolated timestamp in nanoseconds for the given item index.
Definition: DecodedThread.cpp:42
lldb_private::trace_intel_pt::IntelPTError::ID
static char ID
Definition: DecodedThread.h:26
lldb_private::trace_intel_pt::DecodedThread::GetNanosecondsRangeByIndex
llvm::Optional< DecodedThread::NanosecondsRange > GetNanosecondsRangeByIndex(uint64_t item_index)
Get a maximal range of trace items that include the given item_index that have the same nanoseconds t...
Definition: DecodedThread.cpp:166
lldb_private::trace_intel_pt::DecodedThread::EventsStats::total_count
size_t total_count
Definition: DecodedThread.h:133
lldb_private::trace_intel_pt::DecodedThread::DecodedThread
DecodedThread(lldb::ThreadSP thread_sp, const llvm::Optional< LinuxPerfZeroTscConversion > &tsc_conversion)
Definition: DecodedThread.cpp:219
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::libipt_errors_counts
llvm::DenseMap< const char *, int > libipt_errors_counts
Definition: DecodedThread.h:67
lldb_private::trace_intel_pt::IntelPTError::m_libipt_error_code
int m_libipt_error_code
Definition: DecodedThread.h:49
lldb_private::trace_intel_pt::DecodedThread::CreateNewTraceItem
DecodedThread::TraceItemStorage & CreateNewTraceItem(lldb::TraceItemKind kind)
Create a new trace item.
Definition: DecodedThread.cpp:102
lldb_private::trace_intel_pt::IntelPTError::m_address
lldb::addr_t m_address
Definition: DecodedThread.h:50
lldb_private::trace_intel_pt::DecodedThread::AppendEvent
void AppendEvent(lldb::TraceEvent)
Append an event.
Definition: DecodedThread.cpp:173
lldb_private::trace_intel_pt::DecodedThread::GetCPUByIndex
lldb::cpu_id_t GetCPUByIndex(uint64_t item_index) const
Get the most recent CPU id before or at the given trace item index.
Definition: DecodedThread.cpp:152
lldb_private::trace_intel_pt::DecodedThread::NotifySyncPoint
void NotifySyncPoint(lldb::addr_t psb_offset)
Notify this object that a new PSB has been seen.
Definition: DecodedThread.cpp:112
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats
Definition: DecodedThread.h:65
Trace.h
lldb_private::trace_intel_pt::DecodedThread::TSCRange::tsc
TSC tsc
Definition: DecodedThread.h:76
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::tsc
TSC tsc
The corresponding TSC value for this range.
Definition: DecodedThread.h:94
lldb::addr_t
uint64_t addr_t
Definition: lldb-types.h:83
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage
We use a union to optimize the memory usage for the different kinds of trace items.
Definition: DecodedThread.h:239
lldb_private::trace_intel_pt::DecodedThread::GetItemsCount
uint64_t GetItemsCount() const
Get the total number of instruction, errors and events from the decoded trace.
Definition: DecodedThread.cpp:87
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::RecordError
void RecordError(int libipt_error_code)
Definition: DecodedThread.cpp:196
lldb_private::trace_intel_pt::IntelPTError::GetLibiptErrorCode
int GetLibiptErrorCode() const
Definition: DecodedThread.h:44
lldb_private::trace_intel_pt::DecodedThread::EventsStats::events_counts
std::unordered_map< lldb::TraceEvent, size_t > events_counts
A count for each individual event kind.
Definition: DecodedThread.h:132
lldb_private::trace_intel_pt::DecodedThread::m_last_nanoseconds
llvm::Optional< std::map< uint64_t, NanosecondsRange >::iterator > m_last_nanoseconds
Definition: DecodedThread.h:277
lldb_private::trace_intel_pt::DecodedThread::GetInstructionLoadAddress
lldb::addr_t GetInstructionLoadAddress(uint64_t item_index) const
Definition: DecodedThread.cpp:90
error
static llvm::raw_ostream & error(Stream &strm)
Definition: CommandReturnObject.cpp:17
lldb::TraceEvent
TraceEvent
Events that might happen during a trace session.
Definition: lldb-enumerations.h:1170
lldb_private::trace_intel_pt::DecodedThread::TSCRange::items_count
uint64_t items_count
Number of trace items in this range.
Definition: DecodedThread.h:78
lldb_private::trace_intel_pt::DecodedThread::TSCRange::first_item_index
uint64_t first_item_index
Index of the first trace item in this range.
Definition: DecodedThread.h:80
lldb_private::trace_intel_pt::IntelPTError::IntelPTError
IntelPTError(int libipt_error_code, lldb::addr_t address=LLDB_INVALID_ADDRESS)
Definition: DecodedThread.cpp:21
TraceIntelPTGDBRemotePackets.h
lldb_private::trace_intel_pt::DecodedThread::m_item_data
std::vector< TraceItemStorage > m_item_data
Most of the trace data is stored here.
Definition: DecodedThread.h:257
lldb_private::trace_intel_pt::DecodedThread::AppendError
void AppendError(const IntelPTError &error)
Append a decoding error.
Definition: DecodedThread.cpp:182
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage::error
const char * error
The string message of this item if it's an error.
Definition: DecodedThread.h:247
lldb_private::trace_intel_pt::DecodedThread::GetEventsStats
const EventsStats & GetEventsStats() const
Return an object with statistics of the trace events that happened.
Definition: DecodedThread.cpp:201
lldb_private::trace_intel_pt::DecodedThread::m_total_decoding_time
std::chrono::milliseconds m_total_decoding_time
Total amount of time spent decoding.
Definition: DecodedThread.h:295
lldb_private::trace_intel_pt::DecodedThread::AppendInstruction
void AppendInstruction(const pt_insn &insn)
Append an instruction.
Definition: DecodedThread.cpp:178
lldb_private::trace_intel_pt::DecodedThread::LibiptErrorsStats::total_count
size_t total_count
Definition: DecodedThread.h:68
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::InRange
bool InRange(uint64_t item_index) const
Definition: DecodedThread.cpp:37
lldb_private::trace_intel_pt::IntelPTError::convertToErrorCode
std::error_code convertToErrorCode() const override
Definition: DecodedThread.h:40
lldb_private::trace_intel_pt::DecodedThread::TSC
uint64_t TSC
Definition: DecodedThread.h:62
lldb_private::trace_intel_pt::DecodedThread::m_last_tsc
llvm::Optional< std::map< uint64_t, TSCRange >::iterator > m_last_tsc
This is the chronologically last TSC that has been added.
Definition: DecodedThread.h:268
lldb_private::trace_intel_pt::DecodedThread::GetItemKindByIndex
lldb::TraceItemKind GetItemKindByIndex(uint64_t item_index) const
Definition: DecodedThread.cpp:211
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::items_count
uint64_t items_count
Number of trace items in this range.
Definition: DecodedThread.h:98
lldb_private::trace_intel_pt::DecodedThread::TSCRange::InRange
bool InRange(uint64_t item_index) const
Definition: DecodedThread.cpp:32
lldb_private::trace_intel_pt::IntelPTError
Class for representing a libipt decoding error.
Definition: DecodedThread.h:24
lldb_private::trace_intel_pt::IntelPTError::log
void log(llvm::raw_ostream &OS) const override
Definition: DecodedThread.cpp:26
uint32_t
lldb_private::trace_intel_pt::DecodedThread::NotifyTsc
void NotifyTsc(TSC tsc)
Notify this object that a new tsc has been seen.
Definition: DecodedThread.cpp:117
lldb_private::trace_intel_pt::DecodedThread::m_thread_sp
lldb::ThreadSP m_thread_sp
When adding new members to this class, make sure to update CalculateApproximateMemoryUsage() accordin...
Definition: DecodedThread.h:235
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage::event
lldb::TraceEvent event
The event kind of this item if it's an event.
Definition: DecodedThread.h:244
lldb_private::trace_intel_pt::DecodedThread::EventsStats::RecordEvent
void RecordEvent(lldb::TraceEvent event)
Definition: DecodedThread.cpp:205
lldb_private::LinuxPerfZeroTscConversion
jLLDBTraceGetState gdb-remote packet
Definition: TraceIntelPTGDBRemotePackets.h:89
lldb_private::trace_intel_pt::DecodedThread::m_tsc_conversion
llvm::Optional< LinuxPerfZeroTscConversion > m_tsc_conversion
TSC -> nanos conversion utility.
Definition: DecodedThread.h:290
lldb_private::trace_intel_pt::DecodedThread::CalculateApproximateMemoryUsage
size_t CalculateApproximateMemoryUsage() const
The approximate size in bytes used by this instance, including all the already decoded instructions.
Definition: DecodedThread.cpp:224
lldb_private::trace_intel_pt::DecodedThread::GetTSCRangeByIndex
llvm::Optional< DecodedThread::TSCRange > GetTSCRangeByIndex(uint64_t item_index) const
Get a maximal range of trace items that include the given item_index that have the same TSC value.
Definition: DecodedThread.cpp:158
lldb_private::trace_intel_pt::DecodedThread::EventsStats
Definition: DecodedThread.h:129
lldb_private::trace_intel_pt::DecodedThread::GetThread
lldb::ThreadSP GetThread()
Definition: DecodedThread.cpp:99
LLDB_INVALID_ADDRESS
#define LLDB_INVALID_ADDRESS
Definition: lldb-defines.h:74
lldb_private::trace_intel_pt::DecodedThread::NotifyCPU
void NotifyCPU(lldb::cpu_id_t cpu_id)
Notify this object that a CPU has been seen.
Definition: DecodedThread.cpp:144
lldb_private::trace_intel_pt::DecodedThread::m_cpus
std::map< uint64_t, lldb::cpu_id_t > m_cpus
Definition: DecodedThread.h:282
lldb_private::trace_intel_pt::DecodedThread::m_psb_offsets
llvm::DenseMap< uint64_t, lldb::addr_t > m_psb_offsets
Definition: DecodedThread.h:287
lldb_private::trace_intel_pt::DecodedThreadSP
std::shared_ptr< DecodedThread > DecodedThreadSP
Definition: DecodedThread.h:298
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::next_range
NanosecondsRange * next_range
A nullable pointer to the next range.
Definition: DecodedThread.h:96
lldb_private::trace_intel_pt::DecodedThread::GetSyncPointOffsetByIndex
lldb::addr_t GetSyncPointOffsetByIndex(uint64_t item_index) const
Definition: DecodedThread.cpp:95
lldb_private::trace_intel_pt::DecodedThread::m_tscs
std::map< uint64_t, TSCRange > m_tscs
This map contains the TSCs of the decoded trace items.
Definition: DecodedThread.h:266
lldb_private::trace_intel_pt::DecodedThread::m_nanoseconds
std::map< uint64_t, NanosecondsRange > m_nanoseconds
This map contains the non-interpolated nanoseconds timestamps of the decoded trace items.
Definition: DecodedThread.h:275
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::trace_intel_pt::DecodedThread
Definition: DecodedThread.h:60
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange
A structure that represents a maximal range of trace items associated to the same non-interpolated ti...
Definition: DecodedThread.h:90
lldb_private::trace_intel_pt::DecodedThread::m_item_kinds
std::vector< uint8_t > m_item_kinds
The TraceItemKind for each trace item encoded as uint8_t.
Definition: DecodedThread.h:260
lldb_private::trace_intel_pt::DecodedThread::TSCRange
A structure that represents a maximal range of trace items associated to the same TSC value.
Definition: DecodedThread.h:75
lldb_private::trace_intel_pt::DecodedThread::AppendCustomError
void AppendCustomError(llvm::StringRef error)
Append a custom decoding.
Definition: DecodedThread.cpp:187
lldb_private::trace_intel_pt::DecodedThread::GetErrorByIndex
const char * GetErrorByIndex(uint64_t item_index) const
Definition: DecodedThread.cpp:215
lldb_private::trace_intel_pt::DecodedThread::TraceItemStorage::load_address
uint64_t load_address
The load addresses of this item if it's an instruction.
Definition: DecodedThread.h:241
lldb_private::trace_intel_pt::DecodedThread::NanosecondsRange::nanos
uint64_t nanos
The nanoseconds value for this range.
Definition: DecodedThread.h:92
lldb_private::trace_intel_pt::DecodedThread::m_last_cpu
llvm::Optional< uint64_t > m_last_cpu
This is the chronologically last CPU ID.
Definition: DecodedThread.h:284
lldb_private::trace_intel_pt::DecodedThread::m_events_stats
EventsStats m_events_stats
Statistics of all tracing events.
Definition: DecodedThread.h:293
lldb_private::trace_intel_pt::DecodedThread::GetEventByIndex
lldb::TraceEvent GetEventByIndex(int item_index) const
Definition: DecodedThread.cpp:192