summaryrefslogtreecommitdiffstats
path: root/lldb/source
diff options
context:
space:
mode:
authorEnrico Granata <egranata@apple.com>2015-10-01 18:16:18 +0000
committerEnrico Granata <egranata@apple.com>2015-10-01 18:16:18 +0000
commit9b0af1b86f435fd490596af1b7812bd02565888a (patch)
tree5ad02c8a589de53388f900fd86db7fc849758c14 /lldb/source
parent12629324a4e97e9619848826c80314a88f9eae85 (diff)
downloadbcm5719-llvm-9b0af1b86f435fd490596af1b7812bd02565888a.tar.gz
bcm5719-llvm-9b0af1b86f435fd490596af1b7812bd02565888a.zip
Add a 'type lookup' command. This command is meant to look up type information by name in a language-specific way.
Currently, it only supports Objective-C - C++ types can be looked up through debug info via 'image lookup -t', whereas ObjC types via this command are looked up by runtime introspection This behavior is in line with type lookup's behavior in Xcode 7, but I am definitely open to feedback as to what makes the most sense here llvm-svn: 249047
Diffstat (limited to 'lldb/source')
-rw-r--r--lldb/source/Commands/CommandObjectType.cpp213
-rw-r--r--lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp88
-rw-r--r--lldb/source/Plugins/Language/ObjC/ObjCLanguage.h3
-rw-r--r--lldb/source/Target/Language.cpp28
4 files changed, 332 insertions, 0 deletions
diff --git a/lldb/source/Commands/CommandObjectType.cpp b/lldb/source/Commands/CommandObjectType.cpp
index 842c323b62e..f0f4a14d4fc 100644
--- a/lldb/source/Commands/CommandObjectType.cpp
+++ b/lldb/source/Commands/CommandObjectType.cpp
@@ -4558,6 +4558,218 @@ CommandObjectTypeFilterAdd::CommandOptions::g_option_table[] =
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
};
+//----------------------------------------------------------------------
+// "type lookup"
+//----------------------------------------------------------------------
+class CommandObjectTypeLookup : public CommandObjectRaw
+{
+protected:
+
+ class CommandOptions : public OptionGroup
+ {
+ public:
+
+ CommandOptions () :
+ OptionGroup(),
+ m_show_help(false),
+ m_language(eLanguageTypeUnknown)
+ {}
+
+ virtual
+ ~CommandOptions () {}
+
+ virtual uint32_t
+ GetNumDefinitions ()
+ {
+ return 3;
+ }
+
+ virtual const OptionDefinition*
+ GetDefinitions ()
+ {
+ return g_option_table;
+ }
+
+ virtual Error
+ SetOptionValue (CommandInterpreter &interpreter,
+ uint32_t option_idx,
+ const char *option_value)
+ {
+ Error error;
+
+ const int short_option = g_option_table[option_idx].short_option;
+
+ switch (short_option)
+ {
+ case 'h':
+ m_show_help = true;
+ break;
+
+ case 'l':
+ m_language = Language::GetLanguageTypeFromString(option_value);
+ break;
+
+ default:
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);
+ break;
+ }
+
+ return error;
+ }
+
+ virtual void
+ OptionParsingStarting (CommandInterpreter &interpreter)
+ {
+ m_show_help = false;
+ m_language = eLanguageTypeUnknown;
+ }
+
+ // Options table: Required for subclasses of Options.
+
+ static OptionDefinition g_option_table[];
+ bool m_show_help;
+ lldb::LanguageType m_language;
+ };
+
+ OptionGroupOptions m_option_group;
+ CommandOptions m_command_options;
+
+public:
+
+ CommandObjectTypeLookup (CommandInterpreter &interpreter) :
+ CommandObjectRaw (interpreter,
+ "type lookup",
+ "Lookup a type by name in the select target.",
+ "type lookup <typename>",
+ eCommandRequiresTarget),
+ m_option_group(interpreter),
+ m_command_options()
+ {
+ m_option_group.Append(&m_command_options);
+ m_option_group.Finalize();
+ }
+
+ virtual
+ ~CommandObjectTypeLookup ()
+ {
+ }
+
+ virtual
+ Options *
+ GetOptions ()
+ {
+ return &m_option_group;
+ }
+
+ virtual bool
+ DoExecute (const char *raw_command_line, CommandReturnObject &result)
+ {
+ if (!raw_command_line || !raw_command_line[0])
+ {
+ result.SetError("type lookup cannot be invoked without a type name as argument");
+ return false;
+ }
+
+ m_option_group.NotifyOptionParsingStarting();
+
+ const char * name_of_type = NULL;
+
+ if (raw_command_line[0] == '-')
+ {
+ // We have some options and these options MUST end with --.
+ const char *end_options = NULL;
+ const char *s = raw_command_line;
+ while (s && s[0])
+ {
+ end_options = ::strstr (s, "--");
+ if (end_options)
+ {
+ end_options += 2; // Get past the "--"
+ if (::isspace (end_options[0]))
+ {
+ name_of_type = end_options;
+ while (::isspace (*name_of_type))
+ ++name_of_type;
+ break;
+ }
+ }
+ s = end_options;
+ }
+
+ if (end_options)
+ {
+ Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));
+ if (!ParseOptions (args, result))
+ return false;
+
+ Error error (m_option_group.NotifyOptionParsingFinished());
+ if (error.Fail())
+ {
+ result.AppendError (error.AsCString());
+ result.SetStatus (eReturnStatusFailed);
+ return false;
+ }
+ }
+ }
+ if (nullptr == name_of_type)
+ name_of_type = raw_command_line;
+
+ TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());
+ const bool fill_all_in = true;
+ ExecutionContext exe_ctx(target_sp.get(), fill_all_in);
+ ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();
+
+ bool any_found = false;
+
+ std::vector<Language*> languages;
+
+ if (m_command_options.m_language == eLanguageTypeUnknown)
+ {
+ // FIXME: hardcoding languages is not good
+ languages.push_back(Language::FindPlugin(eLanguageTypeObjC));
+ languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));
+ }
+ else
+ {
+ languages.push_back(Language::FindPlugin(m_command_options.m_language));
+ }
+
+ for (Language* language : languages)
+ {
+ if (!language)
+ continue;
+
+ if (auto scavenger = language->GetTypeScavenger())
+ {
+ Language::TypeScavenger::ResultSet search_results;
+ if (scavenger->Find(best_scope, name_of_type, search_results) > 0)
+ {
+ for (const auto& search_result : search_results)
+ {
+ if (search_result && search_result->IsValid())
+ {
+ any_found = true;
+ search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help);
+ }
+ }
+ }
+ }
+ }
+
+ result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult);
+ return true;
+ }
+
+};
+
+OptionDefinition
+CommandObjectTypeLookup::CommandOptions::g_option_table[] =
+{
+ { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display available help for types"},
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Which language's types should the search scope be"},
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }
+};
+
template <typename FormatterType>
class CommandObjectFormatterInfo : public CommandObjectRaw
{
@@ -4778,6 +4990,7 @@ CommandObjectType::CommandObjectType (CommandInterpreter &interpreter) :
#ifndef LLDB_DISABLE_PYTHON
LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
#endif
+ LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter)));
}
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
index c7e024c66c7..6c1aee9be6d 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.cpp
@@ -656,3 +656,91 @@ ObjCLanguage::GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicVa
return result;
}
+
+std::unique_ptr<Language::TypeScavenger>
+ObjCLanguage::GetTypeScavenger ()
+{
+ class ObjCTypeScavenger : public Language::TypeScavenger
+ {
+ private:
+ class ObjCScavengerResult : public Language::TypeScavenger::Result
+ {
+ public:
+ ObjCScavengerResult (CompilerType type) :
+ Language::TypeScavenger::Result(),
+ m_compiler_type(type)
+ {
+ }
+
+ bool
+ IsValid () override
+ {
+ return m_compiler_type.IsValid();
+ }
+
+ bool
+ DumpToStream (Stream& stream,
+ bool print_help_if_available) override
+ {
+ if (IsValid())
+ {
+ m_compiler_type.DumpTypeDescription(&stream);
+ stream.EOL();
+ return true;
+ }
+ return false;
+ }
+
+ virtual ~ObjCScavengerResult() = default;
+ private:
+ CompilerType m_compiler_type;
+ };
+
+ protected:
+ ObjCTypeScavenger() = default;
+
+ virtual ~ObjCTypeScavenger() = default;
+
+ bool
+ Find_Impl (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results) override
+ {
+ bool result = false;
+
+ Process* process = exe_scope->CalculateProcess().get();
+ if (process)
+ {
+ const bool create_on_demand = false;
+ auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);
+ if (objc_runtime)
+ {
+ auto decl_vendor = objc_runtime->GetDeclVendor();
+ if (decl_vendor)
+ {
+ std::vector<clang::NamedDecl *> decls;
+ ConstString name(key);
+ decl_vendor->FindDecls(name, true, UINT32_MAX, decls);
+ for (auto decl : decls)
+ {
+ if (decl)
+ {
+ if (CompilerType candidate = ClangASTContext::GetTypeForDecl(decl))
+ {
+ result = true;
+ std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(candidate));
+ results.insert(std::move(result));
+ }
+ }
+ }
+ }
+ }
+ }
+ return result;
+ }
+
+ friend class ObjCLanguage;
+ };
+
+ return std::unique_ptr<TypeScavenger>(new ObjCTypeScavenger());
+}
diff --git a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
index 0e3c45f0ff1..09ee55d274f 100644
--- a/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
+++ b/lldb/source/Plugins/Language/ObjC/ObjCLanguage.h
@@ -146,6 +146,9 @@ public:
std::vector<ConstString>
GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;
+ std::unique_ptr<TypeScavenger>
+ GetTypeScavenger () override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
diff --git a/lldb/source/Target/Language.cpp b/lldb/source/Target/Language.cpp
index 02b36519b13..f7c2cf6249f 100644
--- a/lldb/source/Target/Language.cpp
+++ b/lldb/source/Target/Language.cpp
@@ -287,6 +287,34 @@ Language::LanguageIsPascal (LanguageType language)
}
}
+std::unique_ptr<Language::TypeScavenger>
+Language::GetTypeScavenger ()
+{
+ return nullptr;
+}
+
+size_t
+Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results,
+ bool append)
+{
+ if (!exe_scope || !exe_scope->CalculateTarget().get())
+ return false;
+
+ if (!key || !key[0])
+ return false;
+
+ if (!append)
+ results.clear();
+
+ size_t old_size = results.size();
+
+ if (this->Find_Impl(exe_scope, key, results))
+ return results.size() - old_size;
+ return 0;
+}
+
//----------------------------------------------------------------------
// Constructor
//----------------------------------------------------------------------
OpenPOWER on IntegriCloud