Add support to get the shared cache information from the new

debugserver jGetSharedCacheInfo packet instead of reading 
the dyld internal data structures directly.  This code is 
(currently) only used for ios native lldb's - I should really
move this ObjectFileMachO::GetProcessSharedCacheUUID method
somewhere else, it makes less and less sense being in the
file reader.

<rdar://problem/25251243> 

llvm-svn: 276369
This commit is contained in:
Jason Molenda 2016-07-22 00:17:55 +00:00
parent 0e2cec075c
commit 37397353cc
7 changed files with 110 additions and 0 deletions

View File

@ -1965,6 +1965,19 @@ public:
return StructuredData::ObjectSP();
}
//------------------------------------------------------------------
// Get information about the library shared cache, if that exists
//
// On macOS 10.12, tvOS 10, iOS 10, watchOS 3 and newer, debugserver can return
// information about the library shared cache (a set of standard libraries that are
// loaded at the same location for all processes on a system) in use.
//------------------------------------------------------------------
virtual lldb_private::StructuredData::ObjectSP
GetSharedCacheInfo ()
{
return StructuredData::ObjectSP();
}
//------------------------------------------------------------------
/// Print a user-visible warning about a module being built with optimization
///

View File

@ -480,6 +480,13 @@ DynamicLoaderMacOS::CanLoadImage ()
}
}
}
else
{
// If we were unable to find _dyld_global_lock_held in any modules, or it is not loaded into
// memory yet, we may be at process startup (sitting at _dyld_start) - so we should not allow
// dlopen calls.
error.SetErrorToGenericError();
}
return error;
}

View File

@ -5449,6 +5449,33 @@ UUID
ObjectFileMachO::GetProcessSharedCacheUUID (Process *process)
{
UUID uuid;
// First see if we can get the shared cache details from debugserver
if (process)
{
StructuredData::ObjectSP info = process->GetSharedCacheInfo();
StructuredData::Dictionary *info_dict = nullptr;
if (info.get() && info->GetAsDictionary())
{
info_dict = info->GetAsDictionary();
}
// {"shared_cache_base_address":140735683125248,"shared_cache_uuid":"DDB8D70C-C9A2-3561-B2C8-BE48A4F33F96","no_shared_cache":false,"shared_cache_private_cache":false}
if (info_dict
&& info_dict->HasKey("shared_cache_uuid")
&& info_dict->HasKey("no_shared_cache")
&& info_dict->HasKey("shared_cache_base_address"))
{
bool process_using_shared_cache = info_dict->GetValueForKey("no_shared_cache")->GetBooleanValue() == false;
std::string uuid_str = info_dict->GetValueForKey("shared_cache_uuid")->GetStringValue();
if (process_using_shared_cache && !uuid_str.empty() && uuid.SetFromCString (uuid_str.c_str()) == 0)
return uuid;
}
}
// Fall back to trying to read the shared cache info out of dyld's internal data structures
if (process)
{
addr_t all_image_infos = process->GetImageInfoAddress();

View File

@ -88,6 +88,7 @@ GDBRemoteCommunicationClient::GDBRemoteCommunicationClient()
m_supports_augmented_libraries_svr4_read(eLazyBoolCalculate),
m_supports_jThreadExtendedInfo(eLazyBoolCalculate),
m_supports_jLoadedDynamicLibrariesInfos(eLazyBoolCalculate),
m_supports_jGetSharedCacheInfo (eLazyBoolCalculate),
m_supports_qProcessInfoPID(true),
m_supports_qfProcessInfo(true),
m_supports_qUserName(true),
@ -676,6 +677,24 @@ GDBRemoteCommunicationClient::GetLoadedDynamicLibrariesInfosSupported ()
return m_supports_jLoadedDynamicLibrariesInfos;
}
bool
GDBRemoteCommunicationClient::GetSharedCacheInfoSupported ()
{
if (m_supports_jGetSharedCacheInfo == eLazyBoolCalculate)
{
StringExtractorGDBRemote response;
m_supports_jGetSharedCacheInfo = eLazyBoolNo;
if (SendPacketAndWaitForResponse("jGetSharedCacheInfo:", response, false) == PacketResult::Success)
{
if (response.IsOKResponse())
{
m_supports_jGetSharedCacheInfo = eLazyBoolYes;
}
}
}
return m_supports_jGetSharedCacheInfo;
}
bool
GDBRemoteCommunicationClient::GetxPacketSupported ()
{

View File

@ -559,6 +559,9 @@ public:
bool
GetLoadedDynamicLibrariesInfosSupported();
bool
GetSharedCacheInfoSupported();
bool
GetModuleInfo (const FileSpec& module_file_spec,
const ArchSpec& arch_spec,
@ -605,6 +608,7 @@ protected:
LazyBool m_supports_augmented_libraries_svr4_read;
LazyBool m_supports_jThreadExtendedInfo;
LazyBool m_supports_jLoadedDynamicLibrariesInfos;
LazyBool m_supports_jGetSharedCacheInfo;
bool
m_supports_qProcessInfoPID:1,

View File

@ -4270,6 +4270,43 @@ ProcessGDBRemote::GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectS
StructuredData::ObjectSP
ProcessGDBRemote::GetSharedCacheInfo ()
{
StructuredData::ObjectSP object_sp;
StructuredData::ObjectSP args_dict(new StructuredData::Dictionary());
if (m_gdb_comm.GetSharedCacheInfoSupported())
{
StreamString packet;
packet << "jGetSharedCacheInfo:";
args_dict->Dump (packet, false);
// FIXME the final character of a JSON dictionary, '}', is the escape
// character in gdb-remote binary mode. lldb currently doesn't escape
// these characters in its packet output -- so we add the quoted version
// of the } character here manually in case we talk to a debugserver which
// un-escapes the characters at packet read time.
packet << (char) (0x7d ^ 0x20);
StringExtractorGDBRemote response;
response.SetResponseValidatorToJSON();
if (m_gdb_comm.SendPacketAndWaitForResponse(packet.GetData(), packet.GetSize(), response, false) == GDBRemoteCommunication::PacketResult::Success)
{
StringExtractorGDBRemote::ResponseType response_type = response.GetResponseType();
if (response_type == StringExtractorGDBRemote::eResponse)
{
if (!response.Empty())
{
object_sp = StructuredData::ParseJSON (response.GetStringRef());
}
}
}
}
return object_sp;
}
// Establish the largest memory read/write payloads we should use.
// If the remote stub has a max packet size, stay under that size.
//

View File

@ -270,6 +270,9 @@ public:
StructuredData::ObjectSP
GetLoadedDynamicLibrariesInfos_sender (StructuredData::ObjectSP args);
StructuredData::ObjectSP
GetSharedCacheInfo () override;
protected:
friend class ThreadGDBRemote;
friend class GDBRemoteCommunicationClient;