diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -546,6 +546,7 @@ LazyBool m_supports_qXfer_libraries_svr4_read; LazyBool m_supports_qXfer_features_read; LazyBool m_supports_qXfer_memory_map_read; + LazyBool m_supports_qLaunchSuccess_error_asciihex; LazyBool m_supports_augmented_libraries_svr4_read; LazyBool m_supports_jThreadExtendedInfo; LazyBool m_supports_jLoadedDynamicLibrariesInfos; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -83,6 +83,7 @@ m_supports_qXfer_libraries_svr4_read(eLazyBoolCalculate), m_supports_qXfer_features_read(eLazyBoolCalculate), m_supports_qXfer_memory_map_read(eLazyBoolCalculate), + m_supports_qLaunchSuccess_error_asciihex(eLazyBoolCalculate), m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate), m_supports_jThreadExtendedInfo(eLazyBoolCalculate), m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate), @@ -297,6 +298,7 @@ m_supports_qXfer_libraries_svr4_read = eLazyBoolCalculate; m_supports_qXfer_features_read = eLazyBoolCalculate; m_supports_qXfer_memory_map_read = eLazyBoolCalculate; + m_supports_qLaunchSuccess_error_asciihex = eLazyBoolCalculate; m_supports_augmented_libraries_svr4_read = eLazyBoolCalculate; m_supports_qProcessInfoPID = true; m_supports_qfProcessInfo = true; @@ -342,11 +344,13 @@ m_supports_augmented_libraries_svr4_read = eLazyBoolNo; m_supports_qXfer_features_read = eLazyBoolNo; m_supports_qXfer_memory_map_read = eLazyBoolNo; + m_supports_qLaunchSuccess_error_asciihex = eLazyBoolNo; m_max_packet_size = UINT64_MAX; // It's supposed to always be there, but if // not, we assume no limit // build the qSupported packet - std::vector features = {"xmlRegisters=i386,arm,mips,arc"}; + std::vector features = {"xmlRegisters=i386,arm,mips,arc", + "qLaunchSuccessASCIIHexErrorText"}; StreamString packet; packet.PutCString("qSupported"); for (uint32_t i = 0; i < features.size(); ++i) { @@ -446,6 +450,9 @@ LLDB_LOGF(log, "Garbled PacketSize spec in qSupported response"); } } + if (::strstr(response_cstr, "qLaunchSuccessASCIIHexErrorText")) { + m_supports_qLaunchSuccess_error_asciihex = eLazyBoolYes; + } } } @@ -764,8 +771,13 @@ if (response.IsOKResponse()) return true; if (response.GetChar() == 'E') { - // A string the describes what failed when launching... - error_str = std::string(response.GetStringRef().substr(1)); + if (m_supports_qLaunchSuccess_error_asciihex == eLazyBoolYes) { + error_str = response.GetStatus().AsCString(); + } else { + // The old format of this packet would respond with a + // 'E' followed by the plain error string with no escaping. + error_str = std::string(response.GetStringRef().substr(1)); + } } else { error_str.assign("unknown error occurred launching process"); } diff --git a/lldb/tools/debugserver/source/RNBRemote.h b/lldb/tools/debugserver/source/RNBRemote.h --- a/lldb/tools/debugserver/source/RNBRemote.h +++ b/lldb/tools/debugserver/source/RNBRemote.h @@ -405,6 +405,7 @@ size_t m_compression_minsize; // only packets larger than this size will be // compressed bool m_enable_compression_next_send_packet; + bool m_qLaunchSuccess_error_fix; compression_types m_compression_mode; }; diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -145,6 +145,18 @@ return addr; } +std::string cstring_to_asciihex_string(const char *str) { + std::string hex_str; + hex_str.reserve(strlen(str) * 2); + while (str && *str) { + uint8_t c = *str++; + char hexbuf[5]; + snprintf(hexbuf, sizeof(hexbuf), "%02x", c); + hex_str += hexbuf; + } + return hex_str; +} + extern void ASLLogCallback(void *baton, uint32_t flags, const char *format, va_list args); @@ -176,6 +188,7 @@ m_extended_mode(false), m_noack_mode(false), m_thread_suffix_supported(false), m_list_threads_in_stop_reply(false), m_compression_minsize(384), m_enable_compression_next_send_packet(false), + m_qLaunchSuccess_error_fix(false), m_compression_mode(compression_types::none) { DNBLogThreadedIf(LOG_RNB_REMOTE, "%s", __PRETTY_FUNCTION__); CreatePacketTable(); @@ -1643,7 +1656,13 @@ return SendPacket("OK"); std::ostringstream ret_str; std::string status_str; - ret_str << "E" << m_ctx.LaunchStatusAsString(status_str); + if (m_qLaunchSuccess_error_fix) { + std::string hexified = + cstring_to_asciihex_string(m_ctx.LaunchStatusAsString(status_str)); + ret_str << "E97;" << hexified.c_str(); + } else { + ret_str << "E" << m_ctx.LaunchStatusAsString(status_str); + } return SendPacket(ret_str.str()); } @@ -2673,17 +2692,6 @@ } } -std::string cstring_to_asciihex_string(const char *str) { - std::string hex_str; - hex_str.reserve (strlen (str) * 2); - while (str && *str) { - char hexbuf[5]; - snprintf (hexbuf, sizeof(hexbuf), "%02x", *str++); - hex_str += hexbuf; - } - return hex_str; -} - void append_hexified_string(std::ostream &ostrm, const std::string &string) { size_t string_size = string.size(); const char *string_buf = string.c_str(); @@ -3647,7 +3655,13 @@ snprintf(numbuf, sizeof(numbuf), "%zu", m_compression_minsize); numbuf[sizeof(numbuf) - 1] = '\0'; strcat(buf, numbuf); - } + } + + // Enable a fix to the qLaunchSuccess packet. + if (strstr(p, "qLaunchSuccessASCIIHexErrorText") != nullptr) { + m_qLaunchSuccess_error_fix = true; + strcat(buf, ";qLaunchSuccessASCIIHexErrorText"); + } return SendPacket(buf); }