Author: Jason Molenda Date: 2021-12-23T15:20:50-08:00 New Revision: 8a26ba6a02f1319ddaca017bbda81c2b82fb4050
URL: https://github.com/llvm/llvm-project/commit/8a26ba6a02f1319ddaca017bbda81c2b82fb4050 DIFF: https://github.com/llvm/llvm-project/commit/8a26ba6a02f1319ddaca017bbda81c2b82fb4050.diff LOG: Load binary by UUID from qProcessInfo packet fields Support three new keys in the qProcessInfo response from the remote gdb stub to handle the case of attaching to a core running some type of standalone/firmware code and the stub knows the UUID and load address-or-slide for the binary. There will be no proper DynamicLoader plugin in this scenario, but we can try to locate and load the binary into lldb at the correct offset. Differential Revision: https://reviews.llvm.org/D116211 rdar://75191077 Added: Modified: lldb/docs/lldb-gdb-remote.txt lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp Removed: ################################################################################ diff --git a/lldb/docs/lldb-gdb-remote.txt b/lldb/docs/lldb-gdb-remote.txt index 17588021e3139..980dc77c86f53 100644 --- a/lldb/docs/lldb-gdb-remote.txt +++ b/lldb/docs/lldb-gdb-remote.txt @@ -1003,6 +1003,9 @@ 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 +main-binary-uuid: is the UUID of a firmware type binary that the gdb stub knows about +main-binary-address: is the load address of the firmware type binary +main-binary-slide: is the slide of the firmware type binary, if address isn't known //---------------------------------------------------------------------- // "qShlibInfoAddr" diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp index 07dfa5e04ee57..b5b105351de5d 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -1006,6 +1006,23 @@ GDBRemoteCommunicationClient::GetProcessArchitecture() { return m_process_arch; } +bool GDBRemoteCommunicationClient::GetProcessStandaloneBinary( + UUID &uuid, addr_t &value, bool &value_is_offset) { + if (m_qProcessInfo_is_valid == eLazyBoolCalculate) + GetCurrentProcessInfo(); + + // Return true if we have a UUID or an address/offset of the + // main standalone / firmware binary being used. + if (!m_process_standalone_uuid.IsValid() && + m_process_standalone_value == LLDB_INVALID_ADDRESS) + return false; + + uuid = m_process_standalone_uuid; + value = m_process_standalone_value; + value_is_offset = m_process_standalone_value_is_offset; + return true; +} + bool GDBRemoteCommunicationClient::GetGDBServerVersion() { if (m_qGDBServerVersion_is_valid == eLazyBoolCalculate) { m_gdb_server_name.clear(); @@ -2147,6 +2164,25 @@ bool GDBRemoteCommunicationClient::GetCurrentProcessInfo(bool allow_lazy) { } else if (name.equals("elf_abi")) { elf_abi = std::string(value); ++num_keys_decoded; + } else if (name.equals("main-binary-uuid")) { + m_process_standalone_uuid.SetFromStringRef(value); + ++num_keys_decoded; + } else if (name.equals("main-binary-slide")) { + StringExtractor extractor(value); + m_process_standalone_value = + extractor.GetU64(LLDB_INVALID_ADDRESS, 16); + if (m_process_standalone_value != LLDB_INVALID_ADDRESS) { + m_process_standalone_value_is_offset = true; + ++num_keys_decoded; + } + } else if (name.equals("main-binary-address")) { + StringExtractor extractor(value); + m_process_standalone_value = + extractor.GetU64(LLDB_INVALID_ADDRESS, 16); + if (m_process_standalone_value != LLDB_INVALID_ADDRESS) { + m_process_standalone_value_is_offset = false; + ++num_keys_decoded; + } } } if (num_keys_decoded > 0) diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h index 6765372ce1245..c69c33bb1c153 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -217,6 +217,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { const ArchSpec &GetProcessArchitecture(); + bool GetProcessStandaloneBinary(UUID &uuid, lldb::addr_t &value, + bool &value_is_offset); + void GetRemoteQSupported(); bool GetVContSupported(char flavor); @@ -584,6 +587,9 @@ class GDBRemoteCommunicationClient : public GDBRemoteClientBase { ArchSpec m_host_arch; ArchSpec m_process_arch; + UUID m_process_standalone_uuid; + lldb::addr_t m_process_standalone_value = LLDB_INVALID_ADDRESS; + bool m_process_standalone_value_is_offset = false; llvm::VersionTuple m_os_version; llvm::VersionTuple m_maccatalyst_version; std::string m_os_build; diff --git a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp index 89702d176ef8b..93fe36c0d9d69 100644 --- a/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -561,6 +561,94 @@ Status ProcessGDBRemote::DoConnectRemote(llvm::StringRef remote_url) { } } + // The remote stub may know about the "main binary" in + // the context of a firmware debug session, and can + // give us a UUID and an address/slide of where the + // binary is loaded in memory. + UUID standalone_uuid; + addr_t standalone_value; + bool standalone_value_is_offset; + if (m_gdb_comm.GetProcessStandaloneBinary( + standalone_uuid, standalone_value, standalone_value_is_offset)) { + ModuleSP module_sp; + + if (standalone_uuid.IsValid()) { + ModuleSpec module_spec; + module_spec.GetUUID() = standalone_uuid; + + // Look up UUID in global module cache before attempting + // a more expensive search. + Status error = ModuleList::GetSharedModule(module_spec, module_sp, + nullptr, nullptr, nullptr); + + if (!module_sp) { + // Force a an external lookup, if that tool is available. + if (!module_spec.GetSymbolFileSpec()) + Symbols::DownloadObjectAndSymbolFile(module_spec, true); + + if (FileSystem::Instance().Exists(module_spec.GetFileSpec())) { + module_sp = std::make_shared<Module>(module_spec); + } + } + + // If we couldn't find the binary anywhere else, as a last resort, + // read it out of memory. + if (!module_sp.get() && standalone_value != LLDB_INVALID_ADDRESS && + !standalone_value_is_offset) { + char namebuf[80]; + snprintf(namebuf, sizeof(namebuf), "mem-image-0x%" PRIx64, + standalone_value); + module_sp = + ReadModuleFromMemory(FileSpec(namebuf), standalone_value); + } + + Log *log(ProcessGDBRemoteLog::GetLogIfAllCategoriesSet( + LIBLLDB_LOG_DYNAMIC_LOADER)); + if (module_sp.get()) { + target.GetImages().AppendIfNeeded(module_sp, false); + + bool changed = false; + if (module_sp->GetObjectFile()) { + if (standalone_value != LLDB_INVALID_ADDRESS) { + if (log) + log->Printf("Loading binary UUID %s at %s 0x%" PRIx64, + standalone_uuid.GetAsString().c_str(), + standalone_value_is_offset ? "offset" : "address", + standalone_value); + module_sp->SetLoadAddress(target, standalone_value, + standalone_value_is_offset, changed); + } else { + // No address/offset/slide, load the binary at file address, + // offset 0. + if (log) + log->Printf("Loading binary UUID %s at file address", + standalone_uuid.GetAsString().c_str()); + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + } else { + // In-memory image, load at its true address, offset 0. + if (log) + log->Printf("Loading binary UUID %s from memory", + standalone_uuid.GetAsString().c_str()); + const bool value_is_slide = true; + module_sp->SetLoadAddress(target, 0, value_is_slide, changed); + } + + ModuleList added_module; + added_module.Append(module_sp, false); + target.ModulesDidLoad(added_module); + } else { + if (log) + log->Printf("Unable to find binary with UUID %s and load it at " + "%s 0x%" PRIx64, + standalone_uuid.GetAsString().c_str(), + standalone_value_is_offset ? "offset" : "address", + standalone_value); + } + } + } + const StateType state = SetThreadStopInfo(response); if (state != eStateInvalid) { SetPrivateState(state); _______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits