Fixed SBDebugger.CreateTarget("filename") and also make sure remote targets don't pickup bogus locally cached files.

<rdar://problem/16217254>
<rdar://problem/16078651>

llvm-svn: 202890
This commit is contained in:
Greg Clayton 2014-03-04 21:20:23 +00:00
parent 2f0e4e78b2
commit 34f1159bbd
2 changed files with 132 additions and 92 deletions

View File

@ -131,16 +131,16 @@ namespace lldb {
Module::Module (const ModuleSpec &module_spec) :
m_mutex (Mutex::eMutexTypeRecursive),
m_mod_time (module_spec.GetFileSpec().GetModificationTime()),
m_arch (module_spec.GetArchitecture()),
m_mod_time (),
m_arch (),
m_uuid (),
m_file (module_spec.GetFileSpec()),
m_platform_file(module_spec.GetPlatformFileSpec()),
m_file (),
m_platform_file(),
m_remote_install_file(),
m_symfile_spec (module_spec.GetSymbolFileSpec()),
m_object_name (module_spec.GetObjectName()),
m_object_offset (module_spec.GetObjectOffset()),
m_object_mod_time (module_spec.GetObjectModificationTime()),
m_symfile_spec (),
m_object_name (),
m_object_offset (),
m_object_mod_time (),
m_objfile_sp (),
m_symfile_ap (),
m_ast (),
@ -163,11 +163,40 @@ Module::Module (const ModuleSpec &module_spec) :
if (log)
log->Printf ("%p Module::Module((%s) '%s%s%s%s')",
this,
m_arch.GetArchitectureName(),
m_file.GetPath().c_str(),
m_object_name.IsEmpty() ? "" : "(",
m_object_name.IsEmpty() ? "" : m_object_name.AsCString(""),
m_object_name.IsEmpty() ? "" : ")");
module_spec.GetArchitecture().GetArchitectureName(),
module_spec.GetFileSpec().GetPath().c_str(),
module_spec.GetObjectName().IsEmpty() ? "" : "(",
module_spec.GetObjectName().IsEmpty() ? "" : module_spec.GetObjectName().AsCString(""),
module_spec.GetObjectName().IsEmpty() ? "" : ")");
// First extract all module specifications from the file using the local
// file path. If there are no specifications, then don't fill anything in
ModuleSpecList modules_specs;
if (ObjectFile::GetModuleSpecifications(module_spec.GetFileSpec(), 0, 0, modules_specs) == 0)
return;
// Now make sure that one of the module specifications matches what we just
// extract. We might have a module specification that specifies a file "/usr/lib/dyld"
// with UUID XXX, but we might have a local version of "/usr/lib/dyld" that has
// UUID YYY and we don't want those to match. If they don't match, just don't
// fill any ivars in so we don't accidentally grab the wrong file later since
// they don't match...
ModuleSpec matching_module_spec;
if (modules_specs.FindMatchingModuleSpec(module_spec, matching_module_spec) == 0)
return;
m_mod_time = module_spec.GetFileSpec().GetModificationTime();
if (module_spec.GetArchitecture().IsValid())
m_arch = module_spec.GetArchitecture();
else
m_arch = matching_module_spec.GetArchitecture();
m_mod_time = module_spec.GetFileSpec().GetModificationTime();
m_file = module_spec.GetFileSpec();
m_platform_file = module_spec.GetPlatformFileSpec();
m_symfile_spec = module_spec.GetSymbolFileSpec();
m_object_name = module_spec.GetObjectName();
m_object_offset = module_spec.GetObjectOffset();
m_object_mod_time = module_spec.GetObjectModificationTime();
}
Module::Module(const FileSpec& file_spec,

View File

@ -303,102 +303,113 @@ PlatformDarwin::GetSharedModuleWithLocalCache (const lldb_private::ModuleSpec &m
module_spec.GetPlatformFileSpec().GetFilename().AsCString(),
module_spec.GetSymbolFileSpec().GetDirectory().AsCString(),
module_spec.GetSymbolFileSpec().GetFilename().AsCString());
std::string cache_path(GetLocalCacheDirectory());
std::string module_path (module_spec.GetFileSpec().GetPath());
cache_path.append(module_path);
FileSpec module_cache_spec(cache_path.c_str(),false);
// if rsync is supported, always bring in the file - rsync will be very efficient
// when files are the same on the local and remote end of the connection
if (this->GetSupportsRSync())
Error err;
err = ModuleList::GetSharedModule(module_spec, module_sp, module_search_paths_ptr, old_module_sp_ptr, did_create_ptr);
if (module_sp)
return err;
if (!IsHost())
{
Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
if (err.Fail())
return err;
if (module_cache_spec.Exists())
std::string cache_path(GetLocalCacheDirectory());
// Only search for a locally cached file if we have a valid cache path
if (!cache_path.empty())
{
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
std::string module_path (module_spec.GetFileSpec().GetPath());
cache_path.append(module_path);
FileSpec module_cache_spec(cache_path.c_str(),false);
// if rsync is supported, always bring in the file - rsync will be very efficient
// when files are the same on the local and remote end of the connection
if (this->GetSupportsRSync())
{
err = BringInRemoteFile (this, module_spec, module_cache_spec);
if (err.Fail())
return err;
if (module_cache_spec.Exists())
{
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s was rsynced and is now there",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
module_sp.reset(new Module(local_spec));
module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
return Error();
}
}
// try to find the module in the cache
if (module_cache_spec.Exists())
{
// get the local and remote MD5 and compare
if (m_remote_platform_sp)
{
// when going over the *slow* GDB remote transfer mechanism we first check
// the hashes of the files - and only do the actual transfer if they differ
uint64_t high_local,high_remote,low_local,low_remote;
Host::CalculateMD5 (module_cache_spec, low_local, high_local);
m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), low_remote, high_remote);
if (low_local != low_remote || high_local != high_remote)
{
// bring in the remote file
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s needs to be replaced from remote copy",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
if (err.Fail())
return err;
}
}
ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
module_sp.reset(new Module(local_spec));
module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s was found in the cache",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
return Error();
}
// bring in the remote module file
if (log)
log->Printf("[%s] module %s/%s was rsynced and is now there",
log->Printf("[%s] module %s/%s needs to come in remotely",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
module_sp.reset(new Module(local_spec));
module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
return Error();
}
}
if (module_spec.GetFileSpec().Exists() && !module_sp)
{
module_sp.reset(new Module(module_spec));
return Error();
}
// try to find the module in the cache
if (module_cache_spec.Exists())
{
// get the local and remote MD5 and compare
if (m_remote_platform_sp)
{
// when going over the *slow* GDB remote transfer mechanism we first check
// the hashes of the files - and only do the actual transfer if they differ
uint64_t high_local,high_remote,low_local,low_remote;
Host::CalculateMD5 (module_cache_spec, low_local, high_local);
m_remote_platform_sp->CalculateMD5(module_spec.GetFileSpec(), low_remote, high_remote);
if (low_local != low_remote || high_local != high_remote)
Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
if (err.Fail())
return err;
if (module_cache_spec.Exists())
{
// bring in the remote file
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s needs to be replaced from remote copy",
log->Printf("[%s] module %s/%s is now cached and fine",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
if (err.Fail())
return err;
ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
module_sp.reset(new Module(local_spec));
module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
return Error();
}
else
return Error("unable to obtain valid module file");
}
ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
module_sp.reset(new Module(local_spec));
module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s was found in the cache",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
return Error();
}
// bring in the remote module file
if (log)
log->Printf("[%s] module %s/%s needs to come in remotely",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
Error err = BringInRemoteFile (this, module_spec, module_cache_spec);
if (err.Fail())
return err;
if (module_cache_spec.Exists())
{
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PLATFORM));
if (log)
log->Printf("[%s] module %s/%s is now cached and fine",
(IsHost() ? "host" : "remote"),
module_spec.GetFileSpec().GetDirectory().AsCString(),
module_spec.GetFileSpec().GetFilename().AsCString());
ModuleSpec local_spec(module_cache_spec, module_spec.GetArchitecture());
module_sp.reset(new Module(local_spec));
module_sp->SetPlatformFileSpec(module_spec.GetFileSpec());
return Error();
else
return Error("no cache path");
}
else
return Error("unable to obtain valid module file");
return Error ("unable to resolve module");
}
Error