diff options
Diffstat (limited to 'lldb/source')
6 files changed, 194 insertions, 9 deletions
diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index fe88de4c866..f487ae94192 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -33,6 +33,7 @@ #include "lldb/Host/HostInfo.h" #include "lldb/Host/StringConvert.h" #include "lldb/Host/TimeValue.h" +#include "lldb/Symbol/Symbol.h" #include "lldb/Target/Target.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/UnixSignals.h" @@ -98,6 +99,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient() : m_supports_z4 (true), m_supports_QEnvironment (true), m_supports_QEnvironmentHexEncoded (true), + m_supports_qSymbol (true), m_curr_pid (LLDB_INVALID_PROCESS_ID), m_curr_tid (LLDB_INVALID_THREAD_ID), m_curr_tid_run (LLDB_INVALID_THREAD_ID), @@ -370,6 +372,7 @@ GDBRemoteCommunicationClient::ResetDiscoverableSettings() m_supports_z4 = true; m_supports_QEnvironment = true; m_supports_QEnvironmentHexEncoded = true; + m_supports_qSymbol = true; m_host_arch.Clear(); m_process_arch.Clear(); @@ -4241,3 +4244,87 @@ GDBRemoteCommunicationClient::ReadExtFeature (const lldb_private::ConstString ob err.Success( ); return true; } + +// Notify the target that gdb is prepared to serve symbol lookup requests. +// packet: "qSymbol::" +// reply: +// OK The target does not need to look up any (more) symbols. +// qSymbol:<sym_name> The target requests the value of symbol sym_name (hex encoded). +// LLDB may provide the value by sending another qSymbol packet +// in the form of"qSymbol:<sym_value>:<sym_name>". + +void +GDBRemoteCommunicationClient::ServeSymbolLookups(lldb_private::Process *process) +{ + if (m_supports_qSymbol) + { + Mutex::Locker locker; + if (GetSequenceMutex(locker, "GDBRemoteCommunicationClient::ServeSymbolLookups() failed due to not getting the sequence mutex")) + { + StreamString packet; + packet.PutCString ("qSymbol::"); + while (1) + { + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponseNoLock(packet.GetData(), packet.GetSize(), response) == PacketResult::Success) + { + if (response.IsOKResponse()) + { + // We are done serving symbols requests + return; + } + + if (response.IsUnsupportedResponse()) + { + // qSymbol is not supported by the current GDB server we are connected to + m_supports_qSymbol = false; + return; + } + else + { + llvm::StringRef response_str(response.GetStringRef()); + if (response_str.startswith("qSymbol:")) + { + response.SetFilePos(strlen("qSymbol:")); + std::string symbol_name; + if (response.GetHexByteString(symbol_name)) + { + if (symbol_name.empty()) + return; + + addr_t symbol_load_addr = LLDB_INVALID_ADDRESS; + lldb_private::SymbolContextList sc_list; + if (process->GetTarget().GetImages().FindSymbolsWithNameAndType(ConstString(symbol_name), eSymbolTypeAny, sc_list)) + { + SymbolContext sc; + if (sc_list.GetContextAtIndex(0, sc)) + { + if (sc.symbol) + symbol_load_addr = sc.symbol->GetAddress().GetLoadAddress(&process->GetTarget()); + } + } + // This is the normal path where our symbol lookup was successful and we want + // to send a packet with the new symbol value and see if another lookup needs to be + // done. + + // Change "packet" to contain the requested symbol value and name + packet.Clear(); + packet.PutCString("qSymbol:"); + if (symbol_load_addr != LLDB_INVALID_ADDRESS) + packet.Printf("%" PRIx64, symbol_load_addr); + packet.PutCString(":"); + packet.PutBytesAsRawHex8(symbol_name.data(), symbol_name.size()); + continue; // go back to the while loop and send "packet" and wait for another response + } + } + } + } + } + // If we make it here, the symbol request packet response wasn't valid or + // our symbol lookup failed so we must abort + return; + + } + } +} + diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 3e5d954c8af..07a3bd93321 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -556,6 +556,9 @@ public: std::string & out, lldb_private::Error & err); + void + ServeSymbolLookups(lldb_private::Process *process); + protected: PacketResult @@ -620,7 +623,8 @@ protected: m_supports_z3:1, m_supports_z4:1, m_supports_QEnvironment:1, - m_supports_QEnvironmentHexEncoded:1; + m_supports_QEnvironmentHexEncoded:1, + m_supports_qSymbol:1; lldb::pid_t m_curr_pid; lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index d41bdc70681..c1ad2e69754 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -1834,6 +1834,10 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) uint32_t exc_type = 0; std::vector<addr_t> exc_data; addr_t thread_dispatch_qaddr = LLDB_INVALID_ADDRESS; + bool queue_vars_valid = false; // says if locals below that start with "queue_" are valid + std::string queue_name; + QueueKind queue_kind = eQueueKindUnknown; + uint64_t queue_serial = 0; ThreadSP thread_sp; ThreadGDBRemote *gdb_thread = NULL; @@ -1914,6 +1918,29 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) { thread_dispatch_qaddr = StringConvert::ToUInt64 (value.c_str(), 0, 16); } + else if (name.compare("qname") == 0) + { + queue_vars_valid = true; + StringExtractor name_extractor; + // Swap "value" over into "name_extractor" + name_extractor.GetStringRef().swap(value); + // Now convert the HEX bytes into a string value + name_extractor.GetHexByteString (value); + queue_name.swap (value); + } + else if (name.compare("qkind") == 0) + { + queue_vars_valid = true; + if (value == "serial") + queue_kind = eQueueKindSerial; + else if (value == "concurrent") + queue_kind = eQueueKindConcurrent; + } + else if (name.compare("qserial") == 0) + { + queue_vars_valid = true; + queue_serial = StringConvert::ToUInt64 (value.c_str(), 0, 0); + } else if (name.compare("reason") == 0) { reason.swap(value); @@ -1976,6 +2003,11 @@ ProcessGDBRemote::SetThreadStopInfo (StringExtractor& stop_packet) thread_sp->SetStopInfo (StopInfoSP()); gdb_thread->SetThreadDispatchQAddr (thread_dispatch_qaddr); + if (queue_vars_valid) + gdb_thread->SetQueueInfo(std::move(queue_name), queue_kind, queue_serial); + else + gdb_thread->ClearQueueInfo(); + gdb_thread->SetName (thread_name.empty() ? NULL : thread_name.c_str()); if (exc_type != 0) { @@ -4236,6 +4268,19 @@ ProcessGDBRemote::GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb return Error("Unknown error happened during sending the load address packet"); } + +void +ProcessGDBRemote::ModulesDidLoad (ModuleList &module_list) +{ + // We must call the lldb_private::Process::ModulesDidLoad () first before we do anything + Process::ModulesDidLoad (module_list); + + // After loading shared libraries, we can ask our remote GDB server if + // it needs any symbols. + m_gdb_comm.ServeSymbolLookups(this); +} + + class CommandObjectProcessGDBRemoteSpeedTest: public CommandObjectParsed { public: diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h index 174d9e7501f..16e47dfcba6 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -244,6 +244,9 @@ public: Error GetFileLoadAddress(const FileSpec& file, bool& is_loaded, lldb::addr_t& load_addr) override; + void + ModulesDidLoad (ModuleList &module_list) override; + protected: friend class ThreadGDBRemote; friend class GDBRemoteCommunicationClient; diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp index e4108edc03f..e58121b1978 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.cpp @@ -40,9 +40,11 @@ ThreadGDBRemote::ThreadGDBRemote (Process &process, lldb::tid_t tid) : Thread(process, tid), m_thread_name (), m_dispatch_queue_name (), - m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS) + m_thread_dispatch_qaddr (LLDB_INVALID_ADDRESS), + m_queue_kind(eQueueKindUnknown), + m_queue_serial(0) { - ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", + ProcessGDBRemoteLog::LogIf(GDBR_LOG_THREAD, "%p: ThreadGDBRemote::ThreadGDBRemote (pid = %i, tid = 0x%4.4x)", this, process.GetID(), GetID()); @@ -66,10 +68,36 @@ ThreadGDBRemote::GetName () return m_thread_name.c_str(); } +void +ThreadGDBRemote::ClearQueueInfo () +{ + m_dispatch_queue_name.clear(); + m_queue_kind = eQueueKindUnknown; + m_queue_serial = 0; +} + +void +ThreadGDBRemote::SetQueueInfo (std::string &&queue_name, QueueKind queue_kind, uint64_t queue_serial) +{ + m_dispatch_queue_name = queue_name; + m_queue_kind = queue_kind; + m_queue_serial = queue_serial; +} + const char * ThreadGDBRemote::GetQueueName () { + // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...) + // with valid information that was gleaned from the stop reply packet. In this case we trust + // that the info is valid in m_dispatch_queue_name without refetching it + if (CachedQueueInfoIsValid()) + { + if (m_dispatch_queue_name.empty()) + return nullptr; + else + return m_dispatch_queue_name.c_str(); + } // Always re-fetch the dispatch queue name since it can change if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) @@ -79,13 +107,12 @@ ThreadGDBRemote::GetQueueName () { SystemRuntime *runtime = process_sp->GetSystemRuntime (); if (runtime) - { m_dispatch_queue_name = runtime->GetQueueNameFromThreadQAddress (m_thread_dispatch_qaddr); - } - if (m_dispatch_queue_name.length() > 0) - { + else + m_dispatch_queue_name.clear(); + + if (!m_dispatch_queue_name.empty()) return m_dispatch_queue_name.c_str(); - } } } return NULL; @@ -94,6 +121,12 @@ ThreadGDBRemote::GetQueueName () queue_id_t ThreadGDBRemote::GetQueueID () { + // If our cached queue info is valid, then someone called ThreadGDBRemote::SetQueueInfo(...) + // with valid information that was gleaned from the stop reply packet. In this case we trust + // that the info is valid in m_dispatch_queue_name without refetching it + if (CachedQueueInfoIsValid()) + return m_queue_serial; + if (m_thread_dispatch_qaddr != 0 || m_thread_dispatch_qaddr != LLDB_INVALID_ADDRESS) { ProcessSP process_sp (GetProcess()); diff --git a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h index 8bff54456dc..175433a3e20 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h +++ b/lldb/source/Plugins/Process/gdb-remote/ThreadGDBRemote.h @@ -91,6 +91,12 @@ public: m_thread_dispatch_qaddr = thread_dispatch_qaddr; } + void + ClearQueueInfo (); + + void + SetQueueInfo (std::string &&queue_name, lldb::QueueKind queue_kind, uint64_t queue_serial); + StructuredData::ObjectSP FetchThreadExtendedInfo () override; @@ -101,13 +107,20 @@ protected: bool PrivateSetRegisterValue (uint32_t reg, StringExtractor &response); - + + bool + CachedQueueInfoIsValid() const + { + return m_queue_kind != lldb::eQueueKindUnknown; + } //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ std::string m_thread_name; std::string m_dispatch_queue_name; lldb::addr_t m_thread_dispatch_qaddr; + lldb::QueueKind m_queue_kind; // Queue info from stop reply/stop info for thread + uint64_t m_queue_serial; // Queue info from stop reply/stop info for thread //------------------------------------------------------------------ // Member variables. //------------------------------------------------------------------ |