|
|
|||
File indexing completed on 2026-05-10 08:42:56
0001 //===-- Trace.h -------------------------------------------------*- C++ -*-===// 0002 // 0003 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 0004 // See https://llvm.org/LICENSE.txt for license information. 0005 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 0006 // 0007 //===----------------------------------------------------------------------===// 0008 0009 #ifndef LLDB_TARGET_TRACE_H 0010 #define LLDB_TARGET_TRACE_H 0011 0012 #include <optional> 0013 #include <unordered_map> 0014 0015 #include "llvm/Support/JSON.h" 0016 0017 #include "lldb/Core/PluginInterface.h" 0018 #include "lldb/Target/Thread.h" 0019 #include "lldb/Target/TraceCursor.h" 0020 #include "lldb/Utility/ArchSpec.h" 0021 #include "lldb/Utility/TraceGDBRemotePackets.h" 0022 #include "lldb/Utility/UnimplementedError.h" 0023 #include "lldb/lldb-private.h" 0024 #include "lldb/lldb-types.h" 0025 0026 namespace lldb_private { 0027 0028 /// \class Trace Trace.h "lldb/Target/Trace.h" 0029 /// A plug-in interface definition class for trace information. 0030 /// 0031 /// Trace plug-ins allow processor trace information to be loaded into LLDB so 0032 /// that the data can be dumped, used for reverse and forward stepping to allow 0033 /// introspection into the reason your process crashed or found its way to its 0034 /// current state. 0035 /// 0036 /// Trace information can be loaded into a target without a process to allow 0037 /// introspection of the trace information during post mortem analysis, such as 0038 /// when loading core files. 0039 /// 0040 /// Processor trace information can also be fetched through the process 0041 /// interfaces during a live debug session if your process supports gathering 0042 /// this information. 0043 /// 0044 /// In order to support live tracing, the name of the plug-in should match the 0045 /// name of the tracing type returned by the gdb-remote packet 0046 /// \a jLLDBTraceSupported. 0047 class Trace : public PluginInterface, 0048 public std::enable_shared_from_this<Trace> { 0049 public: 0050 /// Dump the trace data that this plug-in has access to. 0051 /// 0052 /// This function will dump all of the trace data for all threads in a user 0053 /// readable format. Options for dumping can be added as this API is iterated 0054 /// on. 0055 /// 0056 /// \param[in] s 0057 /// A stream object to dump the information to. 0058 virtual void Dump(Stream *s) const = 0; 0059 0060 /// Save the trace to the specified directory, which will be created if 0061 /// needed. This will also create a file \a <directory>/trace.json with the 0062 /// main properties of the trace session, along with others files which 0063 /// contain the actual trace data. The trace.json file can be used later as 0064 /// input for the "trace load" command to load the trace in LLDB. 0065 /// 0066 /// \param[in] directory 0067 /// The directory where the trace files will be saved. 0068 /// 0069 /// \param[in] compact 0070 /// Try not to save to disk information irrelevant to the traced processes. 0071 /// Each trace plug-in implements this in a different fashion. 0072 /// 0073 /// \return 0074 /// A \a FileSpec pointing to the bundle description file, or an \a 0075 /// llvm::Error otherwise. 0076 virtual llvm::Expected<FileSpec> SaveToDisk(FileSpec directory, 0077 bool compact) = 0; 0078 0079 /// Find a trace plug-in using JSON data. 0080 /// 0081 /// When loading trace data from disk, the information for the trace data 0082 /// can be contained in multiple files and require plug-in specific 0083 /// information about the CPU. Using data like JSON provides an 0084 /// easy way to specify all of the settings and information that we will need 0085 /// to load trace data into LLDB. This structured data can include: 0086 /// - The plug-in name (this allows a specific plug-in to be selected) 0087 /// - Architecture or target triple 0088 /// - one or more paths to the trace data file on disk 0089 /// - cpu trace data 0090 /// - thread events or related information 0091 /// - shared library load information to use for this trace data that 0092 /// allows a target to be created so the trace information can be 0093 /// symbolicated so that the trace information can be displayed to the 0094 /// user 0095 /// - shared library path 0096 /// - load address 0097 /// - information on how to fetch the shared library 0098 /// - path to locally cached file on disk 0099 /// - URL to download the file 0100 /// - Any information needed to load the trace file 0101 /// - CPU information 0102 /// - Custom plug-in information needed to decode the trace information 0103 /// correctly. 0104 /// 0105 /// \param[in] debugger 0106 /// The debugger instance where new Targets will be created as part of the 0107 /// JSON data parsing. 0108 /// 0109 /// \param[in] bundle_description 0110 /// The trace bundle description object describing the trace session. 0111 /// 0112 /// \param[in] bundle_dir 0113 /// The path to the directory that contains the trace bundle. 0114 static llvm::Expected<lldb::TraceSP> 0115 FindPluginForPostMortemProcess(Debugger &debugger, 0116 const llvm::json::Value &bundle_description, 0117 llvm::StringRef session_file_dir); 0118 0119 /// Find a trace plug-in to trace a live process. 0120 /// 0121 /// \param[in] plugin_name 0122 /// Plug-in name to search. 0123 /// 0124 /// \param[in] process 0125 /// Live process to trace. 0126 /// 0127 /// \return 0128 /// A \a TraceSP instance, or an \a llvm::Error if the plug-in name 0129 /// doesn't match any registered plug-ins or tracing couldn't be 0130 /// started. 0131 static llvm::Expected<lldb::TraceSP> 0132 FindPluginForLiveProcess(llvm::StringRef plugin_name, Process &process); 0133 0134 /// Get the schema of a Trace plug-in given its name. 0135 /// 0136 /// \param[in] plugin_name 0137 /// Name of the trace plugin. 0138 static llvm::Expected<llvm::StringRef> 0139 FindPluginSchema(llvm::StringRef plugin_name); 0140 0141 /// Load a trace from a trace description file and create Targets, 0142 /// Processes and Threads based on the contents of such file. 0143 /// 0144 /// \param[in] debugger 0145 /// The debugger instance where new Targets will be created as part of the 0146 /// JSON data parsing. 0147 /// 0148 /// \param[in] trace_description_file 0149 /// The file containing the necessary information to load the trace. 0150 /// 0151 /// \return 0152 /// A \a TraceSP instance, or an \a llvm::Error if loading the trace 0153 /// fails. 0154 static llvm::Expected<lldb::TraceSP> 0155 LoadPostMortemTraceFromFile(Debugger &debugger, 0156 const FileSpec &trace_description_file); 0157 0158 /// Get the command handle for the "process trace start" command. 0159 virtual lldb::CommandObjectSP 0160 GetProcessTraceStartCommand(CommandInterpreter &interpreter) = 0; 0161 0162 /// Get the command handle for the "thread trace start" command. 0163 virtual lldb::CommandObjectSP 0164 GetThreadTraceStartCommand(CommandInterpreter &interpreter) = 0; 0165 0166 /// \return 0167 /// The JSON schema of this Trace plug-in. 0168 virtual llvm::StringRef GetSchema() = 0; 0169 0170 /// Get a \a TraceCursor for the given thread's trace. 0171 /// 0172 /// \return 0173 /// A \a TraceCursorSP. If the thread is not traced or its trace 0174 /// information failed to load, an \a llvm::Error is returned. 0175 virtual llvm::Expected<lldb::TraceCursorSP> 0176 CreateNewCursor(Thread &thread) = 0; 0177 0178 /// Dump general info about a given thread's trace. Each Trace plug-in 0179 /// decides which data to show. 0180 /// 0181 /// \param[in] thread 0182 /// The thread that owns the trace in question. 0183 /// 0184 /// \param[in] s 0185 /// The stream object where the info will be printed printed. 0186 /// 0187 /// \param[in] verbose 0188 /// If \b true, print detailed info 0189 /// If \b false, print compact info 0190 virtual void DumpTraceInfo(Thread &thread, Stream &s, bool verbose, 0191 bool json) = 0; 0192 0193 /// Check if a thread is currently traced by this object. 0194 /// 0195 /// \param[in] tid 0196 /// The id of the thread in question. 0197 /// 0198 /// \return 0199 /// \b true if the thread is traced by this instance, \b false otherwise. 0200 virtual bool IsTraced(lldb::tid_t tid) = 0; 0201 0202 /// \return 0203 /// A description of the parameters to use for the \a Trace::Start method. 0204 virtual const char *GetStartConfigurationHelp() = 0; 0205 0206 /// Start tracing a live process. 0207 /// 0208 /// \param[in] configuration 0209 /// See \a SBTrace::Start(const lldb::SBStructuredData &) for more 0210 /// information. 0211 /// 0212 /// \return 0213 /// \a llvm::Error::success if the operation was successful, or 0214 /// \a llvm::Error otherwise. 0215 virtual llvm::Error Start( 0216 StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0; 0217 0218 /// Start tracing live threads. 0219 /// 0220 /// \param[in] tids 0221 /// Threads to trace. This method tries to trace as many threads as 0222 /// possible. 0223 /// 0224 /// \param[in] configuration 0225 /// See \a SBTrace::Start(const lldb::SBThread &, const 0226 /// lldb::SBStructuredData &) for more information. 0227 /// 0228 /// \return 0229 /// \a llvm::Error::success if the operation was successful, or 0230 /// \a llvm::Error otherwise. 0231 virtual llvm::Error Start( 0232 llvm::ArrayRef<lldb::tid_t> tids, 0233 StructuredData::ObjectSP configuration = StructuredData::ObjectSP()) = 0; 0234 0235 /// Stop tracing live threads. 0236 /// 0237 /// \param[in] tids 0238 /// The threads to stop tracing on. 0239 /// 0240 /// \return 0241 /// \a llvm::Error::success if the operation was successful, or 0242 /// \a llvm::Error otherwise. 0243 llvm::Error Stop(llvm::ArrayRef<lldb::tid_t> tids); 0244 0245 /// Stop tracing all current and future threads of a live process. 0246 /// 0247 /// \param[in] request 0248 /// The information determining which threads or process to stop tracing. 0249 /// 0250 /// \return 0251 /// \a llvm::Error::success if the operation was successful, or 0252 /// \a llvm::Error otherwise. 0253 llvm::Error Stop(); 0254 0255 /// \return 0256 /// The stop ID of the live process being traced, or an invalid stop ID 0257 /// if the trace is in an error or invalid state. 0258 uint32_t GetStopID(); 0259 0260 using OnBinaryDataReadCallback = 0261 std::function<llvm::Error(llvm::ArrayRef<uint8_t> data)>; 0262 using OnCpusBinaryDataReadCallback = std::function<llvm::Error( 0263 const llvm::DenseMap<lldb::cpu_id_t, llvm::ArrayRef<uint8_t>> 0264 &cpu_to_data)>; 0265 0266 /// Fetch binary data associated with a thread, either live or postmortem, and 0267 /// pass it to the given callback. The reason of having a callback is to free 0268 /// the caller from having to manage the life cycle of the data and to hide 0269 /// the different data fetching procedures that exist for live and post mortem 0270 /// threads. 0271 /// 0272 /// The fetched data is not persisted after the callback is invoked. 0273 /// 0274 /// \param[in] tid 0275 /// The tid who owns the data. 0276 /// 0277 /// \param[in] kind 0278 /// The kind of data to read. 0279 /// 0280 /// \param[in] callback 0281 /// The callback to be invoked once the data was successfully read. Its 0282 /// return value, which is an \a llvm::Error, is returned by this 0283 /// function. 0284 /// 0285 /// \return 0286 /// An \a llvm::Error if the data couldn't be fetched, or the return value 0287 /// of the callback, otherwise. 0288 llvm::Error OnThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, 0289 OnBinaryDataReadCallback callback); 0290 0291 /// Fetch binary data associated with a cpu, either live or postmortem, and 0292 /// pass it to the given callback. The reason of having a callback is to free 0293 /// the caller from having to manage the life cycle of the data and to hide 0294 /// the different data fetching procedures that exist for live and post mortem 0295 /// cpus. 0296 /// 0297 /// The fetched data is not persisted after the callback is invoked. 0298 /// 0299 /// \param[in] cpu_id 0300 /// The cpu who owns the data. 0301 /// 0302 /// \param[in] kind 0303 /// The kind of data to read. 0304 /// 0305 /// \param[in] callback 0306 /// The callback to be invoked once the data was successfully read. Its 0307 /// return value, which is an \a llvm::Error, is returned by this 0308 /// function. 0309 /// 0310 /// \return 0311 /// An \a llvm::Error if the data couldn't be fetched, or the return value 0312 /// of the callback, otherwise. 0313 llvm::Error OnCpuBinaryDataRead(lldb::cpu_id_t cpu_id, llvm::StringRef kind, 0314 OnBinaryDataReadCallback callback); 0315 0316 /// Similar to \a OnCpuBinaryDataRead but this is able to fetch the same data 0317 /// from all cpus at once. 0318 llvm::Error OnAllCpusBinaryDataRead(llvm::StringRef kind, 0319 OnCpusBinaryDataReadCallback callback); 0320 0321 /// \return 0322 /// All the currently traced processes. 0323 std::vector<Process *> GetAllProcesses(); 0324 0325 /// \return 0326 /// The list of cpus being traced. Might be empty depending on the 0327 /// plugin. 0328 llvm::ArrayRef<lldb::cpu_id_t> GetTracedCpus(); 0329 0330 /// Helper method for reading a data file and passing its data to the given 0331 /// callback. 0332 static llvm::Error OnDataFileRead(FileSpec file, 0333 OnBinaryDataReadCallback callback); 0334 0335 protected: 0336 /// Get the currently traced live process. 0337 /// 0338 /// \return 0339 /// If it's not a live process, return \a nullptr. 0340 Process *GetLiveProcess(); 0341 0342 /// Get the currently traced postmortem processes. 0343 /// 0344 /// \return 0345 /// If it's not a live process session, return an empty list. 0346 llvm::ArrayRef<Process *> GetPostMortemProcesses(); 0347 0348 /// Dispatcher for live trace data requests with some additional error 0349 /// checking. 0350 llvm::Expected<std::vector<uint8_t>> 0351 GetLiveTraceBinaryData(const TraceGetBinaryDataRequest &request, 0352 uint64_t expected_size); 0353 0354 /// Implementation of \a OnThreadBinaryDataRead() for live threads. 0355 llvm::Error OnLiveThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, 0356 OnBinaryDataReadCallback callback); 0357 0358 /// Implementation of \a OnLiveBinaryDataRead() for live cpus. 0359 llvm::Error OnLiveCpuBinaryDataRead(lldb::cpu_id_t cpu, llvm::StringRef kind, 0360 OnBinaryDataReadCallback callback); 0361 0362 /// Implementation of \a OnThreadBinaryDataRead() for post mortem threads. 0363 llvm::Error 0364 OnPostMortemThreadBinaryDataRead(lldb::tid_t tid, llvm::StringRef kind, 0365 OnBinaryDataReadCallback callback); 0366 0367 /// Implementation of \a OnCpuBinaryDataRead() for post mortem cpus. 0368 llvm::Error OnPostMortemCpuBinaryDataRead(lldb::cpu_id_t cpu_id, 0369 llvm::StringRef kind, 0370 OnBinaryDataReadCallback callback); 0371 0372 /// Get the file path containing data of a postmortem thread given a data 0373 /// identifier. 0374 /// 0375 /// \param[in] tid 0376 /// The thread whose data is requested. 0377 /// 0378 /// \param[in] kind 0379 /// The kind of data requested. 0380 /// 0381 /// \return 0382 /// The file spec containing the requested data, or an \a llvm::Error in 0383 /// case of failures. 0384 llvm::Expected<FileSpec> GetPostMortemThreadDataFile(lldb::tid_t tid, 0385 llvm::StringRef kind); 0386 0387 /// Get the file path containing data of a postmortem cpu given a data 0388 /// identifier. 0389 /// 0390 /// \param[in] cpu_id 0391 /// The cpu whose data is requested. 0392 /// 0393 /// \param[in] kind 0394 /// The kind of data requested. 0395 /// 0396 /// \return 0397 /// The file spec containing the requested data, or an \a llvm::Error in 0398 /// case of failures. 0399 llvm::Expected<FileSpec> GetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, 0400 llvm::StringRef kind); 0401 0402 /// Associate a given thread with a data file using a data identifier. 0403 /// 0404 /// \param[in] tid 0405 /// The thread associated with the data file. 0406 /// 0407 /// \param[in] kind 0408 /// The kind of data being registered. 0409 /// 0410 /// \param[in] file_spec 0411 /// The path of the data file. 0412 void SetPostMortemThreadDataFile(lldb::tid_t tid, llvm::StringRef kind, 0413 FileSpec file_spec); 0414 0415 /// Associate a given cpu with a data file using a data identifier. 0416 /// 0417 /// \param[in] cpu_id 0418 /// The cpu associated with the data file. 0419 /// 0420 /// \param[in] kind 0421 /// The kind of data being registered. 0422 /// 0423 /// \param[in] file_spec 0424 /// The path of the data file. 0425 void SetPostMortemCpuDataFile(lldb::cpu_id_t cpu_id, llvm::StringRef kind, 0426 FileSpec file_spec); 0427 0428 /// Get binary data of a live thread given a data identifier. 0429 /// 0430 /// \param[in] tid 0431 /// The thread whose data is requested. 0432 /// 0433 /// \param[in] kind 0434 /// The kind of data requested. 0435 /// 0436 /// \return 0437 /// A vector of bytes with the requested data, or an \a llvm::Error in 0438 /// case of failures. 0439 llvm::Expected<std::vector<uint8_t>> 0440 GetLiveThreadBinaryData(lldb::tid_t tid, llvm::StringRef kind); 0441 0442 /// Get binary data of a live cpu given a data identifier. 0443 /// 0444 /// \param[in] cpu_id 0445 /// The cpu whose data is requested. 0446 /// 0447 /// \param[in] kind 0448 /// The kind of data requested. 0449 /// 0450 /// \return 0451 /// A vector of bytes with the requested data, or an \a llvm::Error in 0452 /// case of failures. 0453 llvm::Expected<std::vector<uint8_t>> 0454 GetLiveCpuBinaryData(lldb::cpu_id_t cpu_id, llvm::StringRef kind); 0455 0456 /// Get binary data of the current process given a data identifier. 0457 /// 0458 /// \param[in] kind 0459 /// The kind of data requested. 0460 /// 0461 /// \return 0462 /// A vector of bytes with the requested data, or an \a llvm::Error in 0463 /// case of failures. 0464 llvm::Expected<std::vector<uint8_t>> 0465 GetLiveProcessBinaryData(llvm::StringRef kind); 0466 0467 /// Get the size of the data returned by \a GetLiveThreadBinaryData 0468 std::optional<uint64_t> GetLiveThreadBinaryDataSize(lldb::tid_t tid, 0469 llvm::StringRef kind); 0470 0471 /// Get the size of the data returned by \a GetLiveCpuBinaryData 0472 std::optional<uint64_t> GetLiveCpuBinaryDataSize(lldb::cpu_id_t cpu_id, 0473 llvm::StringRef kind); 0474 0475 /// Get the size of the data returned by \a GetLiveProcessBinaryData 0476 std::optional<uint64_t> GetLiveProcessBinaryDataSize(llvm::StringRef kind); 0477 0478 /// Constructor for post mortem processes 0479 Trace(llvm::ArrayRef<lldb::ProcessSP> postmortem_processes, 0480 std::optional<std::vector<lldb::cpu_id_t>> postmortem_cpus); 0481 0482 /// Constructor for a live process 0483 Trace(Process &live_process) : m_live_process(&live_process) {} 0484 0485 /// Start tracing a live process or its threads. 0486 /// 0487 /// \param[in] request 0488 /// JSON object with the information necessary to start tracing. In the 0489 /// case of gdb-remote processes, this JSON object should conform to the 0490 /// jLLDBTraceStart packet. 0491 /// 0492 /// \return 0493 /// \a llvm::Error::success if the operation was successful, or 0494 /// \a llvm::Error otherwise. 0495 llvm::Error Start(const llvm::json::Value &request); 0496 0497 /// Get the current tracing state of a live process and its threads. 0498 /// 0499 /// \return 0500 /// A JSON object string with custom data depending on the trace 0501 /// technology, or an \a llvm::Error in case of errors. 0502 llvm::Expected<std::string> GetLiveProcessState(); 0503 0504 /// Method to be overriden by the plug-in to refresh its own state. 0505 /// 0506 /// This is invoked by RefreshLiveProcessState when a new state is found. 0507 /// 0508 /// \param[in] state 0509 /// The jLLDBTraceGetState response. 0510 /// 0511 /// \param[in] json_response 0512 /// The original JSON response as a string. It might be useful to redecode 0513 /// it if it contains custom data for a specific trace plug-in. 0514 /// 0515 /// \return 0516 /// \b Error::success() if this operation succeedes, or an actual error 0517 /// otherwise. 0518 virtual llvm::Error 0519 DoRefreshLiveProcessState(TraceGetStateResponse state, 0520 llvm::StringRef json_response) = 0; 0521 0522 /// Return the list of processes traced by this instance. None of the returned 0523 /// pointers are invalid. 0524 std::vector<Process *> GetTracedProcesses(); 0525 0526 /// Method to be invoked by the plug-in to refresh the live process state. It 0527 /// will invoked DoRefreshLiveProcessState at some point, which should be 0528 /// implemented by the plug-in for custom state handling. 0529 /// 0530 /// The result is cached through the same process stop. Even in the case of 0531 /// errors, it caches the error. 0532 /// 0533 /// \return 0534 /// An error message if this operation failed, or \b nullptr otherwise. 0535 const char *RefreshLiveProcessState(); 0536 0537 private: 0538 uint32_t m_stop_id = LLDB_INVALID_STOP_ID; 0539 0540 /// Process traced by this object if doing live tracing. Otherwise it's null. 0541 Process *m_live_process = nullptr; 0542 0543 /// We package all the data that can change upon process stops to make sure 0544 /// this contract is very visible. 0545 /// This variable should only be accessed directly by constructores or live 0546 /// process data refreshers. 0547 struct Storage { 0548 /// Portmortem processes traced by this object if doing non-live tracing. 0549 /// Otherwise it's empty. 0550 std::vector<Process *> postmortem_processes; 0551 0552 /// These data kinds are returned by lldb-server when fetching the state of 0553 /// the tracing session. The size in bytes can be used later for fetching 0554 /// the data in batches. 0555 /// \{ 0556 0557 /// tid -> data kind -> size 0558 llvm::DenseMap<lldb::tid_t, llvm::DenseMap<ConstString, uint64_t>> 0559 live_thread_data; 0560 0561 /// cpu id -> data kind -> size 0562 llvm::DenseMap<lldb::cpu_id_t, llvm::DenseMap<ConstString, uint64_t>> 0563 live_cpu_data_sizes; 0564 /// cpu id -> data kind -> bytes 0565 llvm::DenseMap<lldb::cpu_id_t, 0566 llvm::DenseMap<ConstString, std::vector<uint8_t>>> 0567 live_cpu_data; 0568 0569 /// data kind -> size 0570 llvm::DenseMap<ConstString, uint64_t> live_process_data; 0571 /// \} 0572 0573 /// The list of cpus being traced. Might be \b std::nullopt depending on the 0574 /// plug-in. 0575 std::optional<std::vector<lldb::cpu_id_t>> cpus; 0576 0577 /// Postmortem traces can specific additional data files, which are 0578 /// represented in this variable using a data kind identifier for each file. 0579 /// \{ 0580 0581 /// tid -> data kind -> file 0582 llvm::DenseMap<lldb::tid_t, llvm::DenseMap<ConstString, FileSpec>> 0583 postmortem_thread_data; 0584 0585 /// cpu id -> data kind -> file 0586 llvm::DenseMap<lldb::cpu_id_t, llvm::DenseMap<ConstString, FileSpec>> 0587 postmortem_cpu_data; 0588 0589 /// \} 0590 0591 std::optional<std::string> live_refresh_error; 0592 } m_storage; 0593 0594 /// Get the storage after refreshing the data in the case of a live process. 0595 Storage &GetUpdatedStorage(); 0596 }; 0597 0598 } // namespace lldb_private 0599 0600 #endif // LLDB_TARGET_TRACE_H
| [ Source navigation ] | [ Diff markup ] | [ Identifier search ] | [ general search ] |
|
This page was automatically generated by the 2.3.7 LXR engine. The LXR team |
|