ravitheja updated this revision to Diff 99891.
ravitheja added a comment.

Modifying string literals in Unit tests.


https://reviews.llvm.org/D32585

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

Index: unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
===================================================================
--- unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
+++ unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
@@ -14,6 +14,7 @@
 #include "lldb/Core/ModuleSpec.h"
 #include "lldb/Core/StructuredData.h"
 #include "lldb/Target/MemoryRegionInfo.h"
+#include "lldb/Core/TraceOptions.h"
 #include "lldb/Utility/DataBuffer.h"
 
 #include "llvm/ADT/ArrayRef.h"
@@ -370,3 +371,205 @@
   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);
+  });
+
+  const char *expected_packet = R"(jTraceStart:{"buffersize" : 8192,"metabuffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"},"threadid" : 35,"type" : 1})";
+  HandlePacket(server, expected_packet, "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_packet, "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);
+  });
+
+  const char *expected_packet = R"(jTraceBufferRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,"traceid" : 3})";
+  HandlePacket(server, expected_packet, "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_packet, "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);
+  });
+
+  const char *expected_packet = R"(jTraceMetaRead:{"buffersize" : 32,"offset" : 0,"threadid" : 35,"traceid" : 3})";
+  HandlePacket(server, expected_packet, "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_packet, "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})";
+  const char *response = R"({"buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"}],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+  HandlePacket(server, expected_packet, response);
+  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);
+  });
+
+  const char *incorrect_json = R"("buffersize" : 8192,"params" : {"psb" : 1,"tracetech" : "intel-pt"}],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+  HandlePacket(server, expected_packet, incorrect_json);
+  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);
+  });
+
+  const char *incorrect_custom_params = R"({"buffersize" : 8192,"params" : "psb" : 1,"tracetech" : "intel-pt"}],"metabuffersize" : 8192,"threadid" : 35,"type" : 1}])";
+  HandlePacket(server, expected_packet, incorrect_custom_params);
+  ASSERT_FALSE(result4.get().Success());
+}
\ No newline at end of file
Index: source/Utility/StringExtractorGDBRemote.h
===================================================================
--- source/Utility/StringExtractorGDBRemote.h
+++ source/Utility/StringExtractorGDBRemote.h
@@ -164,6 +164,12 @@
     eServerPacketType__M,
     eServerPacketType__m,
     eServerPacketType_notify, // '%' notification
+
+    eServerPacketType_jTraceStart,
+    eServerPacketType_jTraceBufferRead,
+    eServerPacketType_jTraceMetaRead,
+    eServerPacketType_jTraceStop,
+    eServerPacketType_jTraceConfigRead,
   };
 
   ServerPacketType GetServerPacketType() const;
Index: source/Utility/StringExtractorGDBRemote.cpp
===================================================================
--- source/Utility/StringExtractorGDBRemote.cpp
+++ source/Utility/StringExtractorGDBRemote.cpp
@@ -286,6 +286,16 @@
       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':
Index: source/Utility/StringExtractor.cpp
===================================================================
--- source/Utility/StringExtractor.cpp
+++ source/Utility/StringExtractor.cpp
@@ -280,6 +280,15 @@
   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;
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.h
@@ -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 @@
 
   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;
Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
+++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp
@@ -1236,6 +1236,32 @@
   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();
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h
@@ -189,6 +189,14 @@
 
   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);
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp
@@ -183,6 +183,22 @@
       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,229 @@
 }
 
 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.
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h
@@ -24,6 +24,7 @@
 // Project includes
 #include "lldb/Core/ArchSpec.h"
 #include "lldb/Core/StructuredData.h"
+#include "lldb/Utility/StreamGDBRemote.h"
 #include "lldb/Target/Process.h"
 
 #include "llvm/ADT/Optional.h"
@@ -499,6 +500,20 @@
   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 +602,10 @@
       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);
 };
Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
===================================================================
--- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
+++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp
@@ -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,202 @@
          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) {
Index: source/API/SBTrace.cpp
===================================================================
--- source/API/SBTrace.cpp
+++ source/API/SBTrace.cpp
@@ -25,37 +25,37 @@
 
 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 @@
     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 @@
   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)));
   }
 }
 
Index: source/API/SBProcess.cpp
===================================================================
--- source/API/SBProcess.cpp
+++ source/API/SBProcess.cpp
@@ -363,10 +363,9 @@
   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;
 }
Index: include/lldb/Utility/StringExtractor.h
===================================================================
--- include/lldb/Utility/StringExtractor.h
+++ include/lldb/Utility/StringExtractor.h
@@ -111,6 +111,8 @@
 
   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;
Index: include/lldb/Target/Process.h
===================================================================
--- include/lldb/Target/Process.h
+++ include/lldb/Target/Process.h
@@ -2781,7 +2781,7 @@
   /// 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 @@
   /// 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 @@
   /// 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,
-                         size_t offset = 0) {
-    error.SetErrorString("Not implemented");
-    return 0;
+  virtual Status GetData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                        llvm::MutableArrayRef<uint8_t> &buffer,
+                        size_t offset = 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,
-                             size_t offset = 0) {
-    error.SetErrorString("Not implemented");
-    return 0;
+  virtual Status GetMetaData(lldb::user_id_t uid, lldb::tid_t thread_id,
+                            llvm::MutableArrayRef<uint8_t> &buffer,
+                            size_t offset = 0) {
+    return Status("Not implemented");
   }
 
   //------------------------------------------------------------------
@@ -2835,10 +2832,8 @@
   /// 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:
Index: include/lldb/Host/common/NativeProcessProtocol.h
===================================================================
--- include/lldb/Host/common/NativeProcessProtocol.h
+++ include/lldb/Host/common/NativeProcessProtocol.h
@@ -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,107 @@
   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;
 
Index: include/lldb/Core/TraceOptions.h
===================================================================
--- include/lldb/Core/TraceOptions.h
+++ include/lldb/Core/TraceOptions.h
@@ -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 @@
 
   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;
Index: include/lldb/API/SBTrace.h
===================================================================
--- include/lldb/API/SBTrace.h
+++ include/lldb/API/SBTrace.h
@@ -40,7 +40,7 @@
   ///
   /// @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 @@
   ///     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.
   //------------------------------------------------------------------
Index: docs/lldb-gdb-remote.txt
===================================================================
--- docs/lldb-gdb-remote.txt
+++ docs/lldb-gdb-remote.txt
@@ -209,6 +209,163 @@
 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
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to