labath updated this revision to Diff 70409. labath added a comment. - fix a bug where we would mark all modules as invalid if communicating with a stub which does not support this packet - extend the packet documentation about what to do when modules are not found and the server volunteering information
https://reviews.llvm.org/D24236 Files: docs/lldb-gdb-remote.txt include/lldb/Target/Process.h packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp source/Plugins/Process/gdb-remote/ProcessGDBRemote.h source/Utility/StringExtractorGDBRemote.cpp source/Utility/StringExtractorGDBRemote.h unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp
Index: unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp =================================================================== --- unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp +++ unittests/Process/gdb-remote/GDBRemoteCommunicationClientTest.cpp @@ -19,6 +19,7 @@ #include "Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h" #include "lldb/Core/DataBuffer.h" +#include "lldb/Core/ModuleSpec.h" #include "llvm/ADT/ArrayRef.h" @@ -182,3 +183,75 @@ HandlePacket(server, "QSyncThreadState:0047;", "OK"); ASSERT_TRUE(async_result.get()); } + +TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfo) +{ + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + llvm::Triple triple("i386-pc-linux"); + + // Empty list of module specs should not send any packets + ASSERT_TRUE(client.GetModulesInfo({}, triple).empty()); + + FileSpec file_specs[] = { FileSpec("/foo/bar.so", false), FileSpec("/foo/baz.so", false) }; + std::future<std::vector<ModuleSpec>> async_result = + std::async(std::launch::async, [&] { return client.GetModulesInfo(file_specs, triple); }); + HandlePacket(server, "jModulesInfo:[" + R"({"file":"/foo/bar.so","triple":"i386-pc-linux"},)" + R"({"file":"/foo/baz.so","triple":"i386-pc-linux"}])", + R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" + R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}]])"); + + std::vector<ModuleSpec> result = async_result.get(); + ASSERT_EQ(1u, result.size()); + EXPECT_EQ("/foo/bar.so", result[0].GetFileSpec().GetPath()); + EXPECT_EQ(triple, result[0].GetArchitecture().GetTriple()); + EXPECT_EQ(UUID("@ABCDEFGHIJKLMNO", 16), result[0].GetUUID()); + EXPECT_EQ(0u, result[0].GetObjectOffset()); + EXPECT_EQ(1234u, result[0].GetObjectSize()); +} + +TEST_F(GDBRemoteCommunicationClientTest, GetModulesInfoInvalidResponse) +{ + TestClient client; + MockServer server; + Connect(client, server); + if (HasFailure()) + return; + + llvm::Triple triple("i386-pc-linux"); + FileSpec file_spec("/foo/bar.so", false); + + const char *invalid_responses[] = { + "OK", "E47", "[]", "[{}]]", + // no UUID + R"([{"triple":"i386-pc-linux",)" + R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}])", + // no triple + R"([{"uuid":"404142434445464748494a4b4c4d4e4f",)" + R"("file_path":"/foo/bar.so","file_offset":0,"file_size":1234}])", + // no file_path + R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" + R"("file_offset":0,"file_size":1234}])", + // no file_offset + R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" + R"("file_path":"/foo/bar.so","file_size":1234}])", + // no file_size + R"([{"uuid":"404142434445464748494a4b4c4d4e4f","triple":"i386-pc-linux",)" + R"("file_path":"/foo/bar.so","file_offset":0}])", + }; + + for(const char *response: invalid_responses) + { + std::future<std::vector<ModuleSpec>> async_result = + std::async(std::launch::async, [&] { return client.GetModulesInfo(file_spec, triple); }); + HandlePacket(server, R"(jModulesInfo:[{"file":"/foo/bar.so","triple":"i386-pc-linux"}])", + response); + + ASSERT_TRUE(async_result.get().empty()); + } +} Index: source/Utility/StringExtractorGDBRemote.h =================================================================== --- source/Utility/StringExtractorGDBRemote.h +++ source/Utility/StringExtractorGDBRemote.h @@ -146,6 +146,7 @@ eServerPacketType_qXfer_auxv_read, eServerPacketType_jSignalsInfo, + eServerPacketType_jModulesInfo, eServerPacketType_vAttach, eServerPacketType_vAttachWait, Index: source/Utility/StringExtractorGDBRemote.cpp =================================================================== --- source/Utility/StringExtractorGDBRemote.cpp +++ source/Utility/StringExtractorGDBRemote.cpp @@ -223,6 +223,7 @@ break; case 'j': + if (PACKET_STARTS_WITH("jModulesInfo:")) return eServerPacketType_jModulesInfo; if (PACKET_MATCHES("jSignalsInfo")) return eServerPacketType_jSignalsInfo; if (PACKET_MATCHES("jThreadsInfo")) return eServerPacketType_jThreadsInfo; break; Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.h =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.h +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.h @@ -28,6 +28,7 @@ #include "lldb/Core/StringList.h" #include "lldb/Core/StructuredData.h" #include "lldb/Core/ThreadSafeValue.h" +#include "lldb/Core/ModuleSpec.h" #include "lldb/Core/LoadedModuleInfoList.h" #include "lldb/Host/HostThread.h" #include "lldb/lldb-private-forward.h" @@ -38,6 +39,8 @@ #include "GDBRemoteCommunicationClient.h" #include "GDBRemoteRegisterContext.h" +#include "llvm/ADT/DenseMap.h" + namespace lldb_private { namespace process_gdb_remote { @@ -241,6 +244,9 @@ const ArchSpec& arch, ModuleSpec &module_spec) override; + void + PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) override; + bool GetHostOSVersion(uint32_t &major, uint32_t &minor, @@ -514,6 +520,42 @@ HandleAsyncStructuredData(const StructuredData::ObjectSP &object_sp) override; + + using ModuleCacheKey = std::pair<std::string, std::string>; + // KeyInfo for the cached module spec DenseMap. + // The invariant is that all real keys will have the file and architecture set. + // The empty key has an empty file and an empty arch. + // The tombstone key has an invalid arch and an empty file. + // The comparison and hash functions take the file name and architecture triple into account. + struct ModuleCacheInfo + { + static ModuleCacheKey + getEmptyKey() + { + return ModuleCacheKey(); + } + + static ModuleCacheKey + getTombstoneKey() + { + return ModuleCacheKey("", "T"); + } + + static unsigned + getHashValue(const ModuleCacheKey &key) + { + return llvm::hash_combine(key.first, key.second); + } + + static bool + isEqual(const ModuleCacheKey &LHS, const ModuleCacheKey &RHS) + { + return LHS == RHS; + } + }; + + llvm::DenseMap<ModuleCacheKey, ModuleSpec, ModuleCacheInfo> m_cached_module_specs; + DISALLOW_COPY_AND_ASSIGN (ProcessGDBRemote); }; Index: source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp =================================================================== --- source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp +++ source/Plugins/Process/gdb-remote/ProcessGDBRemote.cpp @@ -4397,6 +4397,14 @@ { Log *log = GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PLATFORM); + const ModuleCacheKey key(module_file_spec.GetPath(), arch.GetTriple().getTriple()); + auto cached = m_cached_module_specs.find(key); + if (cached != m_cached_module_specs.end()) + { + module_spec = cached->second; + return bool(module_spec); + } + if (!m_gdb_comm.GetModuleInfo (module_file_spec, arch, module_spec)) { if (log) @@ -4415,9 +4423,22 @@ arch.GetTriple ().getTriple ().c_str (), stream.GetString ().c_str ()); } + m_cached_module_specs[key] = module_spec; return true; } +void +ProcessGDBRemote::PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) +{ + auto module_specs = m_gdb_comm.GetModulesInfo(module_file_specs, triple); + if (module_specs) { + for (const FileSpec &spec : module_file_specs) + m_cached_module_specs[{spec.GetPath(), triple.getTriple()}] = ModuleSpec(); + for (const ModuleSpec &spec : *module_specs) + m_cached_module_specs[{spec.GetFileSpec().GetPath(), triple.getTriple()}] = spec; + } +} + bool ProcessGDBRemote::GetHostOSVersion(uint32_t &major, uint32_t &minor, Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.h @@ -109,6 +109,9 @@ Handle_qModuleInfo (StringExtractorGDBRemote &packet); PacketResult + Handle_jModulesInfo(StringExtractorGDBRemote &packet); + + PacketResult Handle_qPlatform_shell (StringExtractorGDBRemote &packet); PacketResult @@ -192,6 +195,12 @@ virtual FileSpec FindModuleFile (const std::string& module_path, const ArchSpec& arch); + + +private: + ModuleSpec + GetModuleInfo(const std::string &module_path, const std::string &triple); + }; } // namespace process_gdb_remote Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -39,6 +39,7 @@ #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/JSON.h" // Project includes #include "ProcessGDBRemoteLog.h" @@ -94,6 +95,8 @@ &GDBRemoteCommunicationServerCommon::Handle_qEcho); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qModuleInfo, &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo); + RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_jModulesInfo, + &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod, &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod); RegisterMemberFunctionHandler(StringExtractorGDBRemote::eServerPacketType_qPlatform_mkdir, @@ -1125,20 +1128,11 @@ std::string triple; packet.GetHexByteString(triple); - ArchSpec arch(triple.c_str()); - - const FileSpec req_module_path_spec(module_path.c_str(), true); - const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch); - const ModuleSpec module_spec(module_path_spec, arch); - ModuleSpecList module_specs; - if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, module_specs)) + ModuleSpec matched_module_spec = GetModuleInfo(module_path, triple); + if (!matched_module_spec.GetFileSpec()) return SendErrorResponse (3); - ModuleSpec matched_module_spec; - if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) - return SendErrorResponse (4); - const auto file_offset = matched_module_spec.GetObjectOffset(); const auto file_size = matched_module_spec.GetObjectSize(); const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); @@ -1165,7 +1159,7 @@ response.PutChar(';'); response.PutCString("file_path:"); - response.PutCStringAsRawHex8(module_path_spec.GetCString()); + response.PutCStringAsRawHex8(matched_module_spec.GetFileSpec().GetCString()); response.PutChar(';'); response.PutCString("file_offset:"); response.PutHex64(file_offset); @@ -1177,6 +1171,57 @@ return SendPacketNoLock(response.GetString()); } +GDBRemoteCommunication::PacketResult +GDBRemoteCommunicationServerCommon::Handle_jModulesInfo(StringExtractorGDBRemote &packet) +{ + packet.SetFilePos(::strlen ("jModulesInfo:")); + + StructuredData::ObjectSP object_sp = StructuredData::ParseJSON (packet.Peek()); + if (!object_sp) + return SendErrorResponse(1); + + StructuredData::Array *packet_array = object_sp->GetAsArray(); + if (!packet_array) + return SendErrorResponse(2); + + JSONArray::SP response_array_sp = std::make_shared<JSONArray>(); + for (size_t i = 0; i < packet_array->GetSize(); ++i) + { + StructuredData::Dictionary *query = packet_array->GetItemAtIndex(i)->GetAsDictionary(); + if (!query) + continue; + std::string file, triple; + if (!query->GetValueForKeyAsString("file", file) || !query->GetValueForKeyAsString("triple", triple)) + continue; + + ModuleSpec matched_module_spec = GetModuleInfo(file, triple); + if (!matched_module_spec.GetFileSpec()) + continue; + + const auto file_offset = matched_module_spec.GetObjectOffset(); + const auto file_size = matched_module_spec.GetObjectSize(); + const auto uuid_str = matched_module_spec.GetUUID().GetAsString(""); + + if (uuid_str.empty()) + continue; + + JSONObject::SP response = std::make_shared<JSONObject>(); + response_array_sp->AppendObject(response); + response->SetObject("uuid", std::make_shared<JSONString>(uuid_str)); + response->SetObject( + "triple", std::make_shared<JSONString>(matched_module_spec.GetArchitecture().GetTriple().getTriple())); + response->SetObject("file_path", std::make_shared<JSONString>(matched_module_spec.GetFileSpec().GetPath())); + response->SetObject("file_offset", std::make_shared<JSONNumber>(file_offset)); + response->SetObject("file_size", std::make_shared<JSONNumber>(file_size)); + } + + StreamString response; + response_array_sp->Write(response); + StreamGDBRemote escaped_response; + escaped_response.PutEscapedBytes(response.GetData(), response.GetSize()); + return SendPacketNoLock(escaped_response.GetString()); +} + void GDBRemoteCommunicationServerCommon::CreateProcessInfoResponse (const ProcessInstanceInfo &proc_info, StreamString &response) @@ -1284,3 +1329,23 @@ return FileSpec(module_path.c_str(), true); #endif } + +ModuleSpec +GDBRemoteCommunicationServerCommon::GetModuleInfo(const std::string &module_path, const std::string &triple) +{ + ArchSpec arch(triple.c_str()); + + const FileSpec req_module_path_spec(module_path.c_str(), true); + const FileSpec module_path_spec = FindModuleFile(req_module_path_spec.GetPath(), arch); + const ModuleSpec module_spec(module_path_spec, arch); + + ModuleSpecList module_specs; + if (!ObjectFile::GetModuleSpecifications(module_path_spec, 0, 0, module_specs)) + return ModuleSpec(); + + ModuleSpec matched_module_spec; + if (!module_specs.FindMatchingModuleSpec(module_spec, matched_module_spec)) + return ModuleSpec(); + + return matched_module_spec; +} Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.h @@ -26,6 +26,8 @@ #include "lldb/Core/StructuredData.h" #include "lldb/Target/Process.h" +#include "llvm/ADT/Optional.h" + namespace lldb_private { namespace process_gdb_remote { @@ -535,6 +537,9 @@ const ArchSpec& arch_spec, ModuleSpec &module_spec); + llvm::Optional<std::vector<ModuleSpec>> + GetModulesInfo(llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple); + bool ReadExtFeature (const lldb_private::ConstString object, const lldb_private::ConstString annex, @@ -641,7 +646,8 @@ m_supports_qSymbol:1, m_qSymbol_requests_done:1, m_supports_qModuleInfo:1, - m_supports_jThreadsInfo:1; + m_supports_jThreadsInfo:1, + m_supports_jModulesInfo:1; lldb::pid_t m_curr_pid; lldb::tid_t m_curr_tid; // Current gdb remote protocol thread index for all other operations Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationClient.cpp @@ -33,6 +33,7 @@ #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/UnixSignals.h" #include "lldb/Utility/LLDBAssert.h" +#include "lldb/Utility/JSON.h" #include "lldb/Target/Target.h" // Project includes @@ -104,6 +105,7 @@ m_qSymbol_requests_done(false), m_supports_qModuleInfo(true), m_supports_jThreadsInfo(true), + m_supports_jModulesInfo(true), m_curr_pid(LLDB_INVALID_PROCESS_ID), m_curr_tid(LLDB_INVALID_THREAD_ID), m_curr_tid_run(LLDB_INVALID_THREAD_ID), @@ -389,6 +391,7 @@ m_qSupported_response.clear(); m_supported_async_json_packets_is_valid = false; m_supported_async_json_packets_sp.reset(); + m_supports_jModulesInfo = true; } // These flags should be reset when we first connect to a GDB server @@ -3662,6 +3665,89 @@ return true; } +static llvm::Optional<ModuleSpec> +ParseModuleSpec(StructuredData::Dictionary *dict) +{ + ModuleSpec result; + if (!dict) + return llvm::None; + + std::string string; + uint64_t integer; + + if (!dict->GetValueForKeyAsString("uuid", string)) + return llvm::None; + result.GetUUID().SetFromCString(string.c_str(), string.size()); + + if (!dict->GetValueForKeyAsInteger("file_offset", integer)) + return llvm::None; + result.SetObjectOffset(integer); + + if (!dict->GetValueForKeyAsInteger("file_size", integer)) + return llvm::None; + result.SetObjectSize(integer); + + if (!dict->GetValueForKeyAsString("triple", string)) + return llvm::None; + result.GetArchitecture().SetTriple(string.c_str()); + + if (!dict->GetValueForKeyAsString("file_path", string)) + return llvm::None; + result.GetFileSpec() = FileSpec(string, false, result.GetArchitecture()); + + return result; +} + +llvm::Optional<std::vector<ModuleSpec>> +GDBRemoteCommunicationClient::GetModulesInfo(llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) +{ + if (!m_supports_jModulesInfo) + return llvm::None; + + JSONArray::SP module_array_sp = std::make_shared<JSONArray>(); + for (const FileSpec &module_file_spec: module_file_specs) + { + JSONObject::SP module_sp = std::make_shared<JSONObject>(); + module_array_sp->AppendObject(module_sp); + module_sp->SetObject("file", std::make_shared<JSONString>(module_file_spec.GetPath())); + module_sp->SetObject("triple", std::make_shared<JSONString>(triple.getTriple())); + } + StreamString unescaped_payload; + unescaped_payload.PutCString("jModulesInfo:"); + module_array_sp->Write(unescaped_payload); + StreamGDBRemote payload; + payload.PutEscapedBytes(unescaped_payload.GetData(), unescaped_payload.GetSize()); + + StringExtractorGDBRemote response; + if (SendPacketAndWaitForResponse(payload.GetString(), response, false) != PacketResult::Success || + response.IsErrorResponse()) + return llvm::None; + + if (response.IsUnsupportedResponse ()) + { + m_supports_jModulesInfo = false; + return llvm::None; + } + + StructuredData::ObjectSP response_object_sp = StructuredData::ParseJSON(response.GetStringRef()); + if (!response_object_sp) + return llvm::None; + + StructuredData::Array *response_array = response_object_sp->GetAsArray(); + if (! response_array) + return llvm::None; + + std::vector<ModuleSpec> result; + for (size_t i = 0; i < response_array->GetSize(); ++i) + { + if (llvm::Optional<ModuleSpec> module_spec = + ParseModuleSpec(response_array->GetItemAtIndex(i)->GetAsDictionary())) + result.push_back(*module_spec); + } + + return result; +} + // query the target remote for extended information using the qXfer packet // // example: object='features', annex='target.xml', out=<xml output> Index: source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp =================================================================== --- source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp +++ source/Plugins/DynamicLoader/POSIX-DYLD/DynamicLoaderPOSIXDYLD.cpp @@ -521,6 +521,12 @@ module_list.Append(module_sp); } } + + std::vector<FileSpec> module_names; + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) + module_names.push_back(I->file_spec); + m_process->PrefetchModuleSpecs(module_names, m_process->GetTarget().GetArchitecture().GetTriple()); + for (I = m_rendezvous.begin(), E = m_rendezvous.end(); I != E; ++I) { ModuleSP module_sp = LoadModuleAtAddress(I->file_spec, I->link_addr, I->base_addr, true); Index: packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py =================================================================== --- /dev/null +++ packages/Python/lldbsuite/test/tools/lldb-server/TestGdbRemoteModuleInfo.py @@ -0,0 +1,38 @@ +from __future__ import print_function + + + +import gdbremote_testcase +import lldbgdbserverutils +from lldbsuite.test.decorators import * +from lldbsuite.test.lldbtest import * +from lldbsuite.test import lldbutil + +class TestGdbRemoteModuleInfo(gdbremote_testcase.GdbRemoteTestCaseBase): + + mydir = TestBase.compute_mydir(__file__) + + def module_info(self): + procs = self.prep_debug_monitor_and_inferior() + self.test_sequence.add_log_lines([ + 'read packet: $jModulesInfo:[{"file":"%s","triple":"%s"}]]#00'%( + lldbutil.append_to_process_working_directory("a.out"), + self.dbg.GetSelectedPlatform().GetTriple()), + {"direction":"send", "regex":r'^\$\[{(.*)}\]\]#[0-9A-Fa-f]{2}', "capture":{1:"spec"}}, + ], True) + + context = self.expect_gdbremote_sequence() + spec = context.get("spec") + self.assertRegexpMatches(spec, '"file_path":".*"') + self.assertRegexpMatches(spec, '"file_offset":\d+') + self.assertRegexpMatches(spec, '"file_size":\d+') + self.assertRegexpMatches(spec, '"triple":"\w*-\w*-.*"') + self.assertRegexpMatches(spec, '"uuid":"[A-Fa-f0-9]+"') + + @llgs_test + def test_module_info(self): + self.init_llgs_test() + self.build() + self.set_inferior_startup_launch() + self.module_info() + Index: include/lldb/Target/Process.h =================================================================== --- include/lldb/Target/Process.h +++ include/lldb/Target/Process.h @@ -50,6 +50,8 @@ #include "lldb/Target/ThreadList.h" #include "lldb/Target/InstrumentationRuntime.h" +#include "llvm/ADT/ArrayRef.h" + namespace lldb_private { template <typename B, typename S> @@ -3196,6 +3198,11 @@ virtual bool GetModuleSpec(const FileSpec& module_file_spec, const ArchSpec& arch, ModuleSpec &module_spec); + virtual void + PrefetchModuleSpecs(llvm::ArrayRef<FileSpec> module_file_specs, const llvm::Triple &triple) + { + } + //------------------------------------------------------------------ /// Try to find the load address of a file. /// The load address is defined as the address of the first memory Index: docs/lldb-gdb-remote.txt =================================================================== --- docs/lldb-gdb-remote.txt +++ docs/lldb-gdb-remote.txt @@ -1054,6 +1054,28 @@ //---------------------------------------------------------------------- //---------------------------------------------------------------------- +// jModulesInfo:[{"file":"...",triple:"..."}, ...] +// +// BRIEF +// Get information for a list of modules by given module path and +// architecture. +// +// RESPONSE +// A JSON array of dictionaries containing the following keys: uuid, +// triple, file_path, file_offset, file_size. The meaning of the fields +// is the same as in the qModuleInfo packet. The server signals the +// failure to retrieve the module info for a file by ommiting the +// corresponding array entry from the response. The server may also +// include entries the client did not ask for, if it has reason to +// the modules will be interesting to the client. +// +// PRIORITY TO IMPLEMENT +// Optional. If not implemented, qModuleInfo packet will be used, which +// may be slower if the target contains a large number of modules and +// the communication link has a non-negligible latency. +//---------------------------------------------------------------------- + +//---------------------------------------------------------------------- // Stop reply packet extensions // // BRIEF
_______________________________________________ lldb-commits mailing list lldb-commits@lists.llvm.org http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits