LLDB  mainline
TraceIntelPT.h
Go to the documentation of this file.
1 //===-- TraceIntelPT.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_TRACEINTELPT_H
10 #define LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
11 
12 #include "TaskTimer.h"
13 #include "ThreadDecoder.h"
16 #include "lldb/Utility/FileSpec.h"
17 #include "lldb/lldb-types.h"
18 #include "llvm/Support/raw_ostream.h"
19 
20 namespace lldb_private {
21 namespace trace_intel_pt {
22 
23 class TraceIntelPT : public Trace {
24 public:
25  /// Properties to be used with the `settings` command.
26  class PluginProperties : public Properties {
27  public:
28  static ConstString GetSettingName();
29 
31 
32  ~PluginProperties() override = default;
33 
35 
37  };
38 
39  /// Return the global properties for this trace plug-in.
41 
42  void Dump(Stream *s) const override;
43 
44  llvm::Expected<FileSpec> SaveToDisk(FileSpec directory,
45  bool compact) override;
46 
47  ~TraceIntelPT() override = default;
48 
49  /// PluginInterface protocol
50  /// \{
51  llvm::StringRef GetPluginName() override { return GetPluginNameStatic(); }
52 
53  static void Initialize();
54 
55  static void Terminate();
56 
57  /// Create an instance of this class from a trace bundle.
58  ///
59  /// \param[in] trace_bundle_description
60  /// The description of the trace bundle. See \a Trace::FindPlugin.
61  ///
62  /// \param[in] bundle_dir
63  /// The path to the directory that contains the trace bundle.
64  ///
65  /// \param[in] debugger
66  /// The debugger instance where new Targets will be created as part of the
67  /// JSON data parsing.
68  ///
69  /// \return
70  /// A trace instance or an error in case of failures.
71  static llvm::Expected<lldb::TraceSP> CreateInstanceForTraceBundle(
72  const llvm::json::Value &trace_bundle_description,
73  llvm::StringRef bundle_dir, Debugger &debugger);
74 
75  static llvm::Expected<lldb::TraceSP>
77 
78  static llvm::StringRef GetPluginNameStatic() { return "intel-pt"; }
79 
80  static void DebuggerInitialize(Debugger &debugger);
81  /// \}
82 
83  lldb::CommandObjectSP
84  GetProcessTraceStartCommand(CommandInterpreter &interpreter) override;
85 
86  lldb::CommandObjectSP
87  GetThreadTraceStartCommand(CommandInterpreter &interpreter) override;
88 
89  llvm::StringRef GetSchema() override;
90 
91  llvm::Expected<lldb::TraceCursorSP> CreateNewCursor(Thread &thread) override;
92 
93  void DumpTraceInfo(Thread &thread, Stream &s, bool verbose,
94  bool json) override;
95 
96  llvm::Expected<llvm::Optional<uint64_t>> GetRawTraceSize(Thread &thread);
97 
99  llvm::StringRef json_response) override;
100 
101  bool IsTraced(lldb::tid_t tid) override;
102 
103  const char *GetStartConfigurationHelp() override;
104 
105  /// Start tracing a live process.
106  ///
107  /// More information on the parameters below can be found in the
108  /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
109  ///
110  /// \param[in] ipt_trace_size
111  /// Trace size per thread in bytes.
112  ///
113  /// \param[in] total_buffer_size_limit
114  /// Maximum total trace size per process in bytes.
115  ///
116  /// \param[in] enable_tsc
117  /// Whether to use enable TSC timestamps or not.
118  ///
119  /// \param[in] psb_period
120  /// This value defines the period in which PSB packets will be generated.
121  ///
122  /// \param[in] per_cpu_tracing
123  /// This value defines whether to have an intel pt trace buffer per thread
124  /// or per cpu core.
125  ///
126  /// \param[in] disable_cgroup_filtering
127  /// Disable the cgroup filtering that is automatically applied when doing
128  /// per cpu tracing.
129  ///
130  /// \return
131  /// \a llvm::Error::success if the operation was successful, or
132  /// \a llvm::Error otherwise.
133  llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit,
134  bool enable_tsc, llvm::Optional<uint64_t> psb_period,
135  bool m_per_cpu_tracing, bool disable_cgroup_filtering);
136 
137  /// \copydoc Trace::Start
139  StructuredData::ObjectSP()) override;
140 
141  /// Start tracing live threads.
142  ///
143  /// More information on the parameters below can be found in the
144  /// jLLDBTraceStart section in lldb/docs/lldb-gdb-remote.txt.
145  ///
146  /// \param[in] tids
147  /// Threads to trace.
148  ///
149  /// \param[in] ipt_trace_size
150  /// Trace size per thread or per cpu core in bytes.
151  ///
152  /// \param[in] enable_tsc
153  /// Whether to use enable TSC timestamps or not.
154  ///
155  /// \param[in] psb_period
156  /// This value defines the period in which PSB packets will be generated.
157  ///
158  /// \return
159  /// \a llvm::Error::success if the operation was successful, or
160  /// \a llvm::Error otherwise.
161  llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids, uint64_t ipt_trace_size,
162  bool enable_tsc, llvm::Optional<uint64_t> psb_period);
163 
164  /// \copydoc Trace::Start
165  llvm::Error Start(llvm::ArrayRef<lldb::tid_t> tids,
166  StructuredData::ObjectSP configuration =
167  StructuredData::ObjectSP()) override;
168 
169  /// See \a Trace::OnThreadBinaryDataRead().
171  OnBinaryDataReadCallback callback);
172 
173  /// Get or fetch the cpu information from, for example, /proc/cpuinfo.
174  llvm::Expected<pt_cpu> GetCPUInfo();
175 
176  /// Get or fetch the values used to convert to and from TSCs and nanos.
177  llvm::Optional<LinuxPerfZeroTscConversion> GetPerfZeroTscConversion();
178 
179  /// \return
180  /// The timer object for this trace.
181  TaskTimer &GetTimer();
182 
183  /// \return
184  /// The ScopedTaskTimer object for the given thread in this trace.
186 
187  /// \return
188  /// The global copedTaskTimer object for this trace.
190 
192 
193  enum class TraceMode { UserMode, KernelMode };
194 
196 
197 private:
199 
200  llvm::Expected<pt_cpu> GetCPUInfoForLiveProcess();
201 
202  /// Postmortem trace constructor
203  ///
204  /// \param[in] bundle_description
205  /// The definition file for the postmortem bundle.
206  ///
207  /// \param[in] traced_processes
208  /// The processes traced in the postmortem session.
209  ///
210  /// \param[in] trace_threads
211  /// The threads traced in the postmortem session. They must belong to the
212  /// processes mentioned above.
213  ///
214  /// \param[in] trace_mode
215  /// The tracing mode of the postmortem session.
216  ///
217  /// \return
218  /// A TraceIntelPT shared pointer instance.
219  /// \{
221  JSONTraceBundleDescription &bundle_description,
222  llvm::ArrayRef<lldb::ProcessSP> traced_processes,
223  llvm::ArrayRef<lldb::ThreadPostMortemTraceSP> traced_threads,
225 
226  /// This constructor is used by CreateInstanceForPostmortemTrace to get the
227  /// instance ready before using shared pointers, which is a limitation of C++.
228  TraceIntelPT(JSONTraceBundleDescription &bundle_description,
229  llvm::ArrayRef<lldb::ProcessSP> traced_processes,
231  /// \}
232 
233  /// Constructor for live processes
234  TraceIntelPT(Process &live_process)
235  : Trace(live_process), trace_mode(TraceMode::UserMode){};
236 
237  /// Decode the trace of the given thread that, i.e. recontruct the traced
238  /// instructions.
239  ///
240  /// \param[in] thread
241  /// If \a thread is a \a ThreadTrace, then its internal trace file will be
242  /// decoded. Live threads are not currently supported.
243  ///
244  /// \return
245  /// A \a DecodedThread shared pointer with the decoded instructions. Any
246  /// errors are embedded in the instruction list. An \a llvm::Error is
247  /// returned if the decoder couldn't be properly set up.
248  llvm::Expected<DecodedThreadSP> Decode(Thread &thread);
249 
250  /// \return
251  /// The lowest timestamp in nanoseconds in all traces if available, \a
252  /// llvm::None if all the traces were empty or no trace contained no
253  /// timing information, or an \a llvm::Error if it was not possible to set
254  /// up the decoder for some trace.
255  llvm::Expected<llvm::Optional<uint64_t>> FindBeginningOfTimeNanos();
256 
257  // Dump out trace info in JSON format
258  void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose);
259 
260  /// We package all the data that can change upon process stops to make sure
261  /// this contract is very visible.
262  /// This variable should only be accessed directly by constructores or live
263  /// process data refreshers.
264  struct Storage {
265  llvm::Optional<TraceIntelPTMultiCpuDecoder> multicpu_decoder;
266  /// These decoders are used for the non-per-cpu case
267  llvm::DenseMap<lldb::tid_t, std::unique_ptr<ThreadDecoder>> thread_decoders;
268  /// Helper variable used to track long running operations for telemetry.
270  /// It is provided by either a trace bundle or a live process to convert TSC
271  /// counters to and from nanos. It might not be available on all hosts.
272  llvm::Optional<LinuxPerfZeroTscConversion> tsc_conversion;
273  llvm::Optional<uint64_t> beginning_of_time_nanos;
275  } m_storage;
276 
277  /// It is provided by either a trace bundle or a live process' "cpuInfo"
278  /// binary data. We don't put it in the Storage because this variable doesn't
279  /// change.
280  llvm::Optional<pt_cpu> m_cpu_info;
281 
282  /// Get the storage after refreshing the data in the case of a live process.
284 
285  /// The tracing mode of post mortem trace.
287 };
288 
289 } // namespace trace_intel_pt
290 } // namespace lldb_private
291 
292 #endif // LLDB_SOURCE_PLUGINS_TRACE_INTEL_PT_TRACEINTELPT_H
lldb_private::trace_intel_pt::TraceIntelPT::Storage
We package all the data that can change upon process stops to make sure this contract is very visible...
Definition: TraceIntelPT.h:264
lldb_private::trace_intel_pt::TraceIntelPT::GetPluginName
llvm::StringRef GetPluginName() override
PluginInterface protocol.
Definition: TraceIntelPT.h:51
lldb_private::trace_intel_pt::TraceIntelPT::DumpTraceInfo
void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, bool json) override
Dump general info about a given thread's trace.
Definition: TraceIntelPT.cpp:243
lldb_private::TraceGetStateResponse
Definition: TraceGDBRemotePackets.h:132
lldb_private::Trace::OnBinaryDataReadCallback
std::function< llvm::Error(llvm::ArrayRef< uint8_t > data)> OnBinaryDataReadCallback
Definition: Trace.h:260
lldb_private::trace_intel_pt::TraceIntelPT::DebuggerInitialize
static void DebuggerInitialize(Debugger &debugger)
Definition: TraceIntelPT.cpp:85
lldb_private::trace_intel_pt::TraceIntelPT::Decode
llvm::Expected< DecodedThreadSP > Decode(Thread &thread)
Decode the trace of the given thread that, i.e.
Definition: TraceIntelPT.cpp:179
lldb_private::trace_intel_pt::TraceIntelPT::GetTimer
TaskTimer & GetTimer()
Definition: TraceIntelPT.cpp:737
lldb_private::Process
Definition: Process.h:338
lldb_private::trace_intel_pt::TraceIntelPT::GetSchema
llvm::StringRef GetSchema() override
Definition: TraceIntelPT.cpp:100
lldb_private::trace_intel_pt::TraceIntelPT
Definition: TraceIntelPT.h:23
lldb_private::trace_intel_pt::TraceIntelPT::CreateNewCursor
llvm::Expected< lldb::TraceCursorSP > CreateNewCursor(Thread &thread) override
Get a TraceCursor for the given thread's trace.
Definition: TraceIntelPT.cpp:230
lldb_private::trace_intel_pt::TraceIntelPT::Dump
void Dump(Stream *s) const override
Dump the trace data that this plug-in has access to.
Definition: TraceIntelPT.cpp:104
lldb_private::Stream
Definition: Stream.h:28
lldb_private::trace_intel_pt::TraceIntelPT::CreateInstanceForPostmortemTrace
static TraceIntelPTSP CreateInstanceForPostmortemTrace(JSONTraceBundleDescription &bundle_description, llvm::ArrayRef< lldb::ProcessSP > traced_processes, llvm::ArrayRef< lldb::ThreadPostMortemTraceSP > traced_threads, TraceMode trace_mode)
Postmortem trace constructor.
Definition: TraceIntelPT.cpp:130
lldb_private::trace_intel_pt::TraceIntelPT::CreateInstanceForLiveProcess
static llvm::Expected< lldb::TraceSP > CreateInstanceForLiveProcess(Process &process)
Definition: TraceIntelPT.cpp:118
lldb_private::trace_intel_pt::TraceIntelPT::Storage::thread_decoders
llvm::DenseMap< lldb::tid_t, std::unique_ptr< ThreadDecoder > > thread_decoders
These decoders are used for the non-per-cpu case.
Definition: TraceIntelPT.h:267
lldb_private::trace_intel_pt::TraceIntelPT::GetPerfZeroTscConversion
llvm::Optional< LinuxPerfZeroTscConversion > GetPerfZeroTscConversion()
Get or fetch the values used to convert to and from TSCs and nanos.
Definition: TraceIntelPT.cpp:548
lldb_private::trace_intel_pt::TraceIntelPT::Storage::beginning_of_time_nanos_calculated
bool beginning_of_time_nanos_calculated
Definition: TraceIntelPT.h:274
lldb_private::trace_intel_pt::TraceIntelPT::GetStartConfigurationHelp
const char * GetStartConfigurationHelp() override
Definition: TraceIntelPT.cpp:609
lldb_private::Properties
Definition: UserSettingsController.h:33
lldb_private::Trace
Definition: Trace.h:46
lldb_private::FileSpec
Definition: FileSpec.h:55
lldb_private::trace_intel_pt::TraceIntelPTBundleLoader
Definition: TraceIntelPTBundleLoader.h:20
lldb_private::trace_intel_pt::TraceIntelPT::Storage::beginning_of_time_nanos
llvm::Optional< uint64_t > beginning_of_time_nanos
Definition: TraceIntelPT.h:273
lldb_private::trace_intel_pt::ScopedTaskTimer
Class used to track the duration of long running tasks related to a single scope for reporting.
Definition: TaskTimer.h:24
lldb_private::trace_intel_pt::TraceIntelPT::DoRefreshLiveProcessState
llvm::Error DoRefreshLiveProcessState(TraceGetStateResponse state, llvm::StringRef json_response) override
Method to be overriden by the plug-in to refresh its own state.
Definition: TraceIntelPT.cpp:557
lldb_private::trace_intel_pt::TraceIntelPT::TraceMode
TraceMode
Definition: TraceIntelPT.h:193
lldb_private::Thread
Definition: Thread.h:61
lldb_private::StructuredData::ObjectSP
std::shared_ptr< Object > ObjectSP
Definition: StructuredData.h:59
lldb_private::trace_intel_pt::TraceIntelPT::trace_mode
TraceMode trace_mode
The tracing mode of post mortem trace.
Definition: TraceIntelPT.h:286
lldb_private::trace_intel_pt::TraceIntelPT::PluginProperties::PluginProperties
PluginProperties()
Definition: TraceIntelPT.cpp:55
lldb_private::trace_intel_pt::TraceIntelPT::TraceMode::KernelMode
@ KernelMode
lldb_private::ConstString
Definition: ConstString.h:39
lldb_private::trace_intel_pt::TraceIntelPT::GetProcessTraceStartCommand
lldb::CommandObjectSP GetProcessTraceStartCommand(CommandInterpreter &interpreter) override
Get the command handle for the "process trace start" command.
Definition: TraceIntelPT.cpp:32
lldb_private::trace_intel_pt::TraceIntelPT::CreateInstanceForTraceBundle
static llvm::Expected< lldb::TraceSP > CreateInstanceForTraceBundle(const llvm::json::Value &trace_bundle_description, llvm::StringRef bundle_dir, Debugger &debugger)
Create an instance of this class from a trace bundle.
Definition: TraceIntelPT.cpp:111
lldb_private::trace_intel_pt::TraceIntelPT::PluginProperties::GetInfiniteDecodingLoopVerificationThreshold
uint64_t GetInfiniteDecodingLoopVerificationThreshold()
Definition: TraceIntelPT.cpp:61
lldb_private::trace_intel_pt::TraceIntelPT::GetGlobalProperties
static PluginProperties & GetGlobalProperties()
Return the global properties for this trace plug-in.
Definition: TraceIntelPT.cpp:73
lldb_private::trace_intel_pt::TraceIntelPT::PluginProperties
Properties to be used with the settings command.
Definition: TraceIntelPT.h:26
lldb_private::trace_intel_pt::TraceIntelPT::Storage::tsc_conversion
llvm::Optional< LinuxPerfZeroTscConversion > tsc_conversion
It is provided by either a trace bundle or a live process to convert TSC counters to and from nanos.
Definition: TraceIntelPT.h:272
lldb_private::CommandInterpreter
Definition: CommandInterpreter.h:214
lldb_private::trace_intel_pt::TraceIntelPT::GetRawTraceSize
llvm::Expected< llvm::Optional< uint64_t > > GetRawTraceSize(Thread &thread)
Definition: TraceIntelPT.cpp:466
lldb_private::Debugger
Definition: Debugger.h:74
lldb_private::trace_intel_pt::TraceIntelPT::TraceIntelPT
TraceIntelPT(Process &live_process)
Constructor for live processes.
Definition: TraceIntelPT.h:234
lldb_private::trace_intel_pt::TraceIntelPTSP
std::shared_ptr< TraceIntelPT > TraceIntelPTSP
Definition: forward-declarations.h:20
lldb_private::trace_intel_pt::TraceIntelPT::TraceIntelPT
TraceIntelPT(JSONTraceBundleDescription &bundle_description, llvm::ArrayRef< lldb::ProcessSP > traced_processes, TraceMode trace_mode)
This constructor is used by CreateInstanceForPostmortemTrace to get the instance ready before using s...
lldb_private::trace_intel_pt::TraceIntelPT::PluginProperties::GetExtremelyLargeDecodingThreshold
uint64_t GetExtremelyLargeDecodingThreshold()
Definition: TraceIntelPT.cpp:67
lldb_private::trace_intel_pt::TraceIntelPT::IsTraced
bool IsTraced(lldb::tid_t tid) override
Check if a thread is currently traced by this object.
Definition: TraceIntelPT.cpp:598
lldb_private::trace_intel_pt::TraceIntelPT::GetThreadTimer
ScopedTaskTimer & GetThreadTimer(lldb::tid_t tid)
Definition: TraceIntelPT.cpp:739
TaskTimer.h
lldb_private::trace_intel_pt::TraceIntelPT::TraceMode::UserMode
@ UserMode
lldb-types.h
TraceIntelPTMultiCpuDecoder.h
lldb_private::trace_intel_pt::TraceIntelPT::GetThreadTraceStartCommand
lldb::CommandObjectSP GetThreadTraceStartCommand(CommandInterpreter &interpreter) override
Get the command handle for the "thread trace start" command.
Definition: TraceIntelPT.cpp:38
lldb_private::trace_intel_pt::TraceIntelPT::Storage::task_timer
TaskTimer task_timer
Helper variable used to track long running operations for telemetry.
Definition: TraceIntelPT.h:269
lldb_private::trace_intel_pt::TraceIntelPT::GetGlobalTimer
ScopedTaskTimer & GetGlobalTimer()
Definition: TraceIntelPT.cpp:743
lldb_private::trace_intel_pt::JSONTraceBundleDescription
Definition: TraceIntelPTJSONStructs.h:52
lldb_private::trace_intel_pt::TraceIntelPT::PluginProperties::~PluginProperties
~PluginProperties() override=default
lldb_private::trace_intel_pt::TraceIntelPT::GetTraceMode
TraceMode GetTraceMode()
Definition: TraceIntelPT.cpp:128
lldb_private::trace_intel_pt::TaskTimer
Class used to track the duration of long running tasks for reporting.
Definition: TaskTimer.h:60
lldb_private::trace_intel_pt::TraceIntelPT::~TraceIntelPT
~TraceIntelPT() override=default
lldb_private::trace_intel_pt::TraceIntelPT::GetCPUInfoForLiveProcess
llvm::Expected< pt_cpu > GetCPUInfoForLiveProcess()
Definition: TraceIntelPT.cpp:484
lldb_private::trace_intel_pt::TraceIntelPT::m_storage
struct lldb_private::trace_intel_pt::TraceIntelPT::Storage m_storage
lldb_private::trace_intel_pt::TraceIntelPT::Storage::multicpu_decoder
llvm::Optional< TraceIntelPTMultiCpuDecoder > multicpu_decoder
Definition: TraceIntelPT.h:265
ThreadDecoder.h
lldb_private::trace_intel_pt::TraceIntelPT::Terminate
static void Terminate()
Definition: TraceIntelPT.cpp:96
lldb_private
A class that represents a running process on the host machine.
Definition: SBCommandInterpreterRunOptions.h:16
lldb_private::trace_intel_pt::TraceIntelPT::m_cpu_info
llvm::Optional< pt_cpu > m_cpu_info
It is provided by either a trace bundle or a live process' "cpuInfo" binary data.
Definition: TraceIntelPT.h:280
lldb_private::trace_intel_pt::TraceIntelPT::Initialize
static void Initialize()
Definition: TraceIntelPT.cpp:78
Error
llvm::Error Error
Definition: UdtRecordCompleter.cpp:34
lldb_private::trace_intel_pt::TraceIntelPT::GetSharedPtr
TraceIntelPTSP GetSharedPtr()
Definition: TraceIntelPT.cpp:124
lldb_private::trace_intel_pt::TraceIntelPT::Start
llvm::Error Start(uint64_t ipt_trace_size, uint64_t total_buffer_size_limit, bool enable_tsc, llvm::Optional< uint64_t > psb_period, bool m_per_cpu_tracing, bool disable_cgroup_filtering)
Start tracing a live process.
FileSpec.h
lldb_private::trace_intel_pt::TraceIntelPT::GetCPUInfo
llvm::Expected< pt_cpu > GetCPUInfo()
Get or fetch the cpu information from, for example, /proc/cpuinfo.
Definition: TraceIntelPT.cpp:537
lldb_private::trace_intel_pt::TraceIntelPT::SaveToDisk
llvm::Expected< FileSpec > SaveToDisk(FileSpec directory, bool compact) override
Save the trace to the specified directory, which will be created if needed.
Definition: TraceIntelPT.cpp:106
lldb_private::trace_intel_pt::TraceIntelPT::GetPluginNameStatic
static llvm::StringRef GetPluginNameStatic()
Definition: TraceIntelPT.h:78
lldb_private::trace_intel_pt::TraceIntelPT::OnThreadBufferRead
llvm::Error OnThreadBufferRead(lldb::tid_t tid, OnBinaryDataReadCallback callback)
See Trace::OnThreadBinaryDataRead().
Definition: TraceIntelPT.cpp:732
lldb_private::trace_intel_pt::TraceIntelPT::FindBeginningOfTimeNanos
llvm::Expected< llvm::Optional< uint64_t > > FindBeginningOfTimeNanos()
Definition: TraceIntelPT.cpp:193
lldb_private::trace_intel_pt::TraceIntelPT::GetUpdatedStorage
Storage & GetUpdatedStorage()
Get the storage after refreshing the data in the case of a live process.
Definition: TraceIntelPT.cpp:552
lldb_private::trace_intel_pt::TraceIntelPT::PluginProperties::GetSettingName
static ConstString GetSettingName()
Definition: TraceIntelPT.cpp:51
TraceIntelPTBundleLoader.h
lldb_private::trace_intel_pt::TraceIntelPT::DumpTraceInfoAsJson
void DumpTraceInfoAsJson(Thread &thread, Stream &s, bool verbose)
Definition: TraceIntelPT.cpp:354
lldb::tid_t
uint64_t tid_t
Definition: lldb-types.h:86