<div dir="ltr">Hi Enrico,<div><br></div><div>Could you add some tests for this? python API tests and appropriate methods added to SBTarget would be ideal.</div></div><br><div class="gmail_quote"><div dir="ltr">On Thu, Oct 1, 2015 at 11:17 AM Enrico Granata via lldb-commits <<a href="mailto:lldb-commits@lists.llvm.org">lldb-commits@lists.llvm.org</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Author: enrico<br>
Date: Thu Oct 1 13:16:18 2015<br>
New Revision: 249047<br>
<br>
URL: <a href="http://llvm.org/viewvc/llvm-project?rev=249047&view=rev" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project?rev=249047&view=rev</a><br>
Log:<br>
Add a 'type lookup' command. This command is meant to look up type information by name in a language-specific way.<br>
<br>
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<br>
<br>
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<br>
<br>
<br>
Modified:<br>
lldb/trunk/include/lldb/Target/Language.h<br>
lldb/trunk/source/Commands/CommandObjectType.cpp<br>
lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp<br>
lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h<br>
lldb/trunk/source/Target/Language.cpp<br>
<br>
Modified: lldb/trunk/include/lldb/Target/Language.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Language.h?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Language.h?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/include/lldb/Target/Language.h (original)<br>
+++ lldb/trunk/include/lldb/Target/Language.h Thu Oct 1 13:16:18 2015<br>
@@ -13,6 +13,8 @@<br>
// C Includes<br>
// C++ Includes<br>
#include <functional><br>
+#include <memory><br>
+#include <set><br>
#include <vector><br>
<br>
// Other libraries and framework includes<br>
@@ -29,6 +31,42 @@ class Language :<br>
public PluginInterface<br>
{<br>
public:<br>
+<br>
+ class TypeScavenger<br>
+ {<br>
+ public:<br>
+ class Result<br>
+ {<br>
+ public:<br>
+ virtual bool<br>
+ IsValid () = 0;<br>
+<br>
+ virtual bool<br>
+ DumpToStream (Stream& stream,<br>
+ bool print_help_if_available) = 0;<br>
+<br>
+ virtual ~Result() = default;<br>
+ };<br>
+<br>
+ typedef std::set<std::unique_ptr<Result>> ResultSet;<br>
+<br>
+ virtual ~TypeScavenger () = default;<br>
+<br>
+ size_t<br>
+ Find (ExecutionContextScope *exe_scope,<br>
+ const char *key,<br>
+ ResultSet &results,<br>
+ bool append = true);<br>
+<br>
+ protected:<br>
+ TypeScavenger () = default;<br>
+<br>
+ virtual bool<br>
+ Find_Impl (ExecutionContextScope *exe_scope,<br>
+ const char *key,<br>
+ ResultSet &results) = 0;<br>
+ };<br>
+<br>
~Language() override;<br>
<br>
static Language*<br>
@@ -65,6 +103,9 @@ public:<br>
virtual lldb_private::formatters::StringPrinter::EscapingHelper<br>
GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType);<br>
<br>
+ virtual std::unique_ptr<TypeScavenger><br>
+ GetTypeScavenger ();<br>
+<br>
// These are accessors for general information about the Languages lldb knows about:<br>
<br>
static lldb::LanguageType<br>
@@ -91,7 +132,6 @@ public:<br>
<br>
static bool<br>
LanguageIsPascal (lldb::LanguageType language);<br>
-<br>
<br>
protected:<br>
//------------------------------------------------------------------<br>
<br>
Modified: lldb/trunk/source/Commands/CommandObjectType.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Commands/CommandObjectType.cpp (original)<br>
+++ lldb/trunk/source/Commands/CommandObjectType.cpp Thu Oct 1 13:16:18 2015<br>
@@ -4558,6 +4558,218 @@ CommandObjectTypeFilterAdd::CommandOptio<br>
{ 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }<br>
};<br>
<br>
+//----------------------------------------------------------------------<br>
+// "type lookup"<br>
+//----------------------------------------------------------------------<br>
+class CommandObjectTypeLookup : public CommandObjectRaw<br>
+{<br>
+protected:<br>
+<br>
+ class CommandOptions : public OptionGroup<br>
+ {<br>
+ public:<br>
+<br>
+ CommandOptions () :<br>
+ OptionGroup(),<br>
+ m_show_help(false),<br>
+ m_language(eLanguageTypeUnknown)<br>
+ {}<br>
+<br>
+ virtual<br>
+ ~CommandOptions () {}<br>
+<br>
+ virtual uint32_t<br>
+ GetNumDefinitions ()<br>
+ {<br>
+ return 3;<br>
+ }<br>
+<br>
+ virtual const OptionDefinition*<br>
+ GetDefinitions ()<br>
+ {<br>
+ return g_option_table;<br>
+ }<br>
+<br>
+ virtual Error<br>
+ SetOptionValue (CommandInterpreter &interpreter,<br>
+ uint32_t option_idx,<br>
+ const char *option_value)<br>
+ {<br>
+ Error error;<br>
+<br>
+ const int short_option = g_option_table[option_idx].short_option;<br>
+<br>
+ switch (short_option)<br>
+ {<br>
+ case 'h':<br>
+ m_show_help = true;<br>
+ break;<br>
+<br>
+ case 'l':<br>
+ m_language = Language::GetLanguageTypeFromString(option_value);<br>
+ break;<br>
+<br>
+ default:<br>
+ error.SetErrorStringWithFormat("invalid short option character '%c'", short_option);<br>
+ break;<br>
+ }<br>
+<br>
+ return error;<br>
+ }<br>
+<br>
+ virtual void<br>
+ OptionParsingStarting (CommandInterpreter &interpreter)<br>
+ {<br>
+ m_show_help = false;<br>
+ m_language = eLanguageTypeUnknown;<br>
+ }<br>
+<br>
+ // Options table: Required for subclasses of Options.<br>
+<br>
+ static OptionDefinition g_option_table[];<br>
+ bool m_show_help;<br>
+ lldb::LanguageType m_language;<br>
+ };<br>
+<br>
+ OptionGroupOptions m_option_group;<br>
+ CommandOptions m_command_options;<br>
+<br>
+public:<br>
+<br>
+ CommandObjectTypeLookup (CommandInterpreter &interpreter) :<br>
+ CommandObjectRaw (interpreter,<br>
+ "type lookup",<br>
+ "Lookup a type by name in the select target.",<br>
+ "type lookup <typename>",<br>
+ eCommandRequiresTarget),<br>
+ m_option_group(interpreter),<br>
+ m_command_options()<br>
+ {<br>
+ m_option_group.Append(&m_command_options);<br>
+ m_option_group.Finalize();<br>
+ }<br>
+<br>
+ virtual<br>
+ ~CommandObjectTypeLookup ()<br>
+ {<br>
+ }<br>
+<br>
+ virtual<br>
+ Options *<br>
+ GetOptions ()<br>
+ {<br>
+ return &m_option_group;<br>
+ }<br>
+<br>
+ virtual bool<br>
+ DoExecute (const char *raw_command_line, CommandReturnObject &result)<br>
+ {<br>
+ if (!raw_command_line || !raw_command_line[0])<br>
+ {<br>
+ result.SetError("type lookup cannot be invoked without a type name as argument");<br>
+ return false;<br>
+ }<br>
+<br>
+ m_option_group.NotifyOptionParsingStarting();<br>
+<br>
+ const char * name_of_type = NULL;<br>
+<br>
+ if (raw_command_line[0] == '-')<br>
+ {<br>
+ // We have some options and these options MUST end with --.<br>
+ const char *end_options = NULL;<br>
+ const char *s = raw_command_line;<br>
+ while (s && s[0])<br>
+ {<br>
+ end_options = ::strstr (s, "--");<br>
+ if (end_options)<br>
+ {<br>
+ end_options += 2; // Get past the "--"<br>
+ if (::isspace (end_options[0]))<br>
+ {<br>
+ name_of_type = end_options;<br>
+ while (::isspace (*name_of_type))<br>
+ ++name_of_type;<br>
+ break;<br>
+ }<br>
+ }<br>
+ s = end_options;<br>
+ }<br>
+<br>
+ if (end_options)<br>
+ {<br>
+ Args args (llvm::StringRef(raw_command_line, end_options - raw_command_line));<br>
+ if (!ParseOptions (args, result))<br>
+ return false;<br>
+<br>
+ Error error (m_option_group.NotifyOptionParsingFinished());<br>
+ if (error.Fail())<br>
+ {<br>
+ result.AppendError (error.AsCString());<br>
+ result.SetStatus (eReturnStatusFailed);<br>
+ return false;<br>
+ }<br>
+ }<br>
+ }<br>
+ if (nullptr == name_of_type)<br>
+ name_of_type = raw_command_line;<br>
+<br>
+ TargetSP target_sp(GetCommandInterpreter().GetDebugger().GetSelectedTarget());<br>
+ const bool fill_all_in = true;<br>
+ ExecutionContext exe_ctx(target_sp.get(), fill_all_in);<br>
+ ExecutionContextScope *best_scope = exe_ctx.GetBestExecutionContextScope();<br>
+<br>
+ bool any_found = false;<br>
+<br>
+ std::vector<Language*> languages;<br>
+<br>
+ if (m_command_options.m_language == eLanguageTypeUnknown)<br>
+ {<br>
+ // FIXME: hardcoding languages is not good<br>
+ languages.push_back(Language::FindPlugin(eLanguageTypeObjC));<br>
+ languages.push_back(Language::FindPlugin(eLanguageTypeC_plus_plus));<br>
+ }<br>
+ else<br>
+ {<br>
+ languages.push_back(Language::FindPlugin(m_command_options.m_language));<br>
+ }<br>
+<br>
+ for (Language* language : languages)<br>
+ {<br>
+ if (!language)<br>
+ continue;<br>
+<br>
+ if (auto scavenger = language->GetTypeScavenger())<br>
+ {<br>
+ Language::TypeScavenger::ResultSet search_results;<br>
+ if (scavenger->Find(best_scope, name_of_type, search_results) > 0)<br>
+ {<br>
+ for (const auto& search_result : search_results)<br>
+ {<br>
+ if (search_result && search_result->IsValid())<br>
+ {<br>
+ any_found = true;<br>
+ search_result->DumpToStream(result.GetOutputStream(), this->m_command_options.m_show_help);<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+<br>
+ result.SetStatus (any_found ? lldb::eReturnStatusSuccessFinishResult : lldb::eReturnStatusSuccessFinishNoResult);<br>
+ return true;<br>
+ }<br>
+<br>
+};<br>
+<br>
+OptionDefinition<br>
+CommandObjectTypeLookup::CommandOptions::g_option_table[] =<br>
+{<br>
+ { LLDB_OPT_SET_ALL, false, "show-help", 'h', OptionParser::eNoArgument, NULL, NULL, 0, eArgTypeNone, "Display available help for types"},<br>
+ { LLDB_OPT_SET_ALL, false, "language", 'l', OptionParser::eRequiredArgument, NULL, NULL, 0, eArgTypeLanguage, "Which language's types should the search scope be"},<br>
+ { 0, false, NULL, 0, 0, NULL, NULL, 0, eArgTypeNone, NULL }<br>
+};<br>
+<br>
template <typename FormatterType><br>
class CommandObjectFormatterInfo : public CommandObjectRaw<br>
{<br>
@@ -4778,6 +4990,7 @@ CommandObjectType::CommandObjectType (Co<br>
#ifndef LLDB_DISABLE_PYTHON<br>
LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));<br>
#endif<br>
+ LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter)));<br>
}<br>
<br>
<br>
<br>
Modified: lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp (original)<br>
+++ lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp Thu Oct 1 13:16:18 2015<br>
@@ -656,3 +656,91 @@ ObjCLanguage::GetPossibleFormattersMatch<br>
<br>
return result;<br>
}<br>
+<br>
+std::unique_ptr<Language::TypeScavenger><br>
+ObjCLanguage::GetTypeScavenger ()<br>
+{<br>
+ class ObjCTypeScavenger : public Language::TypeScavenger<br>
+ {<br>
+ private:<br>
+ class ObjCScavengerResult : public Language::TypeScavenger::Result<br>
+ {<br>
+ public:<br>
+ ObjCScavengerResult (CompilerType type) :<br>
+ Language::TypeScavenger::Result(),<br>
+ m_compiler_type(type)<br>
+ {<br>
+ }<br>
+<br>
+ bool<br>
+ IsValid () override<br>
+ {<br>
+ return m_compiler_type.IsValid();<br>
+ }<br>
+<br>
+ bool<br>
+ DumpToStream (Stream& stream,<br>
+ bool print_help_if_available) override<br>
+ {<br>
+ if (IsValid())<br>
+ {<br>
+ m_compiler_type.DumpTypeDescription(&stream);<br>
+ stream.EOL();<br>
+ return true;<br>
+ }<br>
+ return false;<br>
+ }<br>
+<br>
+ virtual ~ObjCScavengerResult() = default;<br>
+ private:<br>
+ CompilerType m_compiler_type;<br>
+ };<br>
+<br>
+ protected:<br>
+ ObjCTypeScavenger() = default;<br>
+<br>
+ virtual ~ObjCTypeScavenger() = default;<br>
+<br>
+ bool<br>
+ Find_Impl (ExecutionContextScope *exe_scope,<br>
+ const char *key,<br>
+ ResultSet &results) override<br>
+ {<br>
+ bool result = false;<br>
+<br>
+ Process* process = exe_scope->CalculateProcess().get();<br>
+ if (process)<br>
+ {<br>
+ const bool create_on_demand = false;<br>
+ auto objc_runtime = process->GetObjCLanguageRuntime(create_on_demand);<br>
+ if (objc_runtime)<br>
+ {<br>
+ auto decl_vendor = objc_runtime->GetDeclVendor();<br>
+ if (decl_vendor)<br>
+ {<br>
+ std::vector<clang::NamedDecl *> decls;<br>
+ ConstString name(key);<br>
+ decl_vendor->FindDecls(name, true, UINT32_MAX, decls);<br>
+ for (auto decl : decls)<br>
+ {<br>
+ if (decl)<br>
+ {<br>
+ if (CompilerType candidate = ClangASTContext::GetTypeForDecl(decl))<br>
+ {<br>
+ result = true;<br>
+ std::unique_ptr<Language::TypeScavenger::Result> result(new ObjCScavengerResult(candidate));<br>
+ results.insert(std::move(result));<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+ }<br>
+ return result;<br>
+ }<br>
+<br>
+ friend class ObjCLanguage;<br>
+ };<br>
+<br>
+ return std::unique_ptr<TypeScavenger>(new ObjCTypeScavenger());<br>
+}<br>
<br>
Modified: lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h (original)<br>
+++ lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h Thu Oct 1 13:16:18 2015<br>
@@ -146,6 +146,9 @@ public:<br>
std::vector<ConstString><br>
GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;<br>
<br>
+ std::unique_ptr<TypeScavenger><br>
+ GetTypeScavenger () override;<br>
+<br>
//------------------------------------------------------------------<br>
// Static Functions<br>
//------------------------------------------------------------------<br>
<br>
Modified: lldb/trunk/source/Target/Language.cpp<br>
URL: <a href="http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Language.cpp?rev=249047&r1=249046&r2=249047&view=diff" rel="noreferrer" target="_blank">http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Language.cpp?rev=249047&r1=249046&r2=249047&view=diff</a><br>
==============================================================================<br>
--- lldb/trunk/source/Target/Language.cpp (original)<br>
+++ lldb/trunk/source/Target/Language.cpp Thu Oct 1 13:16:18 2015<br>
@@ -287,6 +287,34 @@ Language::LanguageIsPascal (LanguageType<br>
}<br>
}<br>
<br>
+std::unique_ptr<Language::TypeScavenger><br>
+Language::GetTypeScavenger ()<br>
+{<br>
+ return nullptr;<br>
+}<br>
+<br>
+size_t<br>
+Language::TypeScavenger::Find (ExecutionContextScope *exe_scope,<br>
+ const char *key,<br>
+ ResultSet &results,<br>
+ bool append)<br>
+{<br>
+ if (!exe_scope || !exe_scope->CalculateTarget().get())<br>
+ return false;<br>
+<br>
+ if (!key || !key[0])<br>
+ return false;<br>
+<br>
+ if (!append)<br>
+ results.clear();<br>
+<br>
+ size_t old_size = results.size();<br>
+<br>
+ if (this->Find_Impl(exe_scope, key, results))<br>
+ return results.size() - old_size;<br>
+ return 0;<br>
+}<br>
+<br>
//----------------------------------------------------------------------<br>
// Constructor<br>
//----------------------------------------------------------------------<br>
<br>
<br>
_______________________________________________<br>
lldb-commits mailing list<br>
<a href="mailto:lldb-commits@lists.llvm.org" target="_blank">lldb-commits@lists.llvm.org</a><br>
<a href="http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits" rel="noreferrer" target="_blank">http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits</a><br>
</blockquote></div>