Index: docs/lldb-gdb-remote.txt =================================================================== --- docs/lldb-gdb-remote.txt +++ docs/lldb-gdb-remote.txt @@ -126,6 +126,25 @@ This packet can be sent one or more times _prior_ to sending a "A" packet. //---------------------------------------------------------------------- +// "QErrorStringInPacketSupported" +// +// BRIEF +// This packet queries if the server implementation has capability to +// send error strings along with error packets. If the server posses +// such capability the client can expect to see error packets the +// following syntax in the error packets -> +// +// E;"Error Message" +// +// PRIORITY TO IMPLEMENT +// Low. Only needed if the remote target wants to provide strings that +// are human readable along with an error code. +//---------------------------------------------------------------------- + +send packet: $QErrorStringInPacketSupported +read packet: $OK#00 + +//---------------------------------------------------------------------- // "QSetSTDIN:" // "QSetSTDOUT:" // "QSetSTDERR:" @@ -250,11 +269,11 @@ // // 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. +// error code along with a message is returned instead. //---------------------------------------------------------------------- send packet: jTraceStart:{"type":,"buffersize":}] -read packet: /E +read packet: /E;"Error Message" //---------------------------------------------------------------------- // jTraceStop: @@ -283,12 +302,12 @@ // to stop tracing on that thread. // ========== ==================================================== // -// An OK response is sent in case of success else an error code is -// returned. +// An OK response is sent in case of success else an error code along +// with an error message is returned. //---------------------------------------------------------------------- send packet: jTraceStop:{"traceid":}] -read packet: /E +read packet: /E;"Error Message" //---------------------------------------------------------------------- // jTraceBufferRead: @@ -317,11 +336,11 @@ // ========== ==================================================== // // The trace data is sent as raw binary data if the read was successful -// else an error code is sent. +// else an error code along with an error message is sent. //---------------------------------------------------------------------- send packet: jTraceBufferRead:{"traceid":,"offset":,"buffersize":}] -read packet: /E +read packet: /E;"Error Message" //---------------------------------------------------------------------- // jTraceMetaRead: @@ -359,11 +378,11 @@ // gdb-remote protocol has certain limitations, binary escaping // convention is used. // In case the trace instance with the was not found, an -// error code is returned. +// error code along with an error message is returned. //---------------------------------------------------------------------- send packet: jTraceConfigRead:{"traceid":} -read packet: {"conf1":,"conf2":,"params":{"paramName":paramValue}]}];/E +read packet: {"conf1":,"conf2":,"params":{"paramName":paramValue}]}];/E;"Error Message" //---------------------------------------------------------------------- // "qRegisterInfo" Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -350,6 +350,8 @@ bool GetQPassSignalsSupported(); + bool GetErrorStringInPacketSupported(); + bool GetAugmentedLibrariesSVR4ReadSupported(); bool GetQXferFeaturesReadSupported(); @@ -549,6 +551,7 @@ LazyBool m_supports_jLoadedDynamicLibrariesInfos; LazyBool m_supports_jGetSharedCacheInfo; LazyBool m_supports_QPassSignals; + LazyBool m_supports_error_string_reply; bool m_supports_qProcessInfoPID : 1, m_supports_qfProcessInfo : 1, m_supports_qUserName : 1, m_supports_qGroupName : 1, Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -86,6 +86,7 @@ m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), m_supports_jGetSharedCacheInfo(eLazyBoolCalculate), m_supports_QPassSignals(eLazyBoolCalculate), + m_supports_error_string_reply(eLazyBoolCalculate), m_supports_qProcessInfoPID(true), m_supports_qfProcessInfo(true), m_supports_qUserName(true), m_supports_qGroupName(true), m_supports_qThreadStopInfo(true), m_supports_z0(true), @@ -596,6 +597,20 @@ return m_supports_jThreadExtendedInfo; } +bool GDBRemoteCommunicationClient::GetErrorStringInPacketSupported() { + if (m_supports_error_string_reply == eLazyBoolCalculate) { + StringExtractorGDBRemote response; + m_supports_error_string_reply = eLazyBoolNo; + if (SendPacketAndWaitForResponse("QErrorStringInPacketSupported", + response, false) == PacketResult::Success) { + if (response.IsOKResponse()) { + m_supports_error_string_reply = eLazyBoolYes; + } + } + } + return m_supports_error_string_reply; +} + bool GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported() { if (m_supports_jLoadedDynamicLibrariesInfos == eLazyBoolCalculate) { StringExtractorGDBRemote response; @@ -3181,8 +3196,11 @@ true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsNormalResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); - LLDB_LOG(log, "Target does not support Tracing"); + if (GetErrorStringInPacketSupported()) + error = response.GetStatus(); + else + error.SetError(response.GetError(), eErrorTypeGeneric); + LLDB_LOG(log, "Target does not support Tracing , error {0}", error.AsCString()); } else { ret_uid = response.GetHexMaxU64(false, LLDB_INVALID_UID); } @@ -3219,7 +3237,10 @@ true) == GDBRemoteCommunication::PacketResult::Success) { if (!response.IsOKResponse()) { - error.SetError(response.GetError(), eErrorTypeGeneric); + if (GetErrorStringInPacketSupported()) + error = response.GetStatus(); + else + error.SetError(response.GetError(), eErrorTypeGeneric); LLDB_LOG(log, "stop tracing failed"); } } else { @@ -3308,7 +3329,10 @@ custom_params_sp)); } } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + if (GetErrorStringInPacketSupported()) + error = response.GetStatus(); + else + error.SetError(response.GetError(), eErrorTypeGeneric); } } else { LLDB_LOG(log, "failed to send packet"); @@ -3344,7 +3368,10 @@ size_t filled_size = response.GetHexBytesAvail(buffer); buffer = llvm::MutableArrayRef(buffer.data(), filled_size); } else { - error.SetError(response.GetError(), eErrorTypeGeneric); + if (GetErrorStringInPacketSupported()) + error = response.GetStatus(); + else + error.SetError(response.GetError(), eErrorTypeGeneric); buffer = buffer.slice(buffer.size()); } } else { Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -61,6 +61,8 @@ PacketResult SendErrorResponse(uint8_t error); + PacketResult SendErrorResponse(Status &error); + PacketResult SendIllFormedResponse(const StringExtractorGDBRemote &packet, const char *error_message); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -100,6 +100,18 @@ } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServer::SendErrorResponse(Status &error) { + char errc[16]; + int errc_len = ::snprintf(errc, sizeof(errc), "E%2.2x", error.GetError()); + assert(errc_len < (int)sizeof(errc)); + + std::string packet(errc); + packet += ";"; + packet += std::string(error.AsCString()); + return SendPacketNoLock(packet); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServer::SendIllFormedResponse( const StringExtractorGDBRemote &failed_packet, const char *message) { Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet(GDBR_LOG_PACKETS)); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.h @@ -155,6 +155,8 @@ PacketResult Handle_qRegisterInfo(StringExtractorGDBRemote &packet); + PacketResult Handle_QErrorStringInPacketSupported(StringExtractorGDBRemote &packet); + PacketResult Handle_qfThreadInfo(StringExtractorGDBRemote &packet); PacketResult Handle_qsThreadInfo(StringExtractorGDBRemote &packet); Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerLLGS.cpp @@ -132,6 +132,9 @@ StringExtractorGDBRemote::eServerPacketType_qRegisterInfo, &GDBRemoteCommunicationServerLLGS::Handle_qRegisterInfo); RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_QErrorStringInPacketSupported, + &GDBRemoteCommunicationServerLLGS::Handle_QErrorStringInPacketSupported); + RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_QRestoreRegisterState, &GDBRemoteCommunicationServerLLGS::Handle_QRestoreRegisterState); RegisterMemberFunctionHandler( @@ -1070,6 +1073,12 @@ } GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerLLGS::Handle_QErrorStringInPacketSupported( + StringExtractorGDBRemote &packet) { + return SendOKResponse(); +} + +GDBRemoteCommunication::PacketResult GDBRemoteCommunicationServerLLGS::Handle_jTraceStart( StringExtractorGDBRemote &packet) { Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS)); @@ -1128,7 +1137,7 @@ 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()); + return SendErrorResponse(error); StreamGDBRemote response; response.Printf("%" PRIx64, uid); @@ -1165,7 +1174,7 @@ Status error = m_debugged_process_sp->StopTrace(uid, tid); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); return SendOKResponse(); } @@ -1208,7 +1217,7 @@ Status error = m_debugged_process_sp->GetTraceConfig(uid, options); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); StreamGDBRemote escaped_response; StructuredData::Dictionary json_packet; @@ -1284,7 +1293,7 @@ error = m_debugged_process_sp->GetMetaData(uid, tid, buf, offset); if (error.Fail()) - return SendErrorResponse(error.GetError()); + return SendErrorResponse(error); for (auto i : buf) response.PutHex8(i); Index: source/Utility/StringExtractorGDBRemote.h =================================================================== --- source/Utility/StringExtractorGDBRemote.h +++ source/Utility/StringExtractorGDBRemote.h @@ -11,6 +11,7 @@ #define utility_StringExtractorGDBRemote_h_ #include "lldb/Utility/StringExtractor.h" +#include "lldb/Utility/Status.h" #include "llvm/ADT/StringRef.h" // for StringRef #include @@ -72,6 +73,7 @@ eServerPacketType_qGetWorkingDir, eServerPacketType_qFileLoadAddress, eServerPacketType_QEnvironment, + eServerPacketType_QErrorStringInPacketSupported, eServerPacketType_QLaunchArch, eServerPacketType_QSetDisableASLR, eServerPacketType_QSetDetachOnError, @@ -190,6 +192,8 @@ // digits. Otherwise the error encoded in XX is returned. uint8_t GetError(); + lldb_private::Status GetStatus(); + size_t GetEscapedBinaryData(std::string &str); protected: Index: source/Utility/StringExtractorGDBRemote.cpp =================================================================== --- source/Utility/StringExtractorGDBRemote.cpp +++ source/Utility/StringExtractorGDBRemote.cpp @@ -19,7 +19,7 @@ switch (m_packet[0]) { case 'E': - if (m_packet.size() == 3 && isxdigit(m_packet[1]) && isxdigit(m_packet[2])) + if (isxdigit(m_packet[1]) && isxdigit(m_packet[2])) return eError; break; @@ -86,6 +86,8 @@ return eServerPacketType_QEnvironment; if (PACKET_STARTS_WITH("QEnvironmentHexEncoded:")) return eServerPacketType_QEnvironmentHexEncoded; + if (PACKET_STARTS_WITH("QErrorStringInPacketSupported")) + return eServerPacketType_QErrorStringInPacketSupported; break; case 'P': @@ -438,7 +440,7 @@ } bool StringExtractorGDBRemote::IsErrorResponse() const { - return GetResponseType() == eError && m_packet.size() == 3 && + return GetResponseType() == eError && isxdigit(m_packet[1]) && isxdigit(m_packet[2]); } @@ -450,6 +452,24 @@ return 0; } +lldb_private::Status +StringExtractorGDBRemote::GetStatus() { + lldb_private::Status error; + if (GetResponseType() == eError) { + SetFilePos(1); + uint8_t errc = GetHexU8(255); + error.SetError(errc, lldb::eErrorTypeGeneric); + + std::string error_messg ("Error 47"); + size_t str_index = m_packet.find(';', m_index); + if (str_index != std::string::npos) + error_messg = m_packet.substr(++str_index); + + error.SetErrorString(error_messg); + } + return error; +} + size_t StringExtractorGDBRemote::GetEscapedBinaryData(std::string &str) { // Just get the data bytes in the string as // GDBRemoteCommunication::CheckForPacket()