From 21555fff4de811309ea7935f9cb65578c957d77f Mon Sep 17 00:00:00 2001 From: Walter Erquinigo Date: Thu, 29 Oct 2020 12:44:13 -0700 Subject: [PATCH] [intel-pt][trace] Implement a "get supported trace type" packet Depends on D89283. The goal of this packet (jTraceGetSupportedType) is to be able to query the gdb-server for the tracing technology that can work for the current debuggeer, which can make the user experience simpler but allowing the user to simply type thread trace start to start tracing the current thread without even telling the debugger to use "intel-pt", for example. Similarly, `thread trace start [args...]` would accept args beloging to the working trace type. Also, if the user typed help thread trace start We could directly show the help information of the trace type that is supported for the target, or mention instead that no tracing is supported, if that's the case. I added some simple tests, besides, when I ran this on my machine with intel-pt support, I got $ process plugin packet send "jTraceSupportedType" packet: jTraceSupportedType response: {"description":"Intel Processor Trace","pluginName":"intel-pt"} On a machine without intel-pt support, I got $ process plugin packet send "jTraceSupportedType" packet: jTraceSupportedType response: E00; Reviewed By: clayborg, labath Differential Revision: https://reviews.llvm.org/D90490 --- lldb/docs/lldb-gdb-remote.txt | 37 ++++++++++++++ .../lldb/Host/common/NativeProcessProtocol.h | 5 ++ lldb/include/lldb/Target/Process.h | 13 +++++ lldb/include/lldb/Target/Trace.h | 4 ++ .../lldb/Utility/StringExtractorGDBRemote.h | 12 +++-- lldb/include/lldb/Utility/TraceOptions.h | 21 ++++++++ lldb/include/lldb/lldb-enumerations.h | 3 +- .../Plugins/Process/Linux/NativeProcessLinux.cpp | 6 +++ .../Plugins/Process/Linux/NativeProcessLinux.h | 2 + .../Plugins/Process/Linux/ProcessorTrace.cpp | 43 ++++++++++------ lldb/source/Plugins/Process/Linux/ProcessorTrace.h | 4 ++ .../gdb-remote/GDBRemoteCommunicationClient.cpp | 26 ++++++++++ .../gdb-remote/GDBRemoteCommunicationClient.h | 3 ++ .../GDBRemoteCommunicationServerLLGS.cpp | 30 ++++++++++++ .../gdb-remote/GDBRemoteCommunicationServerLLGS.h | 2 + .../Process/gdb-remote/ProcessGDBRemote.cpp | 4 ++ .../Plugins/Process/gdb-remote/ProcessGDBRemote.h | 2 + lldb/source/Utility/CMakeLists.txt | 1 + lldb/source/Utility/StringExtractorGDBRemote.cpp | 2 + lldb/source/Utility/TraceOptions.cpp | 25 ++++++++++ .../GDBRemoteCommunicationClientTest.cpp | 57 ++++++++++++++++++++++ 21 files changed, 281 insertions(+), 21 deletions(-) create mode 100644 lldb/source/Utility/TraceOptions.cpp diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index 276beed..91f6a4d 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -235,8 +235,37 @@ send packet: QListThreadsInStopReply read packet: OK //---------------------------------------------------------------------- +// jLLDBTraceSupportedType +// +// BRIEF +// Get the processor tracing type supported by the gdb-server for the current +// inferior. Responses might be different depending on the architecture and +// capabilities of the underlying OS. +// +// The return packet is a JSON object with the following schema +// +// { +// "name": +// "description": +// } +// +// If no tracing technology is supported for the inferior, or no process is +// running, then an error should be returned. +// +// NOTE +// This packet is used by Trace plug-ins (see lldb_private::Trace.h) to +// do live tracing. Specifically, the name of the plug-in should match the name +// of the tracing technology returned by this packet. +//---------------------------------------------------------------------- + +send packet: jLLDBTraceSupportedType +read packet: {"name": , "description", }/E;AAAAAAAAA + +//---------------------------------------------------------------------- // jTraceStart: // +// This packet is deprecated. +// // BRIEF // Packet for starting trace of type lldb::TraceType. The following // parameters should be appended to the packet formatted as a JSON @@ -286,6 +315,8 @@ read packet: /E;AAAAAAAAA //---------------------------------------------------------------------- // jTraceStop: // +// This packet is deprecated. +// // BRIEF // Stop tracing instance with trace id , of course trace // needs to be started before. The following parameters should be @@ -320,6 +351,8 @@ read packet: /E;AAAAAAAAA //---------------------------------------------------------------------- // jTraceBufferRead: // +// This packet is deprecated. +// // BRIEF // Packet for reading the trace for tracing instance , i.e the // id obtained from StartTrace API. The following parameters should be @@ -353,6 +386,8 @@ read packet: /E;AAAAAAAAA //---------------------------------------------------------------------- // jTraceMetaRead: // +// This packet is deprecated. +// // BRIEF // Similar Packet as above except it reads meta data. //---------------------------------------------------------------------- @@ -360,6 +395,8 @@ read packet: /E;AAAAAAAAA /---------------------------------------------------------------------- // jTraceConfigRead: // +// This packet is deprecated. +// // BRIEF // Request the trace configuration for the tracing instance with id // . diff --git a/lldb/include/lldb/Host/common/NativeProcessProtocol.h b/lldb/include/lldb/Host/common/NativeProcessProtocol.h index 8bdad59..5be9cb6 100644 --- a/lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ b/lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -392,6 +392,11 @@ public: return Status("Not implemented"); } + /// \copydoc Process::GetSupportedTraceType() + virtual llvm::Expected GetSupportedTraceType() { + return llvm::make_error(); + } + protected: struct SoftwareBreakpoint { uint32_t ref_count; diff --git a/lldb/include/lldb/Target/Process.h b/lldb/include/lldb/Target/Process.h index 90172f3..a1a9760 100644 --- a/lldb/include/lldb/Target/Process.h +++ b/lldb/include/lldb/Target/Process.h @@ -38,6 +38,7 @@ #include "lldb/Target/QueueList.h" #include "lldb/Target/ThreadList.h" #include "lldb/Target/ThreadPlanStack.h" +#include "lldb/Target/Trace.h" #include "lldb/Utility/ArchSpec.h" #include "lldb/Utility/Broadcaster.h" #include "lldb/Utility/Event.h" @@ -47,6 +48,7 @@ #include "lldb/Utility/Status.h" #include "lldb/Utility/StructuredData.h" #include "lldb/Utility/TraceOptions.h" +#include "lldb/Utility/UnimplementedError.h" #include "lldb/Utility/UserIDResolver.h" #include "lldb/lldb-private.h" @@ -2542,6 +2544,17 @@ void PruneThreadPlans(); return Status("Not implemented"); } + /// Get the processor tracing type supported for this process. + /// Responses might be different depending on the architecture and + /// capabilities of the underlying OS. + /// + /// \return + /// The supported trace type or an \a llvm::Error if tracing is + /// not supported for the inferior. + virtual llvm::Expected GetSupportedTraceType() { + return llvm::make_error(); + } + // This calls a function of the form "void * (*)(void)". bool CallVoidArgVoidPtrReturn(const Address *address, lldb::addr_t &returned_func, diff --git a/lldb/include/lldb/Target/Trace.h b/lldb/include/lldb/Target/Trace.h index 56e77d8..632a7b8 100644 --- a/lldb/include/lldb/Target/Trace.h +++ b/lldb/include/lldb/Target/Trace.h @@ -32,6 +32,10 @@ namespace lldb_private { /// Processor trace information can also be fetched through the process /// interfaces during a live debug session if your process supports gathering /// this information. +/// +/// In order to support live tracing, the name of the plug-in should match the +/// name of the tracing type returned by the gdb-remote packet +/// \a jLLDBTraceSupportedType. class Trace : public PluginInterface, public std::enable_shared_from_this { public: diff --git a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h index efb4376..3b6ed80 100644 --- a/lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ b/lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -162,11 +162,13 @@ public: eServerPacketType__m, eServerPacketType_notify, // '%' notification - eServerPacketType_jTraceStart, - eServerPacketType_jTraceBufferRead, - eServerPacketType_jTraceMetaRead, - eServerPacketType_jTraceStop, - eServerPacketType_jTraceConfigRead, + eServerPacketType_jTraceStart, // deprecated + eServerPacketType_jTraceBufferRead, // deprecated + eServerPacketType_jTraceMetaRead, // deprecated + eServerPacketType_jTraceStop, // deprecated + eServerPacketType_jTraceConfigRead, // deprecated + + eServerPacketType_jLLDBTraceSupportedType, }; ServerPacketType GetServerPacketType() const; diff --git a/lldb/include/lldb/Utility/TraceOptions.h b/lldb/include/lldb/Utility/TraceOptions.h index 97aad33..c9a8d12 100644 --- a/lldb/include/lldb/Utility/TraceOptions.h +++ b/lldb/include/lldb/Utility/TraceOptions.h @@ -15,6 +15,19 @@ #include "lldb/Utility/StructuredData.h" namespace lldb_private { + +/// This struct represents a tracing technology. +struct TraceTypeInfo { + /// The name of the technology, e.g. intel-pt or arm-coresight. + /// + /// In order for a Trace plug-in (see \a lldb_private::Trace.h) to support the + /// trace technology given by this struct, it should match its name with this + /// field. + std::string name; + /// A description for the technology. + std::string description; +}; + class TraceOptions { public: TraceOptions() : m_trace_params(new StructuredData::Dictionary()) {} @@ -57,4 +70,12 @@ private: }; } +namespace llvm { +namespace json { + +bool fromJSON(const Value &value, lldb_private::TraceTypeInfo &info, Path path); + +} // namespace json +} // namespace llvm + #endif // LLDB_UTILITY_TRACEOPTIONS_H diff --git a/lldb/include/lldb/lldb-enumerations.h b/lldb/include/lldb/lldb-enumerations.h index 8692dd8..061f385 100644 --- a/lldb/include/lldb/lldb-enumerations.h +++ b/lldb/include/lldb/lldb-enumerations.h @@ -769,10 +769,11 @@ enum BasicType { eBasicTypeOther }; +/// Deprecated enum TraceType { eTraceTypeNone = 0, - // Hardware Trace generated by the processor. + /// Intel Processor Trace eTraceTypeProcessorTrace }; diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp index 5d28737..9883e1c 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1995,6 +1995,12 @@ Status NativeProcessLinux::GetTraceConfig(lldb::user_id_t traceid, return error; } +llvm::Expected NativeProcessLinux::GetSupportedTraceType() { + if (ProcessorTraceMonitor::IsSupported()) + return TraceTypeInfo{"intel-pt", "Intel Processor Trace"}; + return NativeProcessProtocol::GetSupportedTraceType(); +} + lldb::user_id_t NativeProcessLinux::StartTraceGroup(const TraceOptions &config, Status &error) { diff --git a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h index ba953d3..b7d70a6 100644 --- a/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ b/lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -117,6 +117,8 @@ public: Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) override; + virtual llvm::Expected GetSupportedTraceType() override; + // Interface used by NativeRegisterContext-derived classes. static Status PtraceWrapper(int req, lldb::pid_t pid, void *addr = nullptr, void *data = nullptr, size_t data_size = 0, diff --git a/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp b/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp index 9bb01f2..1a8aa36 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp +++ b/lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp @@ -26,6 +26,8 @@ using namespace process_linux; using namespace llvm; lldb::user_id_t ProcessorTraceMonitor::m_trace_num = 1; +const char *kOSEventIntelPTTypeFile = + "/sys/bus/event_source/devices/intel_pt/type"; Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const { #ifndef PERF_ATTR_SIZE_VER5 @@ -44,6 +46,27 @@ Status ProcessorTraceMonitor::GetTraceConfig(TraceOptions &config) const { #endif } +Expected ProcessorTraceMonitor::GetOSEventType() { + auto intel_pt_type_text = + llvm::MemoryBuffer::getFileAsStream(kOSEventIntelPTTypeFile); + + if (!intel_pt_type_text) + return createStringError(inconvertibleErrorCode(), + "Can't open the file '%s'", + kOSEventIntelPTTypeFile); + + uint32_t intel_pt_type = 0; + StringRef buffer = intel_pt_type_text.get()->getBuffer(); + if (buffer.trim().getAsInteger(10, intel_pt_type)) + return createStringError( + inconvertibleErrorCode(), + "The file '%s' has a invalid value. It should be an unsigned int.", + kOSEventIntelPTTypeFile); + return intel_pt_type; +} + +bool ProcessorTraceMonitor::IsSupported() { return (bool)GetOSEventType(); } + Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, const TraceOptions &config) { #ifndef PERF_ATTR_SIZE_VER5 @@ -76,25 +99,15 @@ Status ProcessorTraceMonitor::StartTrace(lldb::pid_t pid, lldb::tid_t tid, attr.exclude_idle = 1; attr.mmap = 1; - int intel_pt_type = 0; - - auto ret = llvm::MemoryBuffer::getFileAsStream( - "/sys/bus/event_source/devices/intel_pt/type"); - if (!ret) { - LLDB_LOG(log, "failed to open Config file"); - return ret.getError(); - } + Expected intel_pt_type = GetOSEventType(); - StringRef rest = ret.get()->getBuffer(); - if (rest.empty() || rest.trim().getAsInteger(10, intel_pt_type)) { - LLDB_LOG(log, "failed to read Config file"); - error.SetErrorString("invalid file"); + if (!intel_pt_type) { + error = intel_pt_type.takeError(); return error; } - rest.trim().getAsInteger(10, intel_pt_type); - LLDB_LOG(log, "intel pt type {0}", intel_pt_type); - attr.type = intel_pt_type; + LLDB_LOG(log, "intel pt type {0}", *intel_pt_type); + attr.type = *intel_pt_type; LLDB_LOG(log, "meta buffer size {0}", metabufsize); LLDB_LOG(log, "buffer size {0} ", bufsize); diff --git a/lldb/source/Plugins/Process/Linux/ProcessorTrace.h b/lldb/source/Plugins/Process/Linux/ProcessorTrace.h index de9bd8c..29f98cc 100644 --- a/lldb/source/Plugins/Process/Linux/ProcessorTrace.h +++ b/lldb/source/Plugins/Process/Linux/ProcessorTrace.h @@ -93,6 +93,10 @@ class ProcessorTraceMonitor { void SetThreadID(lldb::tid_t tid) { m_thread_id = tid; } public: + static llvm::Expected GetOSEventType(); + + static bool IsSupported(); + static Status GetCPUType(TraceOptions &config); static llvm::Expected diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index dd0f698..d661423 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -3454,6 +3454,32 @@ Status GDBRemoteCommunicationClient::SendGetMetaDataPacket( return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); } +llvm::Expected +GDBRemoteCommunicationClient::SendGetSupportedTraceType() { + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PROCESS)); + + StreamGDBRemote escaped_packet; + escaped_packet.PutCString("jLLDBTraceSupportedType"); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(escaped_packet.GetString(), response, + true) == + GDBRemoteCommunication::PacketResult::Success) { + if (!response.IsNormalResponse()) + return response.GetStatus().ToError(); + + if (llvm::Expected type = + llvm::json::parse(response.Peek())) + return *type; + else + return type.takeError(); + } + LLDB_LOG(log, "failed to send packet: jLLDBTraceSupportedType"); + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "failed to send packet: jLLDBTraceSupportedType"); +} + Status GDBRemoteCommunicationClient::SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 61acfad..af3755f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -22,6 +22,7 @@ #include "lldb/Utility/GDBRemote.h" #include "lldb/Utility/ProcessInfo.h" #include "lldb/Utility/StructuredData.h" +#include "lldb/Utility/TraceOptions.h" #if defined(_WIN32) #include "lldb/Host/windows/PosixApi.h" #endif @@ -519,6 +520,8 @@ public: Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options); + llvm::Expected SendGetSupportedTraceType(); + protected: LazyBool m_supports_not_sending_acks; LazyBool m_supports_thread_suffix; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp index 02b6ca4..2e57d7e 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -191,6 +191,9 @@ void GDBRemoteCommunicationServerLLGS::RegisterPacketHandlers() { RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupportedType, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, &GDBRemoteCommunicationServerLLGS::Handle_g); @@ -1227,6 +1230,33 @@ GDBRemoteCommunicationServerLLGS::Handle_jTraceStop( } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType( + StringExtractorGDBRemote &packet) { + + // Fail if we don't have a current process. + if (!m_debugged_process_up || + (m_debugged_process_up->GetID() == LLDB_INVALID_PROCESS_ID)) + return SendErrorResponse(Status("Process not running.")); + + llvm::Expected supported_trace_type = + m_debugged_process_up->GetSupportedTraceType(); + if (!supported_trace_type) + return SendErrorResponse(supported_trace_type.takeError()); + + StreamGDBRemote escaped_response; + StructuredData::Dictionary json_packet; + + json_packet.AddStringItem("name", supported_trace_type->name); + json_packet.AddStringItem("description", supported_trace_type->description); + + 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_jTraceConfigRead( StringExtractorGDBRemote &packet) { diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h index 2a2f4ad..ae8928c 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -164,6 +164,8 @@ protected: PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceSupportedType(StringExtractorGDBRemote &packet); + PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index e8cc90e..0cd97ab 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1224,6 +1224,10 @@ Status ProcessGDBRemote::GetTraceConfig(lldb::user_id_t uid, return m_gdb_comm.SendGetTraceConfigPacket(uid, options); } +llvm::Expected ProcessGDBRemote::GetSupportedTraceType() { + return m_gdb_comm.SendGetSupportedTraceType(); +} + void ProcessGDBRemote::DidExit() { // When we exit, disconnect from the GDB server communications m_gdb_comm.Disconnect(); diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index ba96772..e47300f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -175,6 +175,8 @@ public: llvm::MutableArrayRef &buffer, size_t offset = 0) override; + llvm::Expected GetSupportedTraceType() override; + Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override; Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override; diff --git a/lldb/source/Utility/CMakeLists.txt b/lldb/source/Utility/CMakeLists.txt index 8757381..3aca72d 100644 --- a/lldb/source/Utility/CMakeLists.txt +++ b/lldb/source/Utility/CMakeLists.txt @@ -65,6 +65,7 @@ add_lldb_library(lldbUtility StructuredData.cpp TildeExpressionResolver.cpp Timer.cpp + TraceOptions.cpp UnimplementedError.cpp UUID.cpp UriParser.cpp diff --git a/lldb/source/Utility/StringExtractorGDBRemote.cpp b/lldb/source/Utility/StringExtractorGDBRemote.cpp index 2901500..def0968 100644 --- a/lldb/source/Utility/StringExtractorGDBRemote.cpp +++ b/lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -310,6 +310,8 @@ StringExtractorGDBRemote::GetServerPacketType() const { return eServerPacketType_jTraceStart; if (PACKET_STARTS_WITH("jTraceStop:")) return eServerPacketType_jTraceStop; + if (PACKET_MATCHES("jLLDBTraceSupportedType")) + return eServerPacketType_jLLDBTraceSupportedType; break; case 'v': diff --git a/lldb/source/Utility/TraceOptions.cpp b/lldb/source/Utility/TraceOptions.cpp new file mode 100644 index 0000000..292fb60 --- /dev/null +++ b/lldb/source/Utility/TraceOptions.cpp @@ -0,0 +1,25 @@ +//===-- TraceOptions.cpp ----------------------------------------*- C++ -*-===// +// +// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. +// See https://llvm.org/LICENSE.txt for license information. +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +// +//===----------------------------------------------------------------------===// + +#include "lldb/Utility/TraceOptions.h" + +using namespace lldb_private; + +namespace llvm { +namespace json { + +bool fromJSON(const Value &value, TraceTypeInfo &info, Path path) { + ObjectMapper o(value, path); + if (!o) + return false; + o.map("description", info.description); + return o.map("name", info.name); +} + +} // namespace json +} // namespace llvm diff --git a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp index 6fba1cb..d4f7b25 100644 --- a/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ b/lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -362,6 +362,63 @@ TEST_F(GDBRemoteCommunicationClientTest, GetMemoryRegionInfoInvalidResponse) { EXPECT_FALSE(result.get().Success()); } +TEST_F(GDBRemoteCommunicationClientTest, SendTraceSupportedTypePacket) { + // Success response + { + std::future> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket( + server, "jLLDBTraceSupportedType", + R"({"name":"intel-pt","description":"Intel Processor Trace"}])"); + + llvm::Expected trace_type_or_err = result.get(); + EXPECT_THAT_EXPECTED(trace_type_or_err, llvm::Succeeded()); + ASSERT_STREQ(trace_type_or_err->name.c_str(), "intel-pt"); + ASSERT_STREQ(trace_type_or_err->description.c_str(), + "Intel Processor Trace"); + } + + // Error response - wrong json + { + std::future> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket(server, "jLLDBTraceSupportedType", R"({"type":"intel-pt"}])"); + + llvm::Expected trace_type_or_err = result.get(); + ASSERT_THAT_EXPECTED( + trace_type_or_err, + llvm::Failed(testing::Property( + &StringError::getMessage, + testing::HasSubstr("missing value at (root).name")))); + } + + // Error response + { + std::future> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket(server, "jLLDBTraceSupportedType", "E23"); + llvm::Expected trace_type_or_err = result.get(); + ASSERT_THAT_EXPECTED(trace_type_or_err, llvm::Failed()); + } + + // Error response with error message + { + std::future> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket(server, "jLLDBTraceSupportedType", + "E23;50726F63657373206E6F742072756E6E696E672E"); + llvm::Expected trace_type_or_err = result.get(); + ASSERT_THAT_EXPECTED(trace_type_or_err, + llvm::Failed(testing::Property( + &StringError::getMessage, + testing::HasSubstr("Process not running.")))); + } +} + TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) { TraceOptions options; Status error; -- 2.7.4