diff options
5 files changed, 199 insertions, 23 deletions
diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index 594e3fc3a86..e80af4f66e4 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -407,14 +407,23 @@ ptrsize: is a number that represents how big pointers are in bytes on the debug // Medium. On systems which can launch multiple different architecture processes, // the qHostInfo may not disambiguate sufficiently to know what kind of // process is being debugged. -// e.g. on a 64-bit x86 Mc system both 32-bit and 64-bit user processes are possible, +// e.g. on a 64-bit x86 Mac system both 32-bit and 64-bit user processes are possible, // and with Mach-O univeral files, the executable file may contain both 32- and // 64-bit slices so it may be impossible to know until you're attached to a real // process to know what you're working with. +// +// All numeric fields return base-16 numbers without any "0x" prefix. //---------------------------------------------------------------------- +An i386 process: + +send packet: $qProcessInfo#00 +read packet: $pid:42a8;parent-pid:42bf;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:7;cpusubtype:3;ostype:macosx;vendor:apple;endian:little;ptrsize:4;#00 + +An x86_64 process: + send packet: $qProcessInfo#00 -$pid:0x9517;parent-pid:0x9519;real-uid:0xecf;real-gid:0xb;effective-uid:0xecf;effective-gid:0xb;cputype:0x7;ptrsize:0x4;#00 +read packet: $pid:d22c;parent-pid:d34d;real-uid:ecf;real-gid:b;effective-uid:ecf;effective-gid:b;cputype:1000007;cpusubtype:3;ostype:macosx;vendor:apple;endian:little;ptrsize:8;#00 Key value pairs include: @@ -425,6 +434,10 @@ real-gid: the real group id of the process effective-uid: the effective user id of the process effective-gid: the effective group id of the process cputype: the Mach-O CPU type of the process +cpusubtype: the Mach-O CPU subtype of the process +ostype: is a string the represents the OS being debugged (darwin, lunix, freebsd) +vendor: is a string that represents the vendor (apple) +endian: is one of "little", "big", or "pdp" ptrsize: is a number that represents how big pointers are in bytes diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 9aa504110db..63ddc5d957d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -46,6 +46,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_supports_vCont_s (eLazyBoolCalculate), m_supports_vCont_S (eLazyBoolCalculate), m_qHostInfo_is_valid (eLazyBoolCalculate), + m_qProcessInfo_is_valid (eLazyBoolCalculate), m_supports_alloc_dealloc_memory (eLazyBoolCalculate), m_supports_memory_region_info (eLazyBoolCalculate), m_supports_watchpoint_support_info (eLazyBoolCalculate), @@ -71,6 +72,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient(bool is_platform) : m_async_response (), m_async_signal (-1), m_host_arch(), + m_process_arch(), m_os_version_major (UINT32_MAX), m_os_version_minor (UINT32_MAX), m_os_version_update (UINT32_MAX) @@ -187,6 +189,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_vCont_s = eLazyBoolCalculate; m_supports_vCont_S = eLazyBoolCalculate; m_qHostInfo_is_valid = eLazyBoolCalculate; + m_qProcessInfo_is_valid = eLazyBoolCalculate; m_supports_alloc_dealloc_memory = eLazyBoolCalculate; m_supports_memory_region_info = eLazyBoolCalculate; m_prepare_for_reg_writing_reply = eLazyBoolCalculate; @@ -203,6 +206,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_z3 = true; m_supports_z4 = true; m_host_arch.Clear(); + m_process_arch.Clear(); } @@ -963,6 +967,14 @@ GDBRemoteCommunicationClient::GetSystemArchitecture () return ArchSpec(); } +const lldb_private::ArchSpec & +GDBRemoteCommunicationClient::GetProcessArchitecture () +{ + if (m_qProcessInfo_is_valid == eLazyBoolCalculate) + GetCurrentProcessInfo (); + return m_process_arch; +} + bool GDBRemoteCommunicationClient::GetHostInfo (bool force) @@ -1634,6 +1646,100 @@ GDBRemoteCommunicationClient::GetProcessInfo (lldb::pid_t pid, ProcessInstanceIn return false; } +bool +GDBRemoteCommunicationClient::GetCurrentProcessInfo () +{ + if (m_qProcessInfo_is_valid == eLazyBoolYes) + return true; + if (m_qProcessInfo_is_valid == eLazyBoolNo) + return false; + + GetHostInfo (); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse ("qProcessInfo", response, false)) + { + if (response.IsNormalResponse()) + { + 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)) + { + if (name.compare("cputype") == 0) + { + cpu = Args::StringToUInt32 (value.c_str(), LLDB_INVALID_CPUTYPE, 16); + if (cpu != LLDB_INVALID_CPUTYPE) + ++num_keys_decoded; + } + else if (name.compare("cpusubtype") == 0) + { + sub = Args::StringToUInt32 (value.c_str(), 0, 16); + if (sub != 0) + ++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, 16); + if (pointer_byte_size != 0) + ++num_keys_decoded; + } + } + if (num_keys_decoded > 0) + m_qProcessInfo_is_valid = eLazyBoolYes; + if (cpu != LLDB_INVALID_CPUTYPE && !os_name.empty() && !vendor_name.empty()) + { + m_process_arch.SetArchitecture (eArchTypeMachO, cpu, sub); + if (pointer_byte_size) + { + assert (pointer_byte_size == m_process_arch.GetAddressByteSize()); + } + m_host_arch.GetTriple().setVendorName (llvm::StringRef (vendor_name)); + m_host_arch.GetTriple().setOSName (llvm::StringRef (os_name)); + return true; + } + } + } + else + { + m_qProcessInfo_is_valid = eLazyBoolNo; + } + + return false; +} + + uint32_t GDBRemoteCommunicationClient::FindProcesses (const ProcessInstanceInfoMatch &match_info, ProcessInstanceInfoList &process_infos) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 449aa5ad0ac..201ce61eece 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -217,7 +217,10 @@ public: const lldb_private::ArchSpec & GetHostArchitecture (); - + + const lldb_private::ArchSpec & + GetProcessArchitecture (); + bool GetVContSupported (char flavor); @@ -353,6 +356,9 @@ public: } protected: + bool + GetCurrentProcessInfo (); + //------------------------------------------------------------------ // Classes that inherit from GDBRemoteCommunicationClient can see and modify these //------------------------------------------------------------------ @@ -366,6 +372,7 @@ protected: lldb_private::LazyBool m_supports_vCont_s; lldb_private::LazyBool m_supports_vCont_S; lldb_private::LazyBool m_qHostInfo_is_valid; + lldb_private::LazyBool m_qProcessInfo_is_valid; lldb_private::LazyBool m_supports_alloc_dealloc_memory; lldb_private::LazyBool m_supports_memory_region_info; lldb_private::LazyBool m_supports_watchpoint_support_info; @@ -402,6 +409,7 @@ protected: bool m_interrupt_sent; lldb_private::ArchSpec m_host_arch; + lldb_private::ArchSpec m_process_arch; uint32_t m_os_version_major; uint32_t m_os_version_minor; uint32_t m_os_version_update; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 0b6f12eca43..b00c4c95a56 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -393,7 +393,16 @@ ProcessGDBRemote::BuildDynamicRegisterInfo (bool force) bool from_scratch = (reg_num == 0); const ArchSpec &target_arch = GetTarget().GetArchitecture(); - const ArchSpec &remote_arch = m_gdb_comm.GetHostArchitecture(); + const ArchSpec &remote_host_arch = m_gdb_comm.GetHostArchitecture(); + const ArchSpec &remote_process_arch = m_gdb_comm.GetProcessArchitecture(); + + // Use the process' architecture instead of the host arch, if available + ArchSpec remote_arch; + if (remote_process_arch.IsValid ()) + remote_arch = remote_process_arch; + else + remote_arch = remote_host_arch; + if (!target_arch.IsValid()) { if (remote_arch.IsValid() @@ -480,7 +489,11 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url) && !GetTarget().GetArchitecture().IsValid() && m_gdb_comm.GetHostArchitecture().IsValid()) { - GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); + // Prefer the *process'* architecture over that of the *host*, if available. + if (m_gdb_comm.GetProcessArchitecture().IsValid()) + GetTarget().SetArchitecture(m_gdb_comm.GetProcessArchitecture()); + else + GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture()); } return error; @@ -866,7 +879,15 @@ ProcessGDBRemote::DidLaunchOrAttach () // See if the GDB server supports the qHostInfo information - const ArchSpec &gdb_remote_arch = m_gdb_comm.GetHostArchitecture(); + ArchSpec gdb_remote_arch = m_gdb_comm.GetHostArchitecture(); + + // See if the GDB server supports the qProcessInfo packet, if so + // prefer that over the Host information as it will be more specific + // to our process. + + if (m_gdb_comm.GetProcessArchitecture().IsValid()) + gdb_remote_arch = m_gdb_comm.GetProcessArchitecture(); + if (gdb_remote_arch.IsValid()) { ArchSpec &target_arch = GetTarget().GetArchitecture(); diff --git a/lldb/tools/debugserver/source/RNBRemote.cpp b/lldb/tools/debugserver/source/RNBRemote.cpp index 1c13a325e75..271ceb5cef8 100644 --- a/lldb/tools/debugserver/source/RNBRemote.cpp +++ b/lldb/tools/debugserver/source/RNBRemote.cpp @@ -3781,8 +3781,7 @@ RNBRemote::HandlePacket_qHostInfo (const char *p) // Note that all numeric values returned by qProcessInfo are hex encoded, -// including the pid and the cpu type, and are fixed with "0x" to indicate -// this encoding. +// including the pid and the cpu type. rnb_err_t RNBRemote::HandlePacket_qProcessInfo (const char *p) @@ -3796,7 +3795,7 @@ RNBRemote::HandlePacket_qProcessInfo (const char *p) pid = m_ctx.ProcessID(); - rep << "pid:0x" << std::hex << pid << ";"; + rep << "pid:" << std::hex << pid << ";"; int procpid_mib[4]; procpid_mib[0] = CTL_KERN; @@ -3810,34 +3809,63 @@ RNBRemote::HandlePacket_qProcessInfo (const char *p) { if (proc_kinfo_size > 0) { - rep << "parent-pid:0x" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";"; - rep << "real-uid:0x" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";"; - rep << "real-gid:0x" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";"; - rep << "effective-uid:0x" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";"; + rep << "parent-pid:" << std::hex << proc_kinfo.kp_eproc.e_ppid << ";"; + rep << "real-uid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_ruid << ";"; + rep << "real-gid:" << std::hex << proc_kinfo.kp_eproc.e_pcred.p_rgid << ";"; + rep << "effective-uid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_uid << ";"; if (proc_kinfo.kp_eproc.e_ucred.cr_ngroups > 0) - rep << "effective-gid:0x" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";"; + rep << "effective-gid:" << std::hex << proc_kinfo.kp_eproc.e_ucred.cr_groups[0] << ";"; } } int cputype_mib[CTL_MAXNAME]={0,}; size_t cputype_mib_len = CTL_MAXNAME; + cpu_type_t cputype = -1; if (::sysctlnametomib("sysctl.proc_cputype", cputype_mib, &cputype_mib_len) == 0) { cputype_mib[cputype_mib_len] = pid; cputype_mib_len++; - cpu_type_t cpu; - size_t len = sizeof(cpu); - if (::sysctl (cputype_mib, cputype_mib_len, &cpu, &len, 0, 0) == 0) + size_t len = sizeof(cputype); + if (::sysctl (cputype_mib, cputype_mib_len, &cputype, &len, 0, 0) == 0) { - rep << "cputype:0x" << std::hex << cpu << ";"; + rep << "cputype:" << std::hex << cputype << ";"; } } - nub_thread_t thread = DNBProcessGetCurrentThread (pid); + uint32_t cpusubtype; + size_t cpusubtype_len = sizeof(cpusubtype); + if (::sysctlbyname("hw.cpusubtype", &cpusubtype, &cpusubtype_len, NULL, 0) == 0) + { + if (cputype == CPU_TYPE_X86_64 && cpusubtype == CPU_SUBTYPE_486) + { + cpusubtype = CPU_SUBTYPE_X86_64_ALL; + } + rep << "cpusubtype:" << std::hex << cpusubtype << ';'; + } + + // The OS in the triple should be "ios" or "macosx" which doesn't match our + // "Darwin" which gets returned from "kern.ostype", so we need to hardcode + // this for now. + if (cputype == CPU_TYPE_ARM) + rep << "ostype:ios;"; + else + rep << "ostype:macosx;"; + + rep << "vendor:apple;"; + +#if defined (__LITTLE_ENDIAN__) + rep << "endian:little;"; +#elif defined (__BIG_ENDIAN__) + rep << "endian:big;"; +#elif defined (__PDP_ENDIAN__) + rep << "endian:pdp;"; +#endif + + nub_thread_t thread = DNBProcessGetCurrentThread (pid); kern_return_t kr; -#if defined (__x86_64__) || defined (__i386__) +#if (defined (__x86_64__) || defined (__i386__)) && defined (x86_THREAD_STATE) x86_thread_state_t gp_regs; mach_msg_type_number_t gp_count = x86_THREAD_STATE_COUNT; kr = thread_get_state (thread, x86_THREAD_STATE, @@ -3845,12 +3873,12 @@ RNBRemote::HandlePacket_qProcessInfo (const char *p) if (kr == KERN_SUCCESS) { if (gp_regs.tsh.flavor == x86_THREAD_STATE64) - rep << "ptrsize:0x8;"; + rep << "ptrsize:8;"; else - rep << "ptrsize:0x4;"; + rep << "ptrsize:4;"; } #elif defined (__arm__) - rep << "ptrsize:0x4;"; + rep << "ptrsize:4;"; #endif return SendPacket (rep.str()); |

