diff options
Diffstat (limited to 'lldb/source/Plugins/Process/gdb-remote')
8 files changed, 745 insertions, 185 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp index 7a9694647f4..3b8d6056063 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.cpp @@ -30,7 +30,7 @@ using namespace lldb_private; //---------------------------------------------------------------------- GDBRemoteCommunication::GDBRemoteCommunication(const char *comm_name, const char *listener_name) : Communication(comm_name), - m_packet_timeout (1), + m_packet_timeout (60), m_rx_packet_listener (listener_name), m_sequence_mutex (Mutex::eMutexTypeRecursive), m_public_is_running (false), @@ -57,7 +57,6 @@ GDBRemoteCommunication::~GDBRemoteCommunication() } } - char GDBRemoteCommunication::CalculcateChecksum (const char *payload, size_t payload_length) { @@ -80,7 +79,7 @@ GDBRemoteCommunication::SendAck () log->Printf ("send packet: +"); ConnectionStatus status = eConnectionStatusSuccess; char ack_char = '+'; - return Write (&ack_char, 1, status, NULL) == 1; + return Write (&ack_char, 1, status, NULL); } size_t @@ -91,7 +90,15 @@ GDBRemoteCommunication::SendNack () log->Printf ("send packet: -"); ConnectionStatus status = eConnectionStatusSuccess; char nack_char = '-'; - return Write (&nack_char, 1, status, NULL) == 1; + return Write (&nack_char, 1, status, NULL); +} + +size_t +GDBRemoteCommunication::SendPacket (lldb_private::StreamString &payload) +{ + Mutex::Locker locker(m_sequence_mutex); + const std::string &p (payload.GetString()); + return SendPacketNoLock (p.c_str(), p.size()); } size_t diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h index e8129ce919f..f53d036a518 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunication.h @@ -49,6 +49,9 @@ public: SendPacket (const char *payload, size_t payload_length); + size_t + SendPacket (lldb_private::StreamString &response); + // Wait for a packet within 'nsec' seconds size_t WaitForPacket (StringExtractorGDBRemote &response, diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index f8a0600fb81..d640d5b1d86 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -38,13 +38,17 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : GDBRemoteCommunication("gdb-remote.client", "gdb-remote.client.rx_packet"), m_supports_not_sending_acks (eLazyBoolCalculate), m_supports_thread_suffix (eLazyBoolCalculate), - m_supports_qHostInfo (eLazyBoolCalculate), m_supports_vCont_all (eLazyBoolCalculate), m_supports_vCont_any (eLazyBoolCalculate), m_supports_vCont_c (eLazyBoolCalculate), m_supports_vCont_C (eLazyBoolCalculate), m_supports_vCont_s (eLazyBoolCalculate), m_supports_vCont_S (eLazyBoolCalculate), + m_qHostInfo_is_valid (eLazyBoolCalculate), + m_supports_qProcessInfoPID (true), + m_supports_qfProcessInfo (true), + m_supports_qUserName (true), + m_supports_qGroupName (true), m_async_mutex (Mutex::eMutexTypeRecursive), m_async_packet_predicate (false), m_async_packet (), @@ -113,11 +117,15 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() { m_supports_not_sending_acks = eLazyBoolCalculate; m_supports_thread_suffix = eLazyBoolCalculate; - m_supports_qHostInfo = eLazyBoolCalculate; m_supports_vCont_c = eLazyBoolCalculate; m_supports_vCont_C = eLazyBoolCalculate; m_supports_vCont_s = eLazyBoolCalculate; m_supports_vCont_S = eLazyBoolCalculate; + m_qHostInfo_is_valid = eLazyBoolCalculate; + m_supports_qProcessInfoPID = true; + m_supports_qfProcessInfo = true; + m_supports_qUserName = true; + m_supports_qGroupName = true; m_host_arch.Clear(); } @@ -759,107 +767,159 @@ GDBRemoteCommunicationClient::GetSystemArchitecture () bool GDBRemoteCommunicationClient::GetHostInfo () { - if (m_supports_qHostInfo == eLazyBoolCalculate) + if (m_qHostInfo_is_valid == eLazyBoolCalculate) { - m_supports_qHostInfo = eLazyBoolNo; - + m_qHostInfo_is_valid = eLazyBoolNo; StringExtractorGDBRemote response; if (SendPacketAndWaitForResponse ("qHostInfo", response, false)) { if (response.IsUnsupportedResponse()) + { return false; - - m_supports_qHostInfo = eLazyBoolYes; - - std::string name; - std::string value; - uint32_t cpu = LLDB_INVALID_CPUTYPE; - uint32_t sub = 0; - std::string arch_name; - std::string os_name; - std::string vendor_name; - std::string triple; - uint32_t pointer_byte_size = 0; - StringExtractor extractor; - ByteOrder byte_order = eByteOrderInvalid; - while (response.GetNameColonValue(name, value)) + } + else if (response.IsNormalResponse()) { - if (name.compare("cputype") == 0) + std::string name; + std::string value; + uint32_t cpu = LLDB_INVALID_CPUTYPE; + uint32_t sub = 0; + std::string arch_name; + std::string os_name; + std::string vendor_name; + std::string triple; + uint32_t pointer_byte_size = 0; + StringExtractor extractor; + ByteOrder byte_order = eByteOrderInvalid; + uint32_t num_keys_decoded = 0; + while (response.GetNameColonValue(name, value)) { - // exception type in big endian hex - cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); - } - else if (name.compare("cpusubtype") == 0) - { - // exception count in big endian hex - sub = Args::StringToUInt32 (value.c_str(), 0, 0); - } - else if (name.compare("arch") == 0) - { - arch_name.swap (value); - } - else if (name.compare("triple") == 0) - { - // The triple comes as ASCII hex bytes since it contains '-' chars - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (triple); - } - else if (name.compare("os_build") == 0) - { - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (m_os_build); - } - else if (name.compare("hostname") == 0) - { - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (m_hostname); - } - else if (name.compare("os_kernel") == 0) - { - extractor.GetStringRef().swap(value); - extractor.SetFilePos(0); - extractor.GetHexByteString (m_os_kernel); - } - else if (name.compare("ostype") == 0) - { - os_name.swap (value); - } - else if (name.compare("vendor") == 0) - { - vendor_name.swap(value); - } - else if (name.compare("endian") == 0) - { - if (value.compare("little") == 0) - byte_order = eByteOrderLittle; - else if (value.compare("big") == 0) - byte_order = eByteOrderBig; - else if (value.compare("pdp") == 0) - byte_order = eByteOrderPDP; - } - else if (name.compare("ptrsize") == 0) - { - pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); - } - else if (name.compare("os_version") == 0) - { - Args::StringToVersion (value.c_str(), - m_os_version_major, - m_os_version_minor, - m_os_version_update); + if (name.compare("cputype") == 0) + { + // exception type in big endian hex + cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 0); + if (cpu != LLDB_INVALID_CPUTYPE) + ++num_keys_decoded; + } + else if (name.compare("cpusubtype") == 0) + { + // exception count in big endian hex + sub = Args::StringToUInt32 (value.c_str(), 0, 0); + if (sub != 0) + ++num_keys_decoded; + } + else if (name.compare("arch") == 0) + { + arch_name.swap (value); + ++num_keys_decoded; + } + else if (name.compare("triple") == 0) + { + // The triple comes as ASCII hex bytes since it contains '-' chars + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (triple); + ++num_keys_decoded; + } + else if (name.compare("os_build") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (m_os_build); + ++num_keys_decoded; + } + else if (name.compare("hostname") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (m_hostname); + ++num_keys_decoded; + } + else if (name.compare("os_kernel") == 0) + { + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (m_os_kernel); + ++num_keys_decoded; + } + else if (name.compare("ostype") == 0) + { + os_name.swap (value); + ++num_keys_decoded; + } + else if (name.compare("vendor") == 0) + { + vendor_name.swap(value); + ++num_keys_decoded; + } + else if (name.compare("endian") == 0) + { + ++num_keys_decoded; + if (value.compare("little") == 0) + byte_order = eByteOrderLittle; + else if (value.compare("big") == 0) + byte_order = eByteOrderBig; + else if (value.compare("pdp") == 0) + byte_order = eByteOrderPDP; + else + --num_keys_decoded; + } + else if (name.compare("ptrsize") == 0) + { + pointer_byte_size = Args::StringToUInt32 (value.c_str(), 0, 0); + if (pointer_byte_size != 0) + ++num_keys_decoded; + } + else if (name.compare("os_version") == 0) + { + Args::StringToVersion (value.c_str(), + m_os_version_major, + m_os_version_minor, + m_os_version_update); + if (m_os_version_major != UINT32_MAX) + ++num_keys_decoded; + } } - } - - if (triple.empty()) - { - if (arch_name.empty()) + + if (num_keys_decoded > 0) + m_qHostInfo_is_valid = eLazyBoolYes; + + if (triple.empty()) { - if (cpu != LLDB_INVALID_CPUTYPE) + if (arch_name.empty()) { - m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + if (cpu != LLDB_INVALID_CPUTYPE) + { + m_host_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + if (pointer_byte_size) + { + assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); + } + if (byte_order != eByteOrderInvalid) + { + assert (byte_order == m_host_arch.GetByteOrder()); + } + if (!vendor_name.empty()) + m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); + if (!os_name.empty()) + m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name)); + + } + } + else + { + std::string triple; + triple += arch_name; + triple += '-'; + if (vendor_name.empty()) + triple += "unknown"; + else + triple += vendor_name; + triple += '-'; + if (os_name.empty()) + triple += "unknown"; + else + triple += os_name; + m_host_arch.SetTriple (triple.c_str()); if (pointer_byte_size) { assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); @@ -868,27 +928,11 @@ GDBRemoteCommunicationClient::GetHostInfo () { assert (byte_order == m_host_arch.GetByteOrder()); } - if (!vendor_name.empty()) - m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); - if (!os_name.empty()) - m_host_arch.GetTriple().setVendorName (llvm::StringRef (os_name)); - + } } else { - std::string triple; - triple += arch_name; - triple += '-'; - if (vendor_name.empty()) - triple += "unknown"; - else - triple += vendor_name; - triple += '-'; - if (os_name.empty()) - triple += "unknown"; - else - triple += os_name; m_host_arch.SetTriple (triple.c_str()); if (pointer_byte_size) { @@ -898,24 +942,11 @@ GDBRemoteCommunicationClient::GetHostInfo () { assert (byte_order == m_host_arch.GetByteOrder()); } - - } + } } - else - { - m_host_arch.SetTriple (triple.c_str()); - if (pointer_byte_size) - { - assert (pointer_byte_size == m_host_arch.GetAddressByteSize()); - } - if (byte_order != eByteOrderInvalid) - { - assert (byte_order == m_host_arch.GetByteOrder()); - } - } } } - return m_supports_qHostInfo == eLazyBoolYes; + return m_qHostInfo_is_valid == eLazyBoolYes; } int @@ -927,10 +958,10 @@ GDBRemoteCommunicationClient::SendAttach { if (pid != LLDB_INVALID_PROCESS_ID) { - StreamString packet; - packet.Printf("vAttach;%x", pid); - - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) + char packet[64]; + const int packet_len = ::snprintf (packet, sizeof(packet), "vAttach;%x", pid); + assert (packet_len < sizeof(packet)); + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) { if (response.IsErrorResponse()) return response.GetError(); @@ -943,7 +974,7 @@ GDBRemoteCommunicationClient::SendAttach const lldb_private::ArchSpec & GDBRemoteCommunicationClient::GetHostArchitecture () { - if (m_supports_qHostInfo == eLazyBoolCalculate) + if (m_qHostInfo_is_valid == eLazyBoolCalculate) GetHostInfo (); return m_host_arch; } @@ -952,12 +983,13 @@ addr_t GDBRemoteCommunicationClient::AllocateMemory (size_t size, uint32_t permissions) { char packet[64]; - ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size, - permissions & lldb::ePermissionsReadable ? "r" : "", - permissions & lldb::ePermissionsWritable ? "w" : "", - permissions & lldb::ePermissionsExecutable ? "x" : ""); + const int packet_len = ::snprintf (packet, sizeof(packet), "_M%zx,%s%s%s", size, + permissions & lldb::ePermissionsReadable ? "r" : "", + permissions & lldb::ePermissionsWritable ? "w" : "", + permissions & lldb::ePermissionsExecutable ? "x" : ""); + assert (packet_len < sizeof(packet)); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, response, false)) + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) { if (!response.IsErrorResponse()) return response.GetHexMaxU64(false, LLDB_INVALID_ADDRESS); @@ -969,9 +1001,10 @@ bool GDBRemoteCommunicationClient::DeallocateMemory (addr_t addr) { char packet[64]; - snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr); + const int packet_len = ::snprintf(packet, sizeof(packet), "_m%llx", (uint64_t)addr); + assert (packet_len < sizeof(packet)); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet, response, false)) + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) { if (response.IsOKResponse()) return true; @@ -1070,11 +1103,11 @@ GDBRemoteCommunicationClient::SetWorkingDir (char const *path) int GDBRemoteCommunicationClient::SetDisableASLR (bool enable) { - StreamString packet; - packet.Printf("QSetDisableASLR:%i", enable ? 1 : 0); - + char packet[32]; + const int packet_len = ::snprintf (packet, sizeof (packet), "QSetDisableASLR:%i", enable ? 1 : 0); + assert (packet_len < sizeof(packet)); StringExtractorGDBRemote response; - if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) { if (response.IsOKResponse()) return 0; @@ -1084,3 +1117,251 @@ GDBRemoteCommunicationClient::SetDisableASLR (bool enable) } return -1; } + +bool +GDBRemoteCommunicationClient::DecodeProcessInfoResponse (StringExtractorGDBRemote &response, ProcessInfo &process_info) +{ + if (response.IsNormalResponse()) + { + std::string name; + std::string value; + StringExtractor extractor; + + while (response.GetNameColonValue(name, value)) + { + if (name.compare("pid") == 0) + { + process_info.SetProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + } + else if (name.compare("ppid") == 0) + { + process_info.SetParentProcessID (Args::StringToUInt32 (value.c_str(), LLDB_INVALID_PROCESS_ID, 0)); + } + else if (name.compare("uid") == 0) + { + process_info.SetRealUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + } + else if (name.compare("euid") == 0) + { + process_info.SetEffectiveUserID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + } + else if (name.compare("gid") == 0) + { + process_info.SetRealGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + } + else if (name.compare("egid") == 0) + { + process_info.SetEffectiveGroupID (Args::StringToUInt32 (value.c_str(), UINT32_MAX, 0)); + } + else if (name.compare("triple") == 0) + { + // The triple comes as ASCII hex bytes since it contains '-' chars + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (value); + process_info.GetArchitecture ().SetTriple (value.c_str()); + } + else if (name.compare("name") == 0) + { + StringExtractor extractor; + // The the process name from ASCII hex bytes since we can't + // control the characters in a process name + extractor.GetStringRef().swap(value); + extractor.SetFilePos(0); + extractor.GetHexByteString (value); + process_info.SwapName (value); + } + } + + if (process_info.GetProcessID() != LLDB_INVALID_PROCESS_ID) + return true; + } + return false; +} + +bool +GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInfo &process_info) +{ + process_info.Clear(); + + if (m_supports_qProcessInfoPID) + { + char packet[32]; + const int packet_len = ::snprintf (packet, sizeof (packet), "qProcessInfoPID:%i", pid); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + if (response.IsUnsupportedResponse()) + { + m_supports_qProcessInfoPID = false; + return false; + } + + return DecodeProcessInfoResponse (response, process_info); + } + } + return false; +} + +uint32_t +GDBRemoteCommunicationClient::FindProcesses (const ProcessInfoMatch &match_info, + ProcessInfoList &process_infos) +{ + process_infos.Clear(); + + if (m_supports_qfProcessInfo) + { + StreamString packet; + packet.PutCString ("qfProcessInfo"); + if (!match_info.MatchAllProcesses()) + { + packet.PutChar (':'); + const char *name = match_info.GetProcessInfo().GetName(); + bool has_name_match = false; + if (name && name[0]) + { + has_name_match = true; + NameMatchType name_match_type = match_info.GetNameMatchType(); + switch (name_match_type) + { + case eNameMatchIgnore: + has_name_match = false; + break; + + case eNameMatchEquals: + packet.PutCString ("name_match:equals;"); + break; + + case eNameMatchContains: + packet.PutCString ("name_match:contains;"); + break; + + case eNameMatchStartsWith: + packet.PutCString ("name_match:starts_with;"); + break; + + case eNameMatchEndsWith: + packet.PutCString ("name_match:ends_with;"); + break; + + case eNameMatchRegularExpression: + packet.PutCString ("name_match:regex;"); + break; + } + if (has_name_match) + { + packet.PutCString ("name:"); + packet.PutBytesAsRawHex8(name, ::strlen(name)); + packet.PutChar (';'); + } + } + + if (match_info.GetProcessInfo().ProcessIDIsValid()) + packet.Printf("pid:%u;",match_info.GetProcessInfo().GetProcessID()); + if (match_info.GetProcessInfo().ParentProcessIDIsValid()) + packet.Printf("parent_pid:%u;",match_info.GetProcessInfo().GetParentProcessID()); + if (match_info.GetProcessInfo().RealUserIDIsValid()) + packet.Printf("uid:%u;",match_info.GetProcessInfo().GetRealUserID()); + if (match_info.GetProcessInfo().RealGroupIDIsValid()) + packet.Printf("gid:%u;",match_info.GetProcessInfo().GetRealGroupID()); + if (match_info.GetProcessInfo().EffectiveUserIDIsValid()) + packet.Printf("euid:%u;",match_info.GetProcessInfo().GetEffectiveUserID()); + if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) + packet.Printf("egid:%u;",match_info.GetProcessInfo().GetEffectiveGroupID()); + if (match_info.GetProcessInfo().EffectiveGroupIDIsValid()) + packet.Printf("all_users:%u;",match_info.GetMatchAllUsers() ? 1 : 0); + if (match_info.GetProcessInfo().GetArchitecture().IsValid()) + { + const ArchSpec &match_arch = match_info.GetProcessInfo().GetArchitecture(); + const llvm::Triple &triple = match_arch.GetTriple(); + packet.PutCString("triple:"); + packet.PutCStringAsRawHex8(triple.getTriple().c_str()); + packet.PutChar (';'); + } + } + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet.GetData(), packet.GetSize(), response, false)) + { + if (response.IsUnsupportedResponse()) + { + m_supports_qfProcessInfo = false; + return 0; + } + + do + { + ProcessInfo process_info; + if (!DecodeProcessInfoResponse (response, process_info)) + break; + process_infos.Append(process_info); + response.GetStringRef().clear(); + response.SetFilePos(0); + } while (SendPacketAndWaitForResponse ("qsProcessInfo", strlen ("qsProcessInfo"), response, false)); + } + } + return process_infos.GetSize(); + +} + +bool +GDBRemoteCommunicationClient::GetUserName (uint32_t uid, std::string &name) +{ + if (m_supports_qUserName) + { + char packet[32]; + const int packet_len = ::snprintf (packet, sizeof (packet), "qUserName:%i", uid); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + if (response.IsUnsupportedResponse()) + { + m_supports_qUserName = false; + return false; + } + + if (response.IsNormalResponse()) + { + // Make sure we parsed the right number of characters. The response is + // the hex encoded user name and should make up the entire packet. + // If there are any non-hex ASCII bytes, the length won't match below.. + if (response.GetHexByteString (name) * 2 == response.GetStringRef().size()) + return true; + } + } + } + return false; + +} + +bool +GDBRemoteCommunicationClient::GetGroupName (uint32_t gid, std::string &name) +{ + if (m_supports_qGroupName) + { + char packet[32]; + const int packet_len = ::snprintf (packet, sizeof (packet), "qGroupName:%i", gid); + assert (packet_len < sizeof(packet)); + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse (packet, packet_len, response, false)) + { + if (response.IsUnsupportedResponse()) + { + m_supports_qGroupName = false; + return false; + } + + if (response.IsNormalResponse()) + { + // Make sure we parsed the right number of characters. The response is + // the hex encoded group name and should make up the entire packet. + // If there are any non-hex ASCII bytes, the length won't match below.. + if (response.GetHexByteString (name) * 2 == response.GetStringRef().size()) + return true; + } + } + } + return false; + +} diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 39ddb622218..d28c8275bd4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -213,6 +213,20 @@ public: GetSupportsThreadSuffix (); bool + GetProcessInfo (lldb::pid_t pid, + lldb_private::ProcessInfo &process_info); + + uint32_t + FindProcesses (const lldb_private::ProcessInfoMatch &process_match_info, + lldb_private::ProcessInfoList &process_infos); + + bool + GetUserName (uint32_t uid, std::string &name); + + bool + GetGroupName (uint32_t gid, std::string &name); + + bool HasFullVContSupport () { return GetVContSupported ('A'); @@ -239,13 +253,17 @@ protected: //------------------------------------------------------------------ lldb_private::LazyBool m_supports_not_sending_acks; lldb_private::LazyBool m_supports_thread_suffix; - lldb_private::LazyBool m_supports_qHostInfo; lldb_private::LazyBool m_supports_vCont_all; lldb_private::LazyBool m_supports_vCont_any; lldb_private::LazyBool m_supports_vCont_c; lldb_private::LazyBool m_supports_vCont_C; lldb_private::LazyBool m_supports_vCont_s; lldb_private::LazyBool m_supports_vCont_S; + lldb_private::LazyBool m_qHostInfo_is_valid; + bool m_supports_qProcessInfoPID; + bool m_supports_qfProcessInfo; + bool m_supports_qUserName; + bool m_supports_qGroupName; // If we need to send a packet while the target is running, the m_async_XXX // member variables take care of making this happen. @@ -263,6 +281,9 @@ protected: std::string m_os_kernel; std::string m_hostname; + bool + DecodeProcessInfoResponse (StringExtractorGDBRemote &response, + lldb_private::ProcessInfo &process_info); private: //------------------------------------------------------------------ // For GDBRemoteCommunicationClient only diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp index faee6776a83..ea6842b999a 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -97,13 +97,28 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout break; case StringExtractorGDBRemote::eServerPacketType_unimplemented: - return SendUnimplementedResponse () > 0; + return SendUnimplementedResponse (packet.GetStringRef().c_str()) > 0; case StringExtractorGDBRemote::eServerPacketType_qHostInfo: - return Handle_qHostInfo (); - + return Handle_qHostInfo (packet); + + case StringExtractorGDBRemote::eServerPacketType_qProcessInfoPID: + return Handle_qProcessInfoPID (packet); + + case StringExtractorGDBRemote::eServerPacketType_qfProcessInfo: + return Handle_qfProcessInfo (packet); + + case StringExtractorGDBRemote::eServerPacketType_qsProcessInfo: + return Handle_qsProcessInfo (packet); + + case StringExtractorGDBRemote::eServerPacketType_qUserName: + return Handle_qUserName (packet); + + case StringExtractorGDBRemote::eServerPacketType_qGroupName: + return Handle_qGroupName (packet); + case StringExtractorGDBRemote::eServerPacketType_QStartNoAckMode: - return Handle_QStartNoAckMode (); + return Handle_QStartNoAckMode (packet); } return true; } @@ -119,12 +134,23 @@ GDBRemoteCommunicationServer::GetPacketAndSendResponse (const TimeValue* timeout } size_t -GDBRemoteCommunicationServer::SendUnimplementedResponse () +GDBRemoteCommunicationServer::SendUnimplementedResponse (const char *) { + // TODO: Log the packet we aren't handling... return SendPacket (""); } size_t +GDBRemoteCommunicationServer::SendErrorResponse (uint8_t err) +{ + char packet[16]; + int packet_len = ::snprintf (packet, sizeof(packet), "E%2.2x", err); + assert (packet_len < sizeof(packet)); + return SendPacket (packet, packet_len); +} + + +size_t GDBRemoteCommunicationServer::SendOKResponse () { return SendPacket ("OK"); @@ -139,7 +165,7 @@ GDBRemoteCommunicationServer::HandshakeWithClient(Error *error_ptr) } bool -GDBRemoteCommunicationServer::Handle_qHostInfo () +GDBRemoteCommunicationServer::Handle_qHostInfo (StringExtractorGDBRemote &packet) { StreamString response; @@ -204,13 +230,208 @@ GDBRemoteCommunicationServer::Handle_qHostInfo () response.PutChar(';'); } - return SendPacket (response.GetString().c_str(),response.GetString().size()) > 0; + return SendPacket (response) > 0; +} + +static void +CreateProcessInfoResponse (const ProcessInfo &proc_info, StreamString &response) +{ + response.Printf ("pid:%i;ppid:%i;uid:%i;gid:%i;euid:%i;egid:%i;", + proc_info.GetProcessID(), + proc_info.GetParentProcessID(), + proc_info.GetRealUserID(), + proc_info.GetRealGroupID(), + proc_info.GetEffectiveUserID(), + proc_info.GetEffectiveGroupID()); + response.PutCString ("name:"); + response.PutCStringAsRawHex8(proc_info.GetName()); + response.PutChar(';'); + const ArchSpec &proc_arch = proc_info.GetArchitecture(); + if (proc_arch.IsValid()) + { + const llvm::Triple &proc_triple = proc_arch.GetTriple(); + response.PutCString("triple:"); + response.PutCStringAsRawHex8(proc_triple.getTriple().c_str()); + response.PutChar(';'); + } +} + +bool +GDBRemoteCommunicationServer::Handle_qProcessInfoPID (StringExtractorGDBRemote &packet) +{ + // Packet format: "qProcessInfoPID:%i" where %i is the pid + packet.SetFilePos(strlen ("qProcessInfoPID:")); + lldb::pid_t pid = packet.GetU32 (LLDB_INVALID_PROCESS_ID); + if (pid != LLDB_INVALID_PROCESS_ID) + { + ProcessInfo proc_info; + if (Host::GetProcessInfo(pid, proc_info)) + { + StreamString response; + CreateProcessInfoResponse (proc_info, response); + return SendPacket (response); + } + } + return SendErrorResponse (1); +} + +bool +GDBRemoteCommunicationServer::Handle_qfProcessInfo (StringExtractorGDBRemote &packet) +{ + m_proc_infos_index = 0; + m_proc_infos.Clear(); + + ProcessInfoMatch match_info; + packet.SetFilePos(strlen ("qfProcessInfo")); + if (packet.GetChar() == ':') + { + + std::string key; + std::string value; + while (packet.GetNameColonValue(key, value)) + { + bool success = true; + if (key.compare("name") == 0) + { + StringExtractor extractor; + extractor.GetStringRef().swap(value); + extractor.GetHexByteString (value); + match_info.GetProcessInfo().SetName (value.c_str()); + } + else if (key.compare("name_match") == 0) + { + if (value.compare("equals") == 0) + { + match_info.SetNameMatchType (eNameMatchEquals); + } + else if (value.compare("starts_with") == 0) + { + match_info.SetNameMatchType (eNameMatchStartsWith); + } + else if (value.compare("ends_with") == 0) + { + match_info.SetNameMatchType (eNameMatchEndsWith); + } + else if (value.compare("contains") == 0) + { + match_info.SetNameMatchType (eNameMatchContains); + } + else if (value.compare("regex") == 0) + { + match_info.SetNameMatchType (eNameMatchRegularExpression); + } + else + { + success = false; + } + } + else if (key.compare("pid") == 0) + { + match_info.GetProcessInfo().SetProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + } + else if (key.compare("parent_pid") == 0) + { + match_info.GetProcessInfo().SetParentProcessID (Args::StringToUInt32(value.c_str(), LLDB_INVALID_PROCESS_ID, 0, &success)); + } + else if (key.compare("uid") == 0) + { + match_info.GetProcessInfo().SetRealUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + } + else if (key.compare("gid") == 0) + { + match_info.GetProcessInfo().SetRealGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + } + else if (key.compare("euid") == 0) + { + match_info.GetProcessInfo().SetEffectiveUserID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + } + else if (key.compare("egid") == 0) + { + match_info.GetProcessInfo().SetEffectiveGroupID (Args::StringToUInt32(value.c_str(), UINT32_MAX, 0, &success)); + } + else if (key.compare("all_users") == 0) + { + match_info.SetMatchAllUsers(Args::StringToBoolean(value.c_str(), false, &success)); + } + else if (key.compare("triple") == 0) + { + match_info.GetProcessInfo().GetArchitecture().SetTriple(value.c_str()); + } + else + { + success = false; + } + + if (!success) + return SendErrorResponse (2); + } + } + + if (Host::FindProcesses (match_info, m_proc_infos)) + { + // We found something, return the first item by calling the get + // subsequent process info packet handler... + return Handle_qsProcessInfo (packet); + } + return SendErrorResponse (3); +} + +bool +GDBRemoteCommunicationServer::Handle_qsProcessInfo (StringExtractorGDBRemote &packet) +{ + if (m_proc_infos_index < m_proc_infos.GetSize()) + { + StreamString response; + CreateProcessInfoResponse (m_proc_infos.GetProcessInfoAtIndex(m_proc_infos_index), response); + ++m_proc_infos_index; + return SendPacket (response); + } + return SendErrorResponse (4); +} + +bool +GDBRemoteCommunicationServer::Handle_qUserName (StringExtractorGDBRemote &packet) +{ + // Packet format: "qUserName:%i" where %i is the uid + packet.SetFilePos(strlen ("qUserName:")); + uint32_t uid = packet.GetU32 (UINT32_MAX); + if (uid != UINT32_MAX) + { + std::string name; + if (Host::GetUserName (uid, name)) + { + StreamString response; + response.PutCStringAsRawHex8 (name.c_str()); + return SendPacket (response); + } + } + return SendErrorResponse (5); + } +bool +GDBRemoteCommunicationServer::Handle_qGroupName (StringExtractorGDBRemote &packet) +{ + // Packet format: "qGroupName:%i" where %i is the gid + packet.SetFilePos(strlen ("qGroupName:")); + uint32_t gid = packet.GetU32 (UINT32_MAX); + if (gid != UINT32_MAX) + { + std::string name; + if (Host::GetGroupName (gid, name)) + { + StreamString response; + response.PutCStringAsRawHex8 (name.c_str()); + return SendPacket (response); + } + } + return SendErrorResponse (6); +} bool -GDBRemoteCommunicationServer::Handle_QStartNoAckMode () +GDBRemoteCommunicationServer::Handle_QStartNoAckMode (StringExtractorGDBRemote &packet) { + // Send response first before changing m_send_acks to we ack this packet SendOKResponse (); m_send_acks = false; return true; diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h index 66ddc77bc95..22fb7be4e9f 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -14,9 +14,12 @@ // C++ Includes // Other libraries and framework includes // Project includes +#include "lldb/Target/Process.h" + #include "GDBRemoteCommunication.h" class ProcessGDBRemote; +class StringExtractorGDBRemote; class GDBRemoteCommunicationServer : public GDBRemoteCommunication { @@ -52,18 +55,38 @@ public: protected: lldb::thread_t m_async_thread; + lldb_private::ProcessInfoList m_proc_infos; + uint32_t m_proc_infos_index; + + size_t + SendUnimplementedResponse (const char *packet); size_t - SendUnimplementedResponse (); + SendErrorResponse (uint8_t error); size_t SendOKResponse (); bool - Handle_qHostInfo (); + Handle_qHostInfo (StringExtractorGDBRemote &packet); + + bool + Handle_qProcessInfoPID (StringExtractorGDBRemote &packet); + + bool + Handle_qfProcessInfo (StringExtractorGDBRemote &packet); + + bool + Handle_qsProcessInfo (StringExtractorGDBRemote &packet); + + bool + Handle_qUserName (StringExtractorGDBRemote &packet); + + bool + Handle_qGroupName (StringExtractorGDBRemote &packet); bool - Handle_QStartNoAckMode (); + Handle_QStartNoAckMode (StringExtractorGDBRemote &packet); private: //------------------------------------------------------------------ diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp index 556fa511b3a..0a1f87279f8 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteRegisterContext.cpp @@ -495,15 +495,15 @@ GDBRemoteDynamicRegisterInfo::HardcodeARMRegisters() { "sp", "r13", 4, 52, eEncodingUint, eFormatHex, { gcc_sp, dwarf_sp, LLDB_REGNUM_GENERIC_SP, LLDB_INVALID_REGNUM, 13 }}, { "lr", "r14", 4, 56, eEncodingUint, eFormatHex, { gcc_lr, dwarf_lr, LLDB_REGNUM_GENERIC_RA, LLDB_INVALID_REGNUM, 14 }}, { "pc", "r15", 4, 60, eEncodingUint, eFormatHex, { gcc_pc, dwarf_pc, LLDB_REGNUM_GENERIC_PC, LLDB_INVALID_REGNUM, 15 }}, - { NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 16 }}, - { NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 17 }}, - { NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 18 }}, - { NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 19 }}, - { NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 20 }}, - { NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 21 }}, - { NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 22 }}, - { NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 23 }}, - { NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 24 }}, +// { NULL, NULL, 12, 64, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 16 }}, +// { NULL, NULL, 12, 76, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 17 }}, +// { NULL, NULL, 12, 88, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 18 }}, +// { NULL, NULL, 12, 100, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 19 }}, +// { NULL, NULL, 12, 112, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 20 }}, +// { NULL, NULL, 12, 124, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 21 }}, +// { NULL, NULL, 12, 136, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 22 }}, +// { NULL, NULL, 12, 148, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 23 }}, +// { NULL, NULL, 12, 160, eEncodingIEEE754, eFormatFloat, { LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 24 }}, { "cpsr", "psr", 4, 172, eEncodingUint, eFormatHex, { gcc_cpsr, dwarf_cpsr, LLDB_REGNUM_GENERIC_FLAGS, LLDB_INVALID_REGNUM, 25 }}, { "s0", NULL, 4, 176, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 26 }}, { "s1", NULL, 4, 180, eEncodingIEEE754, eFormatFloat, { LLDB_INVALID_REGNUM, dwarf_s1, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, 27 }}, diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 987f24637d2..a2b17e56892 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -312,6 +312,7 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) else { response_type = StringExtractorGDBRemote::eError; + break; } } @@ -377,6 +378,7 @@ ProcessGDBRemote::DoConnectRemote (const char *remote_url) { // We have a valid process SetID (pid); + UpdateThreadListIfNeeded (); StringExtractorGDBRemote response; if (m_gdb_comm.SendPacketAndWaitForResponse("?", 1, response, false)) { @@ -601,23 +603,28 @@ ProcessGDBRemote::ConnectToDebugserver (const char *connect_url) return error; } - if (m_gdb_comm.StartReadThread(&error)) + // We always seem to be able to open a connection to a local port + // so we need to make sure we can then send data to it. If we can't + // then we aren't actually connected to anything, so try and do the + // handshake with the remote GDB server and make sure that goes + // alright. + if (!m_gdb_comm.HandshakeWithServer (NULL)) { - // Send an initial ack - m_gdb_comm.SendAck(); - - if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) - m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess, - this, - m_debugserver_pid, - false); - - m_gdb_comm.ResetDiscoverableSettings(); - m_gdb_comm.GetSendAcks (); - m_gdb_comm.GetThreadSuffixSupported (); - m_gdb_comm.GetHostInfo (); - m_gdb_comm.GetVContSupported ('c'); + m_gdb_comm.Disconnect(); + if (error.Success()) + error.SetErrorString("not connected to remote gdb server"); + return error; } + if (m_debugserver_pid != LLDB_INVALID_PROCESS_ID) + m_debugserver_thread = Host::StartMonitoringChildProcess (MonitorDebugserverProcess, + this, + m_debugserver_pid, + false); + m_gdb_comm.ResetDiscoverableSettings(); + m_gdb_comm.QueryNoAckModeSupported (); + m_gdb_comm.GetThreadSuffixSupported (); + m_gdb_comm.GetHostInfo (); + m_gdb_comm.GetVContSupported ('c'); return error; } @@ -633,9 +640,6 @@ ProcessGDBRemote::DidLaunchOrAttach () BuildDynamicRegisterInfo (false); - - StreamString strm; - // See if the GDB server supports the qHostInfo information const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture(); @@ -2364,13 +2368,13 @@ ProcessGDBRemote::GetDispatchQueueNameForThread { static ConstString g_dispatch_queue_offsets_symbol_name ("dispatch_queue_offsets"); const Symbol *dispatch_queue_offsets_symbol = NULL; - ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false))); + ModuleSP module_sp(GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libSystem.B.dylib", false), NULL, NULL)); if (module_sp) dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); if (dispatch_queue_offsets_symbol == NULL) { - module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false)); + module_sp = GetTarget().GetImages().FindFirstModuleForFileSpec (FileSpec("libdispatch.dylib", false), NULL, NULL); if (module_sp) dispatch_queue_offsets_symbol = module_sp->FindFirstSymbolWithNameAndType (g_dispatch_queue_offsets_symbol_name, eSymbolTypeData); } |