wallace updated this revision to Diff 303313. wallace marked 5 inline comments as done. wallace added a comment.
Address all comments, specially improved the documentation requested by @clayborg. Repository: rG LLVM Github Monorepo CHANGES SINCE LAST ACTION https://reviews.llvm.org/D90490/new/ https://reviews.llvm.org/D90490 Files: lldb/docs/lldb-gdb-remote.txt lldb/include/lldb/Host/common/NativeProcessProtocol.h lldb/include/lldb/Target/Process.h lldb/include/lldb/Target/Trace.h lldb/include/lldb/Utility/StringExtractorGDBRemote.h lldb/include/lldb/Utility/TraceOptions.h lldb/include/lldb/lldb-enumerations.h lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp lldb/source/Plugins/Process/Linux/NativeProcessLinux.h lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp lldb/source/Plugins/Process/Linux/ProcessorTrace.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h lldb/source/Utility/CMakeLists.txt lldb/source/Utility/StringExtractorGDBRemote.cpp lldb/source/Utility/TraceOptions.cpp lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
Index: lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp =================================================================== --- lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ lldb/unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -362,6 +362,45 @@ EXPECT_FALSE(result.get().Success()); } +TEST_F(GDBRemoteCommunicationClientTest, SendTraceSupportedTypePacket) { + // Success response + { + std::future<llvm::Expected<TraceTypeInfo>> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket( + server, "jLLDBTraceSupportedType", + R"({"name":"intel-pt","description":"Intel Processor Trace"}])"); + + llvm::Expected<TraceTypeInfo> 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<llvm::Expected<TraceTypeInfo>> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket(server, "jLLDBTraceSupportedType", R"({"type":"intel-pt"}])"); + + llvm::Expected<TraceTypeInfo> trace_type_or_err = result.get(); + EXPECT_THAT_EXPECTED(trace_type_or_err, llvm::Failed()); + } + + // Error response + { + std::future<llvm::Expected<TraceTypeInfo>> result = std::async( + std::launch::async, [&] { return client.SendGetSupportedTraceType(); }); + + HandlePacket(server, "jLLDBTraceSupportedType", "E23"); + llvm::Expected<TraceTypeInfo> trace_type_or_err = result.get(); + ASSERT_THAT_EXPECTED(trace_type_or_err, llvm::Failed()); + } +} + TEST_F(GDBRemoteCommunicationClientTest, SendStartTracePacket) { TraceOptions options; Status error; Index: lldb/source/Utility/TraceOptions.cpp =================================================================== --- /dev/null +++ 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 Index: lldb/source/Utility/StringExtractorGDBRemote.cpp =================================================================== --- lldb/source/Utility/StringExtractorGDBRemote.cpp +++ lldb/source/Utility/StringExtractorGDBRemote.cpp @@ -310,6 +310,8 @@ return eServerPacketType_jTraceStart; if (PACKET_STARTS_WITH("jTraceStop:")) return eServerPacketType_jTraceStop; + if (PACKET_MATCHES("jLLDBTraceSupportedType")) + return eServerPacketType_jLLDBTraceSupportedType; break; case 'v': Index: lldb/source/Utility/CMakeLists.txt =================================================================== --- lldb/source/Utility/CMakeLists.txt +++ lldb/source/Utility/CMakeLists.txt @@ -65,6 +65,7 @@ StructuredData.cpp TildeExpressionResolver.cpp Timer.cpp + TraceOptions.cpp UnimplementedError.cpp UUID.cpp UriParser.cpp Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -175,6 +175,8 @@ llvm::MutableArrayRef<uint8_t> &buffer, size_t offset = 0) override; + llvm::Expected<TraceTypeInfo> GetSupportedTraceType() override; + Status GetTraceConfig(lldb::user_id_t uid, TraceOptions &options) override; Status GetWatchpointSupportInfo(uint32_t &num, bool &after) override; Index: lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1224,6 +1224,10 @@ return m_gdb_comm.SendGetTraceConfigPacket(uid, options); } +llvm::Expected<TraceTypeInfo> ProcessGDBRemote::GetSupportedTraceType() { + return m_gdb_comm.SendGetSupportedTraceType(); +} + void ProcessGDBRemote::DidExit() { // When we exit, disconnect from the GDB server communications m_gdb_comm.Disconnect(); Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -164,6 +164,8 @@ PacketResult Handle_jTraceConfigRead(StringExtractorGDBRemote &packet); + PacketResult Handle_jLLDBTraceSupportedType(StringExtractorGDBRemote &packet); + PacketResult Handle_QRestoreRegisterState(StringExtractorGDBRemote &packet); PacketResult Handle_vAttach(StringExtractorGDBRemote &packet); Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -191,6 +191,9 @@ RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_jTraceConfigRead, &GDBRemoteCommunicationServerLLGS::Handle_jTraceConfigRead); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jLLDBTraceSupportedType, + &GDBRemoteCommunicationServerLLGS::Handle_jLLDBTraceSupportedType); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_g, &GDBRemoteCommunicationServerLLGS::Handle_g); @@ -1226,6 +1229,33 @@ return SendOKResponse(); } +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(68); + + llvm::Expected<TraceTypeInfo> supported_trace_type = + m_debugged_process_up->GetSupportedTraceType(); + if (!supported_trace_type) + return SendErrorResponse(Status(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) { Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ 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 @@ Status SendGetTraceConfigPacket(lldb::user_id_t uid, TraceOptions &options); + llvm::Expected<TraceTypeInfo> SendGetSupportedTraceType(); + protected: LazyBool m_supports_not_sending_acks; LazyBool m_supports_thread_suffix; Index: lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -3454,6 +3454,32 @@ return SendGetTraceDataPacket(escaped_packet, uid, thread_id, buffer, offset); } +llvm::Expected<TraceTypeInfo> +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()) { + if (llvm::Expected<TraceTypeInfo> type = + llvm::json::parse<TraceTypeInfo>(response.Peek())) + return *type; + else + return type.takeError(); + } else + return response.GetStatus().ToError(); + } + 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) { Index: lldb/source/Plugins/Process/Linux/ProcessorTrace.h =================================================================== --- lldb/source/Plugins/Process/Linux/ProcessorTrace.h +++ lldb/source/Plugins/Process/Linux/ProcessorTrace.h @@ -93,6 +93,10 @@ void SetThreadID(lldb::tid_t tid) { m_thread_id = tid; } public: + static llvm::Expected<uint32_t> GetOSEventType(); + + static bool IsSupported(); + static Status GetCPUType(TraceOptions &config); static llvm::Expected<ProcessorTraceMonitorUP> Index: lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp +++ lldb/source/Plugins/Process/Linux/ProcessorTrace.cpp @@ -26,6 +26,8 @@ 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 @@ #endif } +Expected<uint32_t> 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 @@ 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<uint32_t> 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); Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- lldb/source/Plugins/Process/Linux/NativeProcessLinux.h +++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.h @@ -117,6 +117,8 @@ Status GetTraceConfig(lldb::user_id_t traceid, TraceOptions &config) override; + virtual llvm::Expected<TraceTypeInfo> 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, Index: lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -1995,6 +1995,12 @@ return error; } +llvm::Expected<TraceTypeInfo> 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) { Index: lldb/include/lldb/lldb-enumerations.h =================================================================== --- lldb/include/lldb/lldb-enumerations.h +++ lldb/include/lldb/lldb-enumerations.h @@ -769,10 +769,11 @@ eBasicTypeOther }; +/// Deprecated enum TraceType { eTraceTypeNone = 0, - // Hardware Trace generated by the processor. + /// Intel Processor Trace eTraceTypeProcessorTrace }; Index: lldb/include/lldb/Utility/TraceOptions.h =================================================================== --- lldb/include/lldb/Utility/TraceOptions.h +++ 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 @@ }; } +namespace llvm { +namespace json { + +bool fromJSON(const Value &value, lldb_private::TraceTypeInfo &info, Path path); + +} // namespace json +} // namespace llvm + #endif // LLDB_UTILITY_TRACEOPTIONS_H Index: lldb/include/lldb/Utility/StringExtractorGDBRemote.h =================================================================== --- lldb/include/lldb/Utility/StringExtractorGDBRemote.h +++ lldb/include/lldb/Utility/StringExtractorGDBRemote.h @@ -162,11 +162,13 @@ 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; Index: lldb/include/lldb/Target/Trace.h =================================================================== --- lldb/include/lldb/Target/Trace.h +++ lldb/include/lldb/Target/Trace.h @@ -32,6 +32,10 @@ /// 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<Trace> { public: Index: lldb/include/lldb/Target/Process.h =================================================================== --- lldb/include/lldb/Target/Process.h +++ 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 @@ 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<TraceTypeInfo> GetSupportedTraceType() { + return llvm::make_error<UnimplementedError>(); + } + // This calls a function of the form "void * (*)(void)". bool CallVoidArgVoidPtrReturn(const Address *address, lldb::addr_t &returned_func, Index: lldb/include/lldb/Host/common/NativeProcessProtocol.h =================================================================== --- lldb/include/lldb/Host/common/NativeProcessProtocol.h +++ lldb/include/lldb/Host/common/NativeProcessProtocol.h @@ -392,6 +392,11 @@ return Status("Not implemented"); } + /// \copydoc Process::GetSupportedTraceType() + virtual llvm::Expected<TraceTypeInfo> GetSupportedTraceType() { + return llvm::make_error<UnimplementedError>(); + } + protected: struct SoftwareBreakpoint { uint32_t ref_count; Index: lldb/docs/lldb-gdb-remote.txt =================================================================== --- lldb/docs/lldb-gdb-remote.txt +++ lldb/docs/lldb-gdb-remote.txt @@ -234,9 +234,38 @@ 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": <tracing technology name, e.g. intel-pt, arm-coresight> +// "description": <description string for this technology> +// } +// +// 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": <name>, "description", <description>}/E<error code> + //---------------------------------------------------------------------- // 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 @@ //---------------------------------------------------------------------- // jTraceStop: // +// This packet is deprecated. +// // BRIEF // Stop tracing instance with trace id <trace id>, of course trace // needs to be started before. The following parameters should be @@ -320,6 +351,8 @@ //---------------------------------------------------------------------- // jTraceBufferRead: // +// This packet is deprecated. +// // BRIEF // Packet for reading the trace for tracing instance <trace id>, i.e the // id obtained from StartTrace API. The following parameters should be @@ -353,6 +386,8 @@ //---------------------------------------------------------------------- // jTraceMetaRead: // +// This packet is deprecated. +// // BRIEF // Similar Packet as above except it reads meta data. //---------------------------------------------------------------------- @@ -360,6 +395,8 @@ /---------------------------------------------------------------------- // jTraceConfigRead: // +// This packet is deprecated. +// // BRIEF // Request the trace configuration for the tracing instance with id // <trace id>.
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits