<rdar://problem/12687087>

Emit an error when using "target modules add PATH" where PATH points to a debug info only (dSYM) file.

Also added a "--uuid" option for "target modules add --uuid UUID" to locate and load a module by UUID if the host supports it.

llvm-svn: 168949
This commit is contained in:
Greg Clayton 2012-11-29 22:16:27 +00:00
parent 929a94f026
commit 50a24bd358
2 changed files with 136 additions and 32 deletions

View File

@ -2442,14 +2442,23 @@ public:
CommandObjectParsed (interpreter,
"target modules add",
"Add a new module to the current target's modules.",
"target modules add [<module>]")
"target modules add [<module>]"),
m_option_group (interpreter)
{
m_option_group.Append (&m_uuid_option_group, LLDB_OPT_SET_ALL, LLDB_OPT_SET_1);
m_option_group.Finalize();
}
virtual
~CommandObjectTargetModulesAdd ()
{
}
virtual Options *
GetOptions ()
{
return &m_option_group;
}
int
HandleArgumentCompletion (Args &input,
@ -2476,6 +2485,11 @@ public:
}
protected:
OptionGroupOptions m_option_group;
OptionGroupUUID m_uuid_option_group;
virtual bool
DoExecute (Args& args,
CommandReturnObject &result)
@ -2492,9 +2506,66 @@ protected:
const size_t argc = args.GetArgumentCount();
if (argc == 0)
{
result.AppendError ("one or more executable image paths must be specified");
result.SetStatus (eReturnStatusFailed);
return false;
if (m_uuid_option_group.GetOptionValue ().OptionWasSet())
{
// We are given a UUID only, go locate the file
ModuleSpec module_spec;
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue ().GetCurrentValue();
if (Symbols::DownloadObjectAndSymbolFile (module_spec))
{
ModuleSP module_sp (target->GetSharedModule (module_spec));
if (module_sp)
{
result.SetStatus (eReturnStatusSuccessFinishResult);
return true;
}
else
{
StreamString strm;
module_spec.GetUUID().Dump (&strm);
if (module_spec.GetFileSpec())
{
if (module_spec.GetSymbolFileSpec())
{
result.AppendErrorWithFormat ("Unable to create the executable or symbol file with UUID %s with path %s/%s and symbol file %s/%s",
strm.GetString().c_str(),
module_spec.GetFileSpec().GetDirectory().GetCString(),
module_spec.GetFileSpec().GetFilename().GetCString(),
module_spec.GetSymbolFileSpec().GetDirectory().GetCString(),
module_spec.GetSymbolFileSpec().GetFilename().GetCString());
}
else
{
result.AppendErrorWithFormat ("Unable to create the executable or symbol file with UUID %s with path %s/%s",
strm.GetString().c_str(),
module_spec.GetFileSpec().GetDirectory().GetCString(),
module_spec.GetFileSpec().GetFilename().GetCString());
}
}
else
{
result.AppendErrorWithFormat ("Unable to create the executable or symbol file with UUID %s",
strm.GetString().c_str());
}
result.SetStatus (eReturnStatusFailed);
return false;
}
}
else
{
StreamString strm;
module_spec.GetUUID().Dump (&strm);
result.AppendErrorWithFormat ("Unable to locate the executable or symbol file with UUID %s", strm.GetString().c_str());
result.SetStatus (eReturnStatusFailed);
return false;
}
}
else
{
result.AppendError ("one or more executable image paths must be specified");
result.SetStatus (eReturnStatusFailed);
return false;
}
}
else
{
@ -2507,10 +2578,18 @@ protected:
if (file_spec.Exists())
{
ModuleSpec module_spec (file_spec);
ModuleSP module_sp (target->GetSharedModule (module_spec));
if (m_uuid_option_group.GetOptionValue ().OptionWasSet())
module_spec.GetUUID() = m_uuid_option_group.GetOptionValue ().GetCurrentValue();
Error error;
ModuleSP module_sp (target->GetSharedModule (module_spec, &error));
if (!module_sp)
{
result.AppendError ("one or more executable image paths must be specified");
const char *error_cstr = error.AsCString();
if (error_cstr)
result.AppendError (error_cstr);
else
result.AppendErrorWithFormat ("unsupported module: %s", path);
result.SetStatus (eReturnStatusFailed);
return false;
}

View File

@ -1460,38 +1460,63 @@ Target::GetSharedModule (const ModuleSpec &module_spec, Error *error_ptr)
// module in the list already, and if there was, let's remove it.
if (module_sp)
{
// GetSharedModule is not guaranteed to find the old shared module, for instance
// in the common case where you pass in the UUID, it is only going to find the one
// module matching the UUID. In fact, it has no good way to know what the "old module"
// relevant to this target is, since there might be many copies of a module with this file spec
// in various running debug sessions, but only one of them will belong to this target.
// So let's remove the UUID from the module list, and look in the target's module list.
// Only do this if there is SOMETHING else in the module spec...
if (!old_module_sp)
ObjectFile *objfile = module_sp->GetObjectFile();
if (objfile)
{
if (module_spec.GetUUID().IsValid() && !module_spec.GetFileSpec().GetFilename().IsEmpty() && !module_spec.GetFileSpec().GetDirectory().IsEmpty())
switch (objfile->GetType())
{
ModuleSpec module_spec_copy(module_spec.GetFileSpec());
module_spec_copy.GetUUID().Clear();
ModuleList found_modules;
size_t num_found = m_images.FindModules (module_spec_copy, found_modules);
if (num_found == 1)
case ObjectFile::eTypeCoreFile: /// A core file that has a checkpoint of a program's execution state
case ObjectFile::eTypeExecutable: /// A normal executable
case ObjectFile::eTypeDynamicLinker: /// The platform's dynamic linker executable
case ObjectFile::eTypeObjectFile: /// An intermediate object file
case ObjectFile::eTypeSharedLibrary: /// A shared library that can be used during execution
break;
case ObjectFile::eTypeDebugInfo: /// An object file that contains only debug information
if (error_ptr)
error_ptr->SetErrorString("debug info files aren't valid target modules, please specify an executable");
return ModuleSP();
case ObjectFile::eTypeStubLibrary: /// A library that can be linked against but not used for execution
if (error_ptr)
error_ptr->SetErrorString("stub libraries aren't valid target modules, please specify an executable");
return ModuleSP();
default:
if (error_ptr)
error_ptr->SetErrorString("unsupported file type, please specify an executable");
return ModuleSP();
}
// GetSharedModule is not guaranteed to find the old shared module, for instance
// in the common case where you pass in the UUID, it is only going to find the one
// module matching the UUID. In fact, it has no good way to know what the "old module"
// relevant to this target is, since there might be many copies of a module with this file spec
// in various running debug sessions, but only one of them will belong to this target.
// So let's remove the UUID from the module list, and look in the target's module list.
// Only do this if there is SOMETHING else in the module spec...
if (!old_module_sp)
{
if (module_spec.GetUUID().IsValid() && !module_spec.GetFileSpec().GetFilename().IsEmpty() && !module_spec.GetFileSpec().GetDirectory().IsEmpty())
{
old_module_sp = found_modules.GetModuleAtIndex(0);
ModuleSpec module_spec_copy(module_spec.GetFileSpec());
module_spec_copy.GetUUID().Clear();
ModuleList found_modules;
size_t num_found = m_images.FindModules (module_spec_copy, found_modules);
if (num_found == 1)
{
old_module_sp = found_modules.GetModuleAtIndex(0);
}
}
}
if (old_module_sp && m_images.GetIndexForModule (old_module_sp.get()) != LLDB_INVALID_INDEX32)
{
m_images.ReplaceModule(old_module_sp, module_sp);
Module *old_module_ptr = old_module_sp.get();
old_module_sp.reset();
ModuleList::RemoveSharedModuleIfOrphaned (old_module_ptr);
}
else
m_images.Append(module_sp);
}
if (old_module_sp && m_images.GetIndexForModule (old_module_sp.get()) != LLDB_INVALID_INDEX32)
{
m_images.ReplaceModule(old_module_sp, module_sp);
Module *old_module_ptr = old_module_sp.get();
old_module_sp.reset();
ModuleList::RemoveSharedModuleIfOrphaned (old_module_ptr);
}
else
m_images.Append(module_sp);
}
}
if (error_ptr)