[Lldb-commits] [lldb] r303972 - Implementation of remote packets for Trace data.

Ravitheja Addepally via lldb-commits lldb-commits at lists.llvm.org
Fri May 26 04:46:28 PDT 2017


Author: ravitheja
Date: Fri May 26 06:46:27 2017
New Revision: 303972

URL: http://llvm.org/viewvc/llvm-project?rev=303972&view=rev
Log:
Implementation of remote packets for Trace data.

Summary:
The changes consist of new packets for trace manipulation and
trace collection. The new packets are also documented. The packets
are capable of providing custom trace specific parameters to start
tracing and also retrieve such configuration from the server.

Reviewers: clayborg, lldb-commits, tberghammer, labath, zturner

Reviewed By: clayborg, labath

Subscribers: krytarowski, lldb-commits

Differential Revision: https://reviews.llvm.org/D32585

Modified:
    lldb/trunk/docs/lldb-gdb-remote.txt
    lldb/trunk/include/lldb/API/SBTrace.h
    lldb/trunk/include/lldb/Core/TraceOptions.h
    lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
    lldb/trunk/include/lldb/Target/Process.h
    lldb/trunk/include/lldb/Utility/StringExtractor.h
    lldb/trunk/source/API/SBProcess.cpp
    lldb/trunk/source/API/SBTrace.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
    lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
    lldb/trunk/source/Utility/StringExtractor.cpp
    lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp
    lldb/trunk/source/Utility/StringExtractorGDBRemote.h
    lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp

Modified: lldb/trunk/docs/lldb-gdb-remote.txt
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/docs/lldb-gdb-remote.txt?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/docs/lldb-gdb-remote.txt (original)
+++ lldb/trunk/docs/lldb-gdb-remote.txt Fri May 26 06:46:27 2017
@@ -209,6 +209,163 @@ send packet: QListThreadsInStopReply
 read packet: OK
 
 //----------------------------------------------------------------------
+// jTraceStart:
+//
+// BRIEF
+//  Packet for starting trace of type lldb::TraceType. The following
+//  parameters should be appended to the packet formatted as a JSON
+//  dictionary, where the schematic for the JSON dictionary in terms of
+//  the recognized Keys is given below in the table.
+//  Different tracing types could require different custom parameters.
+//  Such custom tracing parameters if needed should be collectively
+//  specified in a JSON dictionary and the dictionary can be appended
+//  to this packet (as Value corresponding to "params"). Since sending
+//  JSON data over gdb-remote protocol has certain limitations, binary
+//  escaping convention should be used.
+//
+//  Following is the list of parameters -
+//
+//  Key             Value (Integer)                         (O)Optional/
+//                  (except params which should be a        (M)Mandatory
+//                  JSON dictionary)
+//  ==========      ====================================================
+//
+//  type            The type of trace to start (see          M
+//                  lldb-enumerations for TraceType)
+//
+//  buffersize      The size of the buffer to allocate       M
+//                  for trace gathering.
+//
+//  threadid        The id of the thread to start tracing    O
+//                  on.
+//
+//  metabuffersize  The size of buffer to hold meta data     O
+//                  used for decoding the trace data.
+//
+//  params          Any parameters that are specific to      O
+//                  certain trace technologies should be
+//                  collectively specified as a JSON
+//                  dictionary
+//  ==========      ====================================================
+//
+//  Each tracing instance is identified by a trace id which is returned
+//  as the reply to this packet. In case the tracing failed to begin an
+//  error code is returned instead.
+//----------------------------------------------------------------------
+
+send packet: jTraceStart:{"type":<type>,"buffersize":<buffersize>}]
+read packet: <trace id>/E<error code>
+
+//----------------------------------------------------------------------
+// jTraceStop:
+//
+// BRIEF
+//  Stop tracing instance with trace id <trace id>, of course trace
+//  needs to be started before. The following parameters should be
+//  formatted as a JSON dictionary to the packet. Since sending
+//  JSON data over gdb-remote protocol has certain limitations, binary
+//  escaping convention should be used.
+//
+//  Following is the list of parameters -
+//
+//  Key             Value (Integer)                         (O)Optional/
+//                                                          (M)Mandatory
+//  ==========      ====================================================
+//
+//  traceid         The trace id of the tracing instance    M
+//
+//  threadid        The id of the thread to stop tracing    O
+//                  on. Since <trace id> could map to
+//                  multiple trace instances (in case it
+//                  maps to the complete process), the
+//                  threadid of a particular thread could
+//                  be appended as "threadid:<thread id>;"
+//                  to stop tracing on that thread.
+//  ==========      ====================================================
+//
+//  An OK response is sent in case of success else an error code is
+//  returned.
+//----------------------------------------------------------------------
+
+send packet: jTraceStop:{"traceid":<trace id>}]
+read packet: <OK response>/E<error code>
+
+//----------------------------------------------------------------------
+// jTraceBufferRead:
+//
+// BRIEF
+//  Packet for reading the trace for tracing instance <trace id>, i.e the
+//  id obtained from StartTrace API. The following parameters should be
+//  formatted as a JSON dictionary to the packet. Since sending
+//  JSON data over gdb-remote protocol has certain limitations, binary
+//  escaping convention should be used.
+//
+//  Following is the list of parameters -
+//
+//  Key             Value (Integer)                         (O)Optional/
+//                                                          (M)Mandatory
+//  ==========      ====================================================
+//  traceid         The trace id of the tracing instance    M
+//
+//  offset          The offset to start reading the data    M
+//                  from.
+//
+//  buffersize      The size of the data intended to read.  M
+//
+//  threadid        The id of the thread to retrieve data   O
+//                  from.
+//  ==========      ====================================================
+//
+//  The trace data is sent as raw binary data if the read was successful
+//  else an error code is sent.
+//----------------------------------------------------------------------
+
+send packet: jTraceBufferRead:{"traceid":<trace id>,"offset":<byteoffset>,"buffersize":<byte_count>}]
+read packet: <binary trace data>/E<error code>
+
+//----------------------------------------------------------------------
+// jTraceMetaRead:
+//
+// BRIEF
+//  Similar Packet as above except it reads meta data.
+//----------------------------------------------------------------------
+
+/----------------------------------------------------------------------
+// jTraceConfigRead:
+//
+// BRIEF
+//  Request the trace configuration for the tracing instance with id
+//  <trace id>.
+//
+//  Following is the list of parameters -
+//
+//  Key             Value (Integer)                         (O)Optional/
+//                                                          (M)Mandatory
+//  ==========      ====================================================
+//  traceid         The trace id of the tracing instance    M
+//
+//  threadid        The id of the thread to obtain trace    O
+//                  configuration from. Since <trace id>
+//                  could map to multiple trace instances
+//                  (in case it maps to the complete
+//                  process), the threadid of a particular
+//                  thread could be appended as
+//                  "threadid:<thread id>;" to obtain the
+//                  trace configuration of that thread.
+//  ==========      ====================================================
+//
+//  In the response packet the trace configuration is sent as text,
+//  formatted as a JSON dictionary. Since sending JSON data over
+//  gdb-remote protocol has certain limitations, binary escaping
+//  convention is used.
+//  In case the trace instance with the <trace id> was not found, an
+//  error code is returned.
+//----------------------------------------------------------------------
+
+send packet: jTraceConfigRead:{"traceid":<trace id>}
+read packet: {"conf1":<conf1>,"conf2":<conf2>,"params":{"paramName":paramValue}]}];/E<error code>
+
+//----------------------------------------------------------------------
 // "qRegisterInfo<hex-reg-id>"
 //
 // BRIEF

Modified: lldb/trunk/include/lldb/API/SBTrace.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/API/SBTrace.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/include/lldb/API/SBTrace.h (original)
+++ lldb/trunk/include/lldb/API/SBTrace.h Fri May 26 06:46:27 2017
@@ -40,7 +40,7 @@ public:
   ///
   /// @param[in] thread_id
   ///     Tracing could be started for the complete process or a
-  ///     single thread, in the first case the uid obtained would
+  ///     single thread, in the first case the traceid obtained would
   ///     map to all the threads existing within the process and the
   ///     ones spawning later. The thread_id parameter can be used in
   ///     such a scenario to select the trace data for a specific
@@ -68,16 +68,17 @@ public:
   ///     An error explaining what went wrong.
   ///
   /// @param[in] thread_id
-  ///     The user id could map to a tracing instance for a thread
+  ///     The trace id could map to a tracing instance for a thread
   ///     or could also map to a group of threads being traced with
   ///     the same trace options. A thread_id is normally optional
   ///     except in the case of tracing a complete process and tracing
   ///     needs to switched off on a particular thread.
   ///     A situation could occur where initially a thread (lets say
-  ///     thread A) is being individually traced with a particular uid
-  ///     and then tracing is started on the complete process, in this
-  ///     case thread A will continue without any change. All newly
-  ///     spawned threads would be traced with the uid of the process.
+  ///     thread A) is being individually traced with a particular
+  ///     trace id and then tracing is started on the complete
+  ///     process, in this case thread A will continue without any
+  ///     change. All newly spawned threads would be traced with the
+  ///     trace id of the process.
   ///     Now if the StopTrace API is called for the whole process,
   ///     thread A will not be stopped and must be stopped separately.
   //------------------------------------------------------------------

Modified: lldb/trunk/include/lldb/Core/TraceOptions.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Core/TraceOptions.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Core/TraceOptions.h (original)
+++ lldb/trunk/include/lldb/Core/TraceOptions.h Fri May 26 06:46:27 2017
@@ -18,8 +18,7 @@
 namespace lldb_private {
 class TraceOptions {
 public:
-  TraceOptions()
-      : m_trace_params(new StructuredData::Dictionary()) {}
+  TraceOptions() : m_trace_params(new StructuredData::Dictionary()) {}
 
   const StructuredData::DictionarySP &getTraceParams() const {
     return m_trace_params;
@@ -43,7 +42,7 @@ public:
 
   void setThreadID(lldb::tid_t thread_id) { m_thread_id = thread_id; }
 
-  lldb::tid_t getThreadID() { return m_thread_id; }
+  lldb::tid_t getThreadID() const { return m_thread_id; }
 
 private:
   lldb::TraceType m_type;

Modified: lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h (original)
+++ lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h Fri May 26 06:46:27 2017
@@ -10,6 +10,7 @@
 #ifndef liblldb_NativeProcessProtocol_h_
 #define liblldb_NativeProcessProtocol_h_
 
+#include "lldb/Core/TraceOptions.h"
 #include "lldb/Host/MainLoop.h"
 #include "lldb/Utility/Status.h"
 #include "lldb/lldb-private-forward.h"
@@ -308,6 +309,108 @@ public:
   static Status Attach(lldb::pid_t pid, NativeDelegate &native_delegate,
                        MainLoop &mainloop, NativeProcessProtocolSP &process_sp);
 
+  //------------------------------------------------------------------
+  /// StartTracing API for starting a tracing instance with the
+  /// TraceOptions on a specific thread or process.
+  ///
+  /// @param[in] config
+  ///     The configuration to use when starting tracing.
+  ///
+  /// @param[out] error
+  ///     Status indicates what went wrong.
+  ///
+  /// @return
+  ///     The API returns a user_id which can be used to get trace
+  ///     data, trace configuration or stopping the trace instance.
+  ///     The user_id is a key to identify and operate with a tracing
+  ///     instance. It may refer to the complete process or a single
+  ///     thread.
+  //------------------------------------------------------------------
+  virtual lldb::user_id_t StartTrace(const TraceOptions &config,
+                                     Status &error) {
+    error.SetErrorString("Not implemented");
+    return LLDB_INVALID_UID;
+  }
+
+  //------------------------------------------------------------------
+  /// StopTracing API as the name suggests stops a tracing instance.
+  ///
+  /// @param[in] uid
+  ///     The user id of the trace intended to be stopped. Now a
+  ///     user_id may map to multiple threads in which case this API
+  ///     could be used to stop the tracing for a specific thread by
+  ///     supplying its thread id.
+  ///
+  /// @param[in] thread
+  ///     Thread is needed when the complete process is being traced
+  ///     and the user wishes to stop tracing on a particular thread.
+  ///
+  /// @return
+  ///     Status indicating what went wrong.
+  //------------------------------------------------------------------
+  virtual Status StopTrace(lldb::user_id_t uid,
+                           lldb::tid_t thread = LLDB_INVALID_THREAD_ID) {
+    return Status("Not implemented");
+  }
+
+  //------------------------------------------------------------------
+  /// This API provides the trace data collected in the form of raw
+  /// data.
+  ///
+  /// @param[in] uid thread
+  ///     The uid and thread provide the context for the trace
+  ///     instance.
+  ///
+  /// @param[in] buffer
+  ///     The buffer provides the destination buffer where the trace
+  ///     data would be read to. The buffer should be truncated to the
+  ///     filled length by this function.
+  ///
+  /// @param[in] offset
+  ///     There is possibility to read partially the trace data from
+  ///     a specified offset where in such cases the buffer provided
+  ///     may be smaller than the internal trace collection container.
+  ///
+  /// @return
+  ///     The size of the data actually read.
+  //------------------------------------------------------------------
+  virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread,
+                         llvm::MutableArrayRef<uint8_t> &buffer,
+                         size_t offset = 0) {
+    return Status("Not implemented");
+  }
+
+  //------------------------------------------------------------------
+  /// Similar API as above except it aims to provide any extra data
+  /// useful for decoding the actual trace data.
+  //------------------------------------------------------------------
+  virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread,
+                             llvm::MutableArrayRef<uint8_t> &buffer,
+                             size_t offset = 0) {
+    return Status("Not implemented");
+  }
+
+  //------------------------------------------------------------------
+  /// API to query the TraceOptions for a given user id
+  ///
+  /// @param[in] uid
+  ///     The user id of the tracing instance.
+  ///
+  /// @param[in] config
+  ///     The thread id of the tracing instance, in case configuration
+  ///     for a specific thread is needed should be specified in the
+  ///     config.
+  ///
+  /// @param[out] error
+  ///     Status indicates what went wrong.
+  ///
+  /// @param[out] config
+  ///     The actual configuration being used for tracing.
+  //------------------------------------------------------------------
+  virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &config) {
+    return Status("Not implemented");
+  }
+
 protected:
   lldb::pid_t m_pid;
 
@@ -381,6 +484,6 @@ protected:
 private:
   void SynchronouslyNotifyProcessStateChanged(lldb::StateType state);
 };
-}
+} // namespace lldb_private
 
 #endif // #ifndef liblldb_NativeProcessProtocol_h_

Modified: lldb/trunk/include/lldb/Target/Process.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Process.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Process.h (original)
+++ lldb/trunk/include/lldb/Target/Process.h Fri May 26 06:46:27 2017
@@ -2781,7 +2781,7 @@ public:
   /// GetTraceConfig should supply the actual used trace
   /// configuration.
   //------------------------------------------------------------------
-  virtual lldb::user_id_t StartTrace(lldb::TraceOptionsSP &options,
+  virtual lldb::user_id_t StartTrace(const TraceOptions &options,
                                      Status &error) {
     error.SetErrorString("Not implemented");
     return LLDB_INVALID_UID;
@@ -2796,9 +2796,8 @@ public:
   /// In the other case that tracing on an individual thread needs
   /// to be stopped a thread_id can be supplied.
   //------------------------------------------------------------------
-  virtual void StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id,
-                         Status &error) {
-    error.SetErrorString("Not implemented");
+  virtual Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
+    return Status("Not implemented");
   }
 
   //------------------------------------------------------------------
@@ -2809,21 +2808,19 @@ public:
   /// may not. The thread_id should be used to select a particular
   /// thread for trace extraction.
   //------------------------------------------------------------------
-  virtual size_t GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
-                         Status &error, void *buf, size_t size,
+  virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                         llvm::MutableArrayRef<uint8_t> &buffer,
                          size_t offset = 0) {
-    error.SetErrorString("Not implemented");
-    return 0;
+    return Status("Not implemented");
   }
 
   //------------------------------------------------------------------
   /// Similar API as above except for obtaining meta data
   //------------------------------------------------------------------
-  virtual size_t GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
-                             Status &error, void *buf, size_t size,
+  virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                             llvm::MutableArrayRef<uint8_t> &buffer,
                              size_t offset = 0) {
-    error.SetErrorString("Not implemented");
-    return 0;
+    return Status("Not implemented");
   }
 
   //------------------------------------------------------------------
@@ -2835,10 +2832,8 @@ public:
   /// configuration used by a specific thread. The thread_id specified
   /// should also match the uid otherwise an error will be returned.
   //------------------------------------------------------------------
-  virtual void GetTraceConfig(lldb::user_id_t uid, Status &error,
-                              lldb::TraceOptionsSP &options) {
-    error.SetErrorString("Not implemented");
-    return;
+  virtual Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) {
+    return Status("Not implemented");
   }
 
 protected:

Modified: lldb/trunk/include/lldb/Utility/StringExtractor.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Utility/StringExtractor.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Utility/StringExtractor.h (original)
+++ lldb/trunk/include/lldb/Utility/StringExtractor.h Fri May 26 06:46:27 2017
@@ -111,6 +111,8 @@ public:
 
   size_t GetHexByteStringTerminatedBy(std::string &str, char terminator);
 
+  bool ConsumeFront(const llvm::StringRef &str);
+
   const char *Peek() {
     if (m_index < m_packet.size())
       return m_packet.c_str() + m_index;

Modified: lldb/trunk/source/API/SBProcess.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBProcess.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/API/SBProcess.cpp (original)
+++ lldb/trunk/source/API/SBProcess.cpp Fri May 26 06:46:27 2017
@@ -363,10 +363,9 @@ lldb::SBTrace SBProcess::StartTrace(SBTr
   if (!process_sp) {
     error.SetErrorString("invalid process");
   } else {
-
-    uid = process_sp->StartTrace(options.m_traceoptions_sp, error.ref());
+    uid = process_sp->StartTrace(*(options.m_traceoptions_sp), error.ref());
     trace_instance.SetTraceUID(uid);
-    LLDB_LOG(log, "SBProcess::returned uid - %" PRIx64, uid);
+    LLDB_LOG(log, "SBProcess::returned uid - {0}", uid);
   }
   return trace_instance;
 }

Modified: lldb/trunk/source/API/SBTrace.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/API/SBTrace.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/API/SBTrace.cpp (original)
+++ lldb/trunk/source/API/SBTrace.cpp Fri May 26 06:46:27 2017
@@ -7,8 +7,8 @@
 //
 //===----------------------------------------------------------------------===//
 
-#include "lldb/Utility/Log.h"
 #include "lldb/Target/Process.h"
+#include "lldb/Utility/Log.h"
 
 #include "lldb/API/SBTrace.h"
 #include "lldb/API/SBTraceOptions.h"
@@ -25,37 +25,37 @@ lldb::ProcessSP SBTrace::GetSP() const {
 
 size_t SBTrace::GetTraceData(SBError &error, void *buf, size_t size,
                              size_t offset, lldb::tid_t thread_id) {
-  size_t bytes_read = 0;
   ProcessSP process_sp(GetSP());
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+  llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
   error.Clear();
 
   if (!process_sp) {
     error.SetErrorString("invalid process");
   } else {
-    bytes_read = process_sp->GetData(GetTraceUID(), thread_id, error.ref(), buf,
-                                     size, offset);
-    LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read);
+    error.SetError(
+        process_sp->GetData(GetTraceUID(), thread_id, buffer, offset));
+    LLDB_LOG(log, "SBTrace::bytes_read - {0}", buffer.size());
   }
-  return bytes_read;
+  return buffer.size();
 }
 
 size_t SBTrace::GetMetaData(SBError &error, void *buf, size_t size,
                             size_t offset, lldb::tid_t thread_id) {
-  size_t bytes_read = 0;
   ProcessSP process_sp(GetSP());
   Log *log(lldb_private::GetLogIfAllCategoriesSet(LIBLLDB_LOG_API));
+  llvm::MutableArrayRef<uint8_t> buffer(static_cast<uint8_t *>(buf), size);
   error.Clear();
 
   if (!process_sp) {
     error.SetErrorString("invalid process");
   } else {
 
-    bytes_read = process_sp->GetMetaData(GetTraceUID(), thread_id, error.ref(),
-                                         buf, size, offset);
-    LLDB_LOG(log, "SBTrace::bytes_read - %" PRIx64, bytes_read);
+    error.SetError(
+        process_sp->GetMetaData(GetTraceUID(), thread_id, buffer, offset));
+    LLDB_LOG(log, "SBTrace::bytes_read - {0}", buffer.size());
   }
-  return bytes_read;
+  return buffer.size();
 }
 
 void SBTrace::StopTrace(SBError &error, lldb::tid_t thread_id) {
@@ -66,7 +66,7 @@ void SBTrace::StopTrace(SBError &error,
     error.SetErrorString("invalid process");
     return;
   }
-  process_sp->StopTrace(GetTraceUID(), thread_id, error.ref());
+  error.SetError(process_sp->StopTrace(GetTraceUID(), thread_id));
 }
 
 void SBTrace::GetTraceConfig(SBTraceOptions &options, SBError &error) {
@@ -76,8 +76,8 @@ void SBTrace::GetTraceConfig(SBTraceOpti
   if (!process_sp) {
     error.SetErrorString("invalid process");
   } else {
-    process_sp->GetTraceConfig(GetTraceUID(), error.ref(),
-                               options.m_traceoptions_sp);
+    error.SetError(process_sp->GetTraceConfig(GetTraceUID(),
+                                              *(options.m_traceoptions_sp)));
   }
 }
 

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp Fri May 26 06:46:27 2017
@@ -30,7 +30,6 @@
 #include "lldb/Utility/JSON.h"
 #include "lldb/Utility/LLDBAssert.h"
 #include "lldb/Utility/Log.h"
-#include "lldb/Utility/StreamGDBRemote.h"
 #include "lldb/Utility/StreamString.h"
 
 // Project includes
@@ -3152,6 +3151,211 @@ bool GDBRemoteCommunicationClient::SyncT
          response.IsOKResponse();
 }
 
+lldb::user_id_t
+GDBRemoteCommunicationClient::SendStartTracePacket(const TraceOptions &options,
+                                                   Status &error) {
+  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+  lldb::user_id_t ret_uid = LLDB_INVALID_UID;
+
+  StreamGDBRemote escaped_packet;
+  escaped_packet.PutCString("jTraceStart:");
+
+  StructuredData::Dictionary json_packet;
+  json_packet.AddIntegerItem("type", options.getType());
+  json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
+  json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
+
+  if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
+    json_packet.AddIntegerItem("threadid", options.getThreadID());
+
+  StructuredData::DictionarySP custom_params = options.getTraceParams();
+  if (custom_params)
+    json_packet.AddItem("params", custom_params);
+
+  StreamString json_string;
+  json_packet.Dump(json_string, false);
+  escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+
+  StringExtractorGDBRemote response;
+  if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+                                   true) ==
+      GDBRemoteCommunication::PacketResult::Success) {
+    if (!response.IsNormalResponse()) {
+      error.SetError(response.GetError(), eErrorTypeGeneric);
+      LLDB_LOG(log, "Target does not support Tracing");
+    } else {
+      ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID);
+    }
+  } else {
+    LLDB_LOG(log, "failed to send packet");
+    error.SetErrorStringWithFormat("failed to send packet: '%s'",
+                                   escaped_packet.GetData());
+  }
+  return ret_uid;
+}
+
+Status
+GDBRemoteCommunicationClient::SendStopTracePacket(lldb::user_id_t uid,
+                                                  lldb::tid_t thread_id) {
+  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+  StringExtractorGDBRemote response;
+  Status error;
+
+  StructuredData::Dictionary json_packet;
+  StreamGDBRemote escaped_packet;
+  StreamString json_string;
+  escaped_packet.PutCString("jTraceStop:");
+
+  json_packet.AddIntegerItem("traceid", uid);
+
+  if (thread_id != LLDB_INVALID_THREAD_ID)
+    json_packet.AddIntegerItem("threadid", thread_id);
+
+  json_packet.Dump(json_string, false);
+
+  escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+
+  if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+                                   true) ==
+      GDBRemoteCommunication::PacketResult::Success) {
+    if (!response.IsOKResponse()) {
+      error.SetError(response.GetError(), eErrorTypeGeneric);
+      LLDB_LOG(log, "stop tracing failed");
+    }
+  } else {
+    LLDB_LOG(log, "failed to send packet");
+    error.SetErrorStringWithFormat(
+        "failed to send packet: '%s' with error '%d'", escaped_packet.GetData(),
+        response.GetError());
+  }
+  return error;
+}
+
+Status GDBRemoteCommunicationClient::SendGetDataPacket(
+    lldb::user_id_t uid, lldb::tid_t thread_id,
+    llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+  StreamGDBRemote escaped_packet;
+  escaped_packet.PutCString("jTraceBufferRead:");
+  return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
+}
+
+Status GDBRemoteCommunicationClient::SendGetMetaDataPacket(
+    lldb::user_id_t uid, lldb::tid_t thread_id,
+    llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+  StreamGDBRemote escaped_packet;
+  escaped_packet.PutCString("jTraceMetaRead:");
+  return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset);
+}
+
+Status
+GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid,
+                                                       TraceOptions &options) {
+  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+  StringExtractorGDBRemote response;
+  Status error;
+
+  StreamString json_string;
+  StreamGDBRemote escaped_packet;
+  escaped_packet.PutCString("jTraceConfigRead:");
+
+  StructuredData::Dictionary json_packet;
+  json_packet.AddIntegerItem("traceid", uid);
+
+  if (options.getThreadID() != LLDB_INVALID_THREAD_ID)
+    json_packet.AddIntegerItem("threadid", options.getThreadID());
+
+  json_packet.Dump(json_string, false);
+  escaped_packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+
+  if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response,
+                                   true) ==
+      GDBRemoteCommunication::PacketResult::Success) {
+    if (response.IsNormalResponse()) {
+      uint64_t type = std::numeric_limits<uint64_t>::max();
+      uint64_t buffersize = std::numeric_limits<uint64_t>::max();
+      uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
+
+      auto json_object = StructuredData::ParseJSON(response.Peek());
+
+      if (!json_object ||
+          json_object->GetType() != StructuredData::Type::eTypeDictionary) {
+        error.SetErrorString("Invalid Configuration obtained");
+        return error;
+      }
+
+      auto json_dict = json_object->GetAsDictionary();
+
+      json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize",
+                                                   metabuffersize);
+      options.setMetaDataBufferSize(metabuffersize);
+
+      json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize);
+      options.setTraceBufferSize(buffersize);
+
+      json_dict->GetValueForKeyAsInteger<uint64_t>("type", type);
+      options.setType(static_cast<lldb::TraceType>(type));
+
+      StructuredData::ObjectSP custom_params_sp =
+          json_dict->GetValueForKey("params");
+      if (custom_params_sp) {
+        if (custom_params_sp->GetType() !=
+            StructuredData::Type::eTypeDictionary) {
+          error.SetErrorString("Invalid Configuration obtained");
+          return error;
+        } else
+          options.setTraceParams(
+              static_pointer_cast<StructuredData::Dictionary>(
+                  custom_params_sp));
+      }
+    } else {
+      error.SetError(response.GetError(), eErrorTypeGeneric);
+    }
+  } else {
+    LLDB_LOG(log, "failed to send packet");
+    error.SetErrorStringWithFormat("failed to send packet: '%s'",
+                                   escaped_packet.GetData());
+  }
+  return error;
+}
+
+Status GDBRemoteCommunicationClient::SendGetTraceDataPacket(
+    StreamGDBRemote &packet, lldb::user_id_t uid, lldb::tid_t thread_id,
+    llvm::MutableArrayRef<uint8_t> &buffer, size_t offset) {
+  Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS));
+  Status error;
+
+  StructuredData::Dictionary json_packet;
+
+  json_packet.AddIntegerItem("traceid", uid);
+  json_packet.AddIntegerItem("offset", offset);
+  json_packet.AddIntegerItem("buffersize", buffer.size());
+
+  if (thread_id != LLDB_INVALID_THREAD_ID)
+    json_packet.AddIntegerItem("threadid", thread_id);
+
+  StreamString json_string;
+  json_packet.Dump(json_string, false);
+
+  packet.PutEscapedBytes(json_string.GetData(), json_string.GetSize());
+  StringExtractorGDBRemote response;
+  if (SendPacketAndWaitForResponse(packet.GetString(), response, true) ==
+      GDBRemoteCommunication::PacketResult::Success) {
+    if (response.IsNormalResponse()) {
+      size_t filled_size = response.GetHexBytesAvail(buffer);
+      buffer = llvm::MutableArrayRef<uint8_t>(buffer.data(), filled_size);
+    } else {
+      error.SetError(response.GetError(), eErrorTypeGeneric);
+      buffer = buffer.slice(buffer.size());
+    }
+  } else {
+    LLDB_LOG(log, "failed to send packet");
+    error.SetErrorStringWithFormat("failed to send packet: '%s'",
+                                   packet.GetData());
+    buffer = buffer.slice(buffer.size());
+  }
+  return error;
+}
+
 bool GDBRemoteCommunicationClient::GetModuleInfo(
     const FileSpec &module_file_spec, const lldb_private::ArchSpec &arch_spec,
     ModuleSpec &module_spec) {

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h Fri May 26 06:46:27 2017
@@ -25,6 +25,7 @@
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/StructuredData.h"
 #include "lldb/Target/Process.h"
+#include "lldb/Utility/StreamGDBRemote.h"
 
 #include "llvm/ADT/Optional.h"
 
@@ -499,6 +500,21 @@ public:
   ConfigureRemoteStructuredData(const ConstString &type_name,
                                 const StructuredData::ObjectSP &config_sp);
 
+  lldb::user_id_t SendStartTracePacket(const TraceOptions &options,
+                                       Status &error);
+
+  Status SendStopTracePacket(lldb::user_id_t uid, lldb::tid_t thread_id);
+
+  Status SendGetDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
+                           llvm::MutableArrayRef<uint8_t> &buffer,
+                           size_t offset = 0);
+
+  Status SendGetMetaDataPacket(lldb::user_id_t uid, lldb::tid_t thread_id,
+                               llvm::MutableArrayRef<uint8_t> &buffer,
+                               size_t offset = 0);
+
+  Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options);
+
 protected:
   LazyBool m_supports_not_sending_acks;
   LazyBool m_supports_thread_suffix;
@@ -587,6 +603,11 @@ protected:
       lldb::tid_t tid, StreamString &&payload,
       StringExtractorGDBRemote &response, bool send_async);
 
+  Status SendGetTraceDataPacket(StreamGDBRemote &packet, lldb::user_id_t uid,
+                                lldb::tid_t thread_id,
+                                llvm::MutableArrayRef<uint8_t> &buffer,
+                                size_t offset);
+
 private:
   DISALLOW_COPY_AND_ASSIGN(GDBRemoteCommunicationClient);
 };

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp Fri May 26 06:46:27 2017
@@ -183,6 +183,22 @@ void GDBRemoteCommunicationServerLLGS::R
       StringExtractorGDBRemote::eServerPacketType_QPassSignals,
       &GDBRemoteCommunicationServerLLGS::Handle_QPassSignals);
 
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_jTraceStart,
+      &GDBRemoteCommunicationServerLLGS::Handle_jTraceStart);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_jTraceBufferRead,
+      &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_jTraceMetaRead,
+      &GDBRemoteCommunicationServerLLGS::Handle_jTraceRead);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_jTraceStop,
+      &GDBRemoteCommunicationServerLLGS::Handle_jTraceStop);
+  RegisterMemberFunctionHandler(
+      StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead,
+      &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead);
+
   RegisterPacketHandler(StringExtractorGDBRemote::eServerPacketType_k,
                         [this](StringExtractorGDBRemote packet, Status &error,
                                bool &interrupt, bool &quit) {
@@ -1084,6 +1100,232 @@ void GDBRemoteCommunicationServerLLGS::S
 }
 
 GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceStart(
+    StringExtractorGDBRemote &packet) {
+  Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
+  // Fail if we don't have a current process.
+  if (!m_debugged_process_sp ||
+      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+    return SendErrorResponse(68);
+
+  if (!packet.ConsumeFront("jTraceStart:"))
+    return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
+
+  TraceOptions options;
+  uint64_t type = std::numeric_limits<uint64_t>::max();
+  uint64_t buffersize = std::numeric_limits<uint64_t>::max();
+  lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+  uint64_t metabuffersize = std::numeric_limits<uint64_t>::max();
+
+  auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+  if (!json_object ||
+      json_object->GetType() != StructuredData::Type::eTypeDictionary)
+    return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
+
+  auto json_dict = json_object->GetAsDictionary();
+
+  json_dict->GetValueForKeyAsInteger<uint64_t>("metabuffersize",
+                                               metabuffersize);
+  options.setMetaDataBufferSize(metabuffersize);
+
+  json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", buffersize);
+  options.setTraceBufferSize(buffersize);
+
+  json_dict->GetValueForKeyAsInteger<uint64_t>("type", type);
+  options.setType(static_cast<lldb::TraceType>(type));
+
+  json_dict->GetValueForKeyAsInteger<uint64_t>("threadid", tid);
+  options.setThreadID(tid);
+
+  StructuredData::ObjectSP custom_params_sp =
+      json_dict->GetValueForKey("params");
+  if (custom_params_sp &&
+      custom_params_sp->GetType() != StructuredData::Type::eTypeDictionary)
+    return SendIllFormedResponse(packet, "jTraceStart: Ill formed packet ");
+
+  options.setTraceParams(
+      static_pointer_cast<StructuredData::Dictionary>(custom_params_sp));
+
+  if (buffersize == std::numeric_limits<uint64_t>::max() ||
+      type != lldb::TraceType::eTraceTypeProcessorTrace) {
+    LLDB_LOG(log, "Ill formed packet buffersize = {0} type = {1}", buffersize,
+             type);
+    return SendIllFormedResponse(packet, "JTrace:start: Ill formed packet ");
+  }
+
+  Status error;
+  lldb::user_id_t uid = LLDB_INVALID_UID;
+  uid = m_debugged_process_sp->StartTrace(options, error);
+  LLDB_LOG(log, "uid is {0} , error is {1}", uid, error.GetError());
+  if (error.Fail())
+    return SendErrorResponse(error.GetError());
+
+  StreamGDBRemote response;
+  response.Printf("%" PRIx64, uid);
+  return SendPacketNoLock(response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceStop(
+    StringExtractorGDBRemote &packet) {
+  // Fail if we don't have a current process.
+  if (!m_debugged_process_sp ||
+      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+    return SendErrorResponse(68);
+
+  if (!packet.ConsumeFront("jTraceStop:"))
+    return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+
+  lldb::user_id_t uid = LLDB_INVALID_UID;
+  lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+
+  auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+  if (!json_object ||
+      json_object->GetType() != StructuredData::Type::eTypeDictionary)
+    return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+
+  auto json_dict = json_object->GetAsDictionary();
+
+  if (!json_dict->GetValueForKeyAsInteger<lldb::user_id_t>("traceid", uid))
+    return SendIllFormedResponse(packet, "jTraceStop: Ill formed packet ");
+
+  json_dict->GetValueForKeyAsInteger<lldb::tid_t>("threadid", tid);
+
+  Status error = m_debugged_process_sp->StopTrace(uid, tid);
+
+  if (error.Fail())
+    return SendErrorResponse(error.GetError());
+
+  return SendOKResponse();
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead(
+    StringExtractorGDBRemote &packet) {
+
+  // Fail if we don't have a current process.
+  if (!m_debugged_process_sp ||
+      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+    return SendErrorResponse(68);
+
+  if (!packet.ConsumeFront("jTraceConfigRead:"))
+    return SendIllFormedResponse(packet,
+                                 "jTraceConfigRead: Ill formed packet ");
+
+  lldb::user_id_t uid = LLDB_INVALID_UID;
+  lldb::tid_t threadid = LLDB_INVALID_THREAD_ID;
+
+  auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+  if (!json_object ||
+      json_object->GetType() != StructuredData::Type::eTypeDictionary)
+    return SendIllFormedResponse(packet,
+                                 "jTraceConfigRead: Ill formed packet ");
+
+  auto json_dict = json_object->GetAsDictionary();
+
+  if (!json_dict->GetValueForKeyAsInteger<lldb::user_id_t>("traceid", uid))
+    return SendIllFormedResponse(packet,
+                                 "jTraceConfigRead: Ill formed packet ");
+
+  json_dict->GetValueForKeyAsInteger<lldb::tid_t>("threadid", threadid);
+
+  TraceOptions options;
+  StreamGDBRemote response;
+
+  options.setThreadID(threadid);
+  Status error = m_debugged_process_sp->GetTraceConfig(uid, options);
+
+  if (error.Fail())
+    return SendErrorResponse(error.GetError());
+
+  StreamGDBRemote escaped_response;
+  StructuredData::Dictionary json_packet;
+
+  json_packet.AddIntegerItem("type", options.getType());
+  json_packet.AddIntegerItem("buffersize", options.getTraceBufferSize());
+  json_packet.AddIntegerItem("metabuffersize", options.getMetaDataBufferSize());
+
+  StructuredData::DictionarySP custom_params = options.getTraceParams();
+  if (custom_params)
+    json_packet.AddItem("params", custom_params);
+
+  StreamString json_string;
+  json_packet.Dump(json_string, false);
+  escaped_response.PutEscapedBytes(json_string.GetData(),
+                                   json_string.GetSize());
+  return SendPacketNoLock(escaped_response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
+GDBRemoteCommunicationServerLLGS::Handle_jTraceRead(
+    StringExtractorGDBRemote &packet) {
+
+  // Fail if we don't have a current process.
+  if (!m_debugged_process_sp ||
+      (m_debugged_process_sp->GetID() == LLDB_INVALID_PROCESS_ID))
+    return SendErrorResponse(68);
+
+  enum PacketType { MetaData, BufferData };
+  PacketType tracetype = MetaData;
+
+  if (packet.ConsumeFront("jTraceBufferRead:"))
+    tracetype = BufferData;
+  else if (packet.ConsumeFront("jTraceMetaRead:"))
+    tracetype = MetaData;
+  else {
+    return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
+  }
+
+  lldb::user_id_t uid = LLDB_INVALID_UID;
+
+  size_t byte_count = std::numeric_limits<size_t>::max();
+  lldb::tid_t tid = LLDB_INVALID_THREAD_ID;
+  size_t offset = std::numeric_limits<size_t>::max();
+
+  auto json_object = StructuredData::ParseJSON(packet.Peek());
+
+  if (!json_object ||
+      json_object->GetType() != StructuredData::Type::eTypeDictionary)
+    return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
+
+  auto json_dict = json_object->GetAsDictionary();
+
+  if (!json_dict->GetValueForKeyAsInteger<lldb::user_id_t>("traceid", uid) ||
+      !json_dict->GetValueForKeyAsInteger<uint64_t>("offset", offset) ||
+      !json_dict->GetValueForKeyAsInteger<uint64_t>("buffersize", byte_count))
+    return SendIllFormedResponse(packet, "jTrace: Ill formed packet ");
+
+  json_dict->GetValueForKeyAsInteger<lldb::tid_t>("threadid", tid);
+
+  // Allocate the response buffer.
+  uint8_t *buffer = new (std::nothrow) uint8_t[byte_count];
+  if (buffer == nullptr)
+    return SendErrorResponse(0x78);
+
+  StreamGDBRemote response;
+  Status error;
+  llvm::MutableArrayRef<uint8_t> buf(buffer, byte_count);
+
+  if (tracetype == BufferData)
+    error = m_debugged_process_sp->GetData(uid, tid, buf, offset);
+  else if (tracetype == MetaData)
+    error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset);
+
+  if (error.Fail())
+    return SendErrorResponse(error.GetError());
+
+  for (size_t i = 0; i < buf.size(); ++i)
+    response.PutHex8(buf[i]);
+
+  StreamGDBRemote escaped_response;
+  escaped_response.PutEscapedBytes(response.GetData(), response.GetSize());
+  return SendPacketNoLock(escaped_response.GetString());
+}
+
+GDBRemoteCommunication::PacketResult
 GDBRemoteCommunicationServerLLGS::Handle_qProcessInfo(
     StringExtractorGDBRemote &packet) {
   // Fail if we don't have a current process.

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h Fri May 26 06:46:27 2017
@@ -189,6 +189,14 @@ protected:
 
   PacketResult Handle_QSaveRegisterState(StringExtractorGDBRemote &packet);
 
+  PacketResult Handle_jTraceStart(StringExtractorGDBRemote &packet);
+
+  PacketResult Handle_jTraceRead(StringExtractorGDBRemote &packet);
+
+  PacketResult Handle_jTraceStop(StringExtractorGDBRemote &packet);
+
+  PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet);
+
   PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet);
 
   PacketResult Handle_vAttach(StringExtractorGDBRemote &packet);

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Fri May 26 06:46:27 2017
@@ -1236,6 +1236,32 @@ Status ProcessGDBRemote::DoAttachToProce
   return error;
 }
 
+lldb::user_id_t ProcessGDBRemote::StartTrace(const TraceOptions &options,
+                                             Status &error) {
+  return m_gdb_comm.SendStartTracePacket(options, error);
+}
+
+Status ProcessGDBRemote::StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) {
+  return m_gdb_comm.SendStopTracePacket(uid, thread_id);
+}
+
+Status ProcessGDBRemote::GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                                 llvm::MutableArrayRef<uint8_t> &buffer,
+                                 size_t offset) {
+  return m_gdb_comm.SendGetDataPacket(uid, thread_id, buffer, offset);
+}
+
+Status ProcessGDBRemote::GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                                     llvm::MutableArrayRef<uint8_t> &buffer,
+                                     size_t offset) {
+  return m_gdb_comm.SendGetMetaDataPacket(uid, thread_id, buffer, offset);
+}
+
+Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid,
+                                        TraceOptions &options) {
+  return m_gdb_comm.SendGetTraceConfigPacket(uid, options);
+}
+
 void ProcessGDBRemote::DidExit() {
   // When we exit, disconnect from the GDB server communications
   m_gdb_comm.Disconnect();

Modified: lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h (original)
+++ lldb/trunk/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h Fri May 26 06:46:27 2017
@@ -31,6 +31,7 @@
 #include "lldb/Target/Thread.h"
 #include "lldb/Utility/ConstString.h"
 #include "lldb/Utility/Status.h"
+#include "lldb/Utility/StreamGDBRemote.h"
 #include "lldb/Utility/StreamString.h"
 #include "lldb/Utility/StringExtractor.h"
 #include "lldb/Utility/StringList.h"
@@ -177,6 +178,21 @@ public:
 
   Status GetWatchpointSupportInfo(uint32_t &num) override;
 
+  lldb::user_id_t StartTrace(const TraceOptions &options,
+                             Status &error) override;
+
+  Status StopTrace(lldb::user_id_t uid, lldb::tid_t thread_id) override;
+
+  Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                 llvm::MutableArrayRef<uint8_t> &buffer,
+                 size_t offset = 0) override;
+
+  Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                     llvm::MutableArrayRef<uint8_t> &buffer,
+                     size_t offset = 0) override;
+
+  Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override;
+
   Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override;
 
   bool StartNoticingNewThreads() override;

Modified: lldb/trunk/source/Utility/StringExtractor.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractor.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Utility/StringExtractor.cpp (original)
+++ lldb/trunk/source/Utility/StringExtractor.cpp Fri May 26 06:46:27 2017
@@ -280,6 +280,15 @@ uint64_t StringExtractor::GetHexMaxU64(b
   return result;
 }
 
+bool StringExtractor::ConsumeFront(const llvm::StringRef &str) {
+  llvm::StringRef S = GetStringRef();
+  if (!S.startswith(str))
+    return false;
+  else
+    m_index += str.size();
+  return true;
+}
+
 size_t StringExtractor::GetHexBytes(llvm::MutableArrayRef<uint8_t> dest,
                                     uint8_t fail_fill_value) {
   size_t bytes_extracted = 0;

Modified: lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp (original)
+++ lldb/trunk/source/Utility/StringExtractorGDBRemote.cpp Fri May 26 06:46:27 2017
@@ -286,6 +286,16 @@ StringExtractorGDBRemote::GetServerPacke
       return eServerPacketType_jSignalsInfo;
     if (PACKET_MATCHES("jThreadsInfo"))
       return eServerPacketType_jThreadsInfo;
+    if (PACKET_STARTS_WITH("jTraceBufferRead:"))
+      return eServerPacketType_jTraceBufferRead;
+    if (PACKET_STARTS_WITH("jTraceConfigRead:"))
+      return eServerPacketType_jTraceConfigRead;
+    if (PACKET_STARTS_WITH("jTraceMetaRead:"))
+      return eServerPacketType_jTraceMetaRead;
+    if (PACKET_STARTS_WITH("jTraceStart:"))
+      return eServerPacketType_jTraceStart;
+    if (PACKET_STARTS_WITH("jTraceStop:"))
+      return eServerPacketType_jTraceStop;
     break;
 
   case 'v':

Modified: lldb/trunk/source/Utility/StringExtractorGDBRemote.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Utility/StringExtractorGDBRemote.h?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/source/Utility/StringExtractorGDBRemote.h (original)
+++ lldb/trunk/source/Utility/StringExtractorGDBRemote.h Fri May 26 06:46:27 2017
@@ -164,6 +164,12 @@ public:
     eServerPacketType__M,
     eServerPacketType__m,
     eServerPacketType_notify, // '%' notification
+
+    eServerPacketType_jTraceStart,
+    eServerPacketType_jTraceBufferRead,
+    eServerPacketType_jTraceMetaRead,
+    eServerPacketType_jTraceStop,
+    eServerPacketType_jTraceConfigRead,
   };
 
   ServerPacketType GetServerPacketType() const;

Modified: lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp?rev=303972&r1=303971&r2=303972&view=diff
==============================================================================
--- lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp (original)
+++ lldb/trunk/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp Fri May 26 06:46:27 2017
@@ -13,6 +13,7 @@
 #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h"
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/StructuredData.h"
+#include "lldb/Core/TraceOptions.h"
 #include "lldb/Target/MemoryRegionInfo.h"
 #include "lldb/Utility/DataBuffer.h"
 
@@ -370,3 +371,227 @@ TEST_F(GDBRemoteCommunicationClientTest,
   HandlePacket(server, "qMemoryRegionInfo:4000", "start:4000;size:0000;");
   EXPECT_FALSE(result.get().Success());
 }
+
+TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) {
+  TestClient client;
+  MockServer server;
+  Connect(client, server);
+  if (HasFailure())
+    return;
+
+  TraceOptions options;
+  Status error;
+
+  options.setType(lldb::TraceType::eTraceTypeProcessorTrace);
+  options.setMetaDataBufferSize(8192);
+  options.setTraceBufferSize(8192);
+  options.setThreadID(0x23);
+
+  StructuredData::DictionarySP custom_params =
+      std::make_shared<StructuredData::Dictionary>();
+  custom_params->AddStringItem("tracetech", "intel-pt");
+  custom_params->AddIntegerItem("psb", 0x01);
+
+  options.setTraceParams(custom_params);
+
+  std::future<lldb::user_id_t> result = std::async(std::launch::async, [&] {
+    return client.SendStartTracePacket(options, error);
+  });
+
+  // Since the line is exceeding 80 characters.
+  std::string expected_packet1 =
+      R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" :)";
+  std::string expected_packet2 =
+      R"( {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})";
+  HandlePacket(server, (expected_packet1 + expected_packet2), "1");
+  ASSERT_TRUE(error.Success());
+  ASSERT_EQ(result.get(), 1);
+
+  error.Clear();
+  result = std::async(std::launch::async, [&] {
+    return client.SendStartTracePacket(options, error);
+  });
+
+  HandlePacket(server, (expected_packet1 + expected_packet2), "E23");
+  ASSERT_EQ(result.get(), LLDB_INVALID_UID);
+  ASSERT_FALSE(error.Success());
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendStopTracePacket) {
+  TestClient client;
+  MockServer server;
+  Connect(client, server);
+  if (HasFailure())
+    return;
+
+  lldb::tid_t thread_id = 0x23;
+  lldb::user_id_t trace_id = 3;
+
+  std::future<Status> result = std::async(std::launch::async, [&] {
+    return client.SendStopTracePacket(trace_id, thread_id);
+  });
+
+  const char *expected_packet =
+      R"(jTraceStop:{"threadid" : 35,"traceid" : 3})";
+  HandlePacket(server, expected_packet, "OK");
+  ASSERT_TRUE(result.get().Success());
+
+  result = std::async(std::launch::async, [&] {
+    return client.SendStopTracePacket(trace_id, thread_id);
+  });
+
+  HandlePacket(server, expected_packet, "E23");
+  ASSERT_FALSE(result.get().Success());
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendGetDataPacket) {
+  TestClient client;
+  MockServer server;
+  Connect(client, server);
+  if (HasFailure())
+    return;
+
+  lldb::tid_t thread_id = 0x23;
+  lldb::user_id_t trace_id = 3;
+
+  uint8_t buf[32] = {};
+  llvm::MutableArrayRef<uint8_t> buffer(buf, 32);
+  size_t offset = 0;
+
+  std::future<Status> result = std::async(std::launch::async, [&] {
+    return client.SendGetDataPacket(trace_id, thread_id, buffer, offset);
+  });
+
+  std::string expected_packet1 =
+      R"(jTraceBufferRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)";
+  std::string expected_packet2 = R"("traceid" : 3})";
+  HandlePacket(server, expected_packet1+expected_packet2, "123456");
+  ASSERT_TRUE(result.get().Success());
+  ASSERT_EQ(buffer.size(), 3);
+  ASSERT_EQ(buf[0], 0x12);
+  ASSERT_EQ(buf[1], 0x34);
+  ASSERT_EQ(buf[2], 0x56);
+
+  llvm::MutableArrayRef<uint8_t> buffer2(buf, 32);
+  result = std::async(std::launch::async, [&] {
+    return client.SendGetDataPacket(trace_id, thread_id, buffer2, offset);
+  });
+
+  HandlePacket(server, expected_packet1+expected_packet2, "E23");
+  ASSERT_FALSE(result.get().Success());
+  ASSERT_EQ(buffer2.size(), 0);
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendGetMetaDataPacket) {
+  TestClient client;
+  MockServer server;
+  Connect(client, server);
+  if (HasFailure())
+    return;
+
+  lldb::tid_t thread_id = 0x23;
+  lldb::user_id_t trace_id = 3;
+
+  uint8_t buf[32] = {};
+  llvm::MutableArrayRef<uint8_t> buffer(buf, 32);
+  size_t offset = 0;
+
+  std::future<Status> result = std::async(std::launch::async, [&] {
+    return client.SendGetMetaDataPacket(trace_id, thread_id, buffer, offset);
+  });
+
+  std::string expected_packet1 =
+      R"(jTraceMetaRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,)";
+  std::string expected_packet2 = R"("traceid" : 3})";
+  HandlePacket(server, expected_packet1+expected_packet2, "123456");
+  ASSERT_TRUE(result.get().Success());
+  ASSERT_EQ(buffer.size(), 3);
+  ASSERT_EQ(buf[0], 0x12);
+  ASSERT_EQ(buf[1], 0x34);
+  ASSERT_EQ(buf[2], 0x56);
+
+  llvm::MutableArrayRef<uint8_t> buffer2(buf, 32);
+  result = std::async(std::launch::async, [&] {
+    return client.SendGetMetaDataPacket(trace_id, thread_id, buffer2, offset);
+  });
+
+  HandlePacket(server, expected_packet1+expected_packet2, "E23");
+  ASSERT_FALSE(result.get().Success());
+  ASSERT_EQ(buffer2.size(), 0);
+}
+
+TEST_F(GDBRemoteCommunicationClientTest, SendGetTraceConfigPacket) {
+  TestClient client;
+  MockServer server;
+  Connect(client, server);
+  if (HasFailure())
+    return;
+
+  lldb::tid_t thread_id = 0x23;
+  lldb::user_id_t trace_id = 3;
+  TraceOptions options;
+  options.setThreadID(thread_id);
+
+  std::future<Status> result = std::async(std::launch::async, [&] {
+    return client.SendGetTraceConfigPacket(trace_id, options);
+  });
+
+  const char *expected_packet =
+      R"(jTraceConfigRead:{"threadid" : 35,"traceid" : 3})";
+  std::string response1 =
+      R"({"buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})";
+  std::string response2 =
+      R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+  HandlePacket(server, expected_packet, response1+response2);
+  ASSERT_TRUE(result.get().Success());
+  ASSERT_EQ(options.getTraceBufferSize(), 8192);
+  ASSERT_EQ(options.getMetaDataBufferSize(), 8192);
+  ASSERT_EQ(options.getType(), 1);
+
+  auto custom_params = options.getTraceParams();
+
+  uint64_t psb_value;
+  llvm::StringRef trace_tech_value;
+
+  ASSERT_TRUE(custom_params);
+  ASSERT_EQ(custom_params->GetType(), StructuredData::Type::eTypeDictionary);
+  ASSERT_TRUE(
+      custom_params->GetValueForKeyAsInteger<uint64_t>("psb", psb_value));
+  ASSERT_EQ(psb_value, 1);
+  ASSERT_TRUE(
+      custom_params->GetValueForKeyAsString("tracetech", trace_tech_value));
+  ASSERT_STREQ(trace_tech_value.data(), "intel-pt");
+
+  // Checking error response.
+  std::future<Status> result2 = std::async(std::launch::async, [&] {
+    return client.SendGetTraceConfigPacket(trace_id, options);
+  });
+
+  HandlePacket(server, expected_packet, "E23");
+  ASSERT_FALSE(result2.get().Success());
+
+  // Wrong JSON as response.
+  std::future<Status> result3 = std::async(std::launch::async, [&] {
+    return client.SendGetTraceConfigPacket(trace_id, options);
+  });
+
+  std::string incorrect_json1 =
+      R"("buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"})";
+  std::string incorrect_json2 =
+      R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+  HandlePacket(server, expected_packet, incorrect_json1+incorrect_json2);
+  ASSERT_FALSE(result3.get().Success());
+
+  // Wrong JSON as custom_params.
+  std::future<Status> result4 = std::async(std::launch::async, [&] {
+    return client.SendGetTraceConfigPacket(trace_id, options);
+  });
+
+  std::string incorrect_custom_params1 =
+      R"({"buffersize" : 8192,"params" : "psb" : 1,"tracetech" : "intel-pt"})";
+  std::string incorrect_custom_params2 =
+      R"(],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+  HandlePacket(server, expected_packet, incorrect_custom_params1+
+      incorrect_custom_params2);
+  ASSERT_FALSE(result4.get().Success());
+}
\ No newline at end of file




More information about the lldb-commits mailing list