From 2f1fbaebe25a4637cf75ec9ab1877c64584ede24 Mon Sep 17 00:00:00 2001 From: Pavel Labath Date: Thu, 8 Sep 2016 10:07:04 +0000 Subject: gdb-remote: Add jModulesInfo packet Summary: This adds the jModulesInfo packet, which is the equivalent of qModulesInfo, but it enables us to query multiple modules at once. This makes a significant speed improvement in case the application has many (over a hundred) modules, and the communication link has a non-negligible latency. This functionality is accessed by ProcessGdbRemote::PrefetchModuleSpecs(), which does the caching. GetModuleSpecs() is modified to first consult the cache before asking the remote stub. PrefetchModuleSpecs is currently only called from POSIX-DYLD dynamic loader plugin, after it reads the list of modules from the inferior memory, but other uses are possible. This decreases the attach time to an android application by about 40%. Reviewers: clayborg Subscribers: tberghammer, lldb-commits, danalbert Differential Revision: https://reviews.llvm.org/D24236 llvm-svn: 280919 --- .../GDBRemoteCommunicationServerCommon.cpp | 99 +++++++++++++++++++--- 1 file changed, 85 insertions(+), 14 deletions(-) (limited to 'lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp') diff --git a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp index f7ef2fe2176..0d7ca3c53e4 100644 --- a/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp +++ b/lldb/source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServerCommon.cpp @@ -38,6 +38,7 @@ #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Utility/JSON.h" #include "llvm/ADT/Triple.h" // Project includes @@ -101,6 +102,9 @@ GDBRemoteCommunicationServerCommon::GDBRemoteCommunicationServerCommon( RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qModuleInfo, &GDBRemoteCommunicationServerCommon::Handle_qModuleInfo); + RegisterMemberFunctionHandler( + StringExtractorGDBRemote::eServerPacketType_jModulesInfo, + &GDBRemoteCommunicationServerCommon::Handle_jModulesInfo); RegisterMemberFunctionHandler( StringExtractorGDBRemote::eServerPacketType_qPlatform_chmod, &GDBRemoteCommunicationServerCommon::Handle_qPlatform_chmod); @@ -1078,22 +1082,11 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( 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(""); @@ -1119,7 +1112,7 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( 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); @@ -1131,6 +1124,63 @@ GDBRemoteCommunicationServerCommon::Handle_qModuleInfo( 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(); + 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(); + response_array_sp->AppendObject(response); + response->SetObject("uuid", std::make_shared(uuid_str)); + response->SetObject( + "triple", + std::make_shared( + matched_module_spec.GetArchitecture().GetTriple().getTriple())); + response->SetObject("file_path", + std::make_shared( + matched_module_spec.GetFileSpec().GetPath())); + response->SetObject("file_offset", + std::make_shared(file_offset)); + response->SetObject("file_size", std::make_shared(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) { response.Printf( @@ -1230,3 +1280,24 @@ FileSpec GDBRemoteCommunicationServerCommon::FindModuleFile( 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; +} -- cgit v1.2.3