[Lldb-commits] [lldb] r249047 - Add a 'type lookup' command. This command is meant to look up type information by name in a language-specific way.
Enrico Granata via lldb-commits
lldb-commits at lists.llvm.org
Thu Oct 1 11:16:19 PDT 2015
Author: enrico
Date: Thu Oct 1 13:16:18 2015
New Revision: 249047
URL: http://llvm.org/viewvc/llvm-project?rev=249047&view=rev
Log:
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
Modified:
lldb/trunk/include/lldb/Target/Language.h
lldb/trunk/source/Commands/CommandObjectType.cpp
lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp
lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h
lldb/trunk/source/Target/Language.cpp
Modified: lldb/trunk/include/lldb/Target/Language.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/include/lldb/Target/Language.h?rev=249047&r1=249046&r2=249047&view=diff
==============================================================================
--- lldb/trunk/include/lldb/Target/Language.h (original)
+++ lldb/trunk/include/lldb/Target/Language.h Thu Oct 1 13:16:18 2015
@@ -13,6 +13,8 @@
// C Includes
// C++ Includes
#include <functional>
+#include <memory>
+#include <set>
#include <vector>
// Other libraries and framework includes
@@ -29,6 +31,42 @@ class Language :
public PluginInterface
{
public:
+
+ class TypeScavenger
+ {
+ public:
+ class Result
+ {
+ public:
+ virtual bool
+ IsValid () = 0;
+
+ virtual bool
+ DumpToStream (Stream& stream,
+ bool print_help_if_available) = 0;
+
+ virtual ~Result() = default;
+ };
+
+ typedef std::set<std::unique_ptr<Result>> ResultSet;
+
+ virtual ~TypeScavenger () = default;
+
+ size_t
+ Find (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results,
+ bool append = true);
+
+ protected:
+ TypeScavenger () = default;
+
+ virtual bool
+ Find_Impl (ExecutionContextScope *exe_scope,
+ const char *key,
+ ResultSet &results) = 0;
+ };
+
~Language() override;
static Language*
@@ -65,6 +103,9 @@ public:
virtual lldb_private::formatters::StringPrinter::EscapingHelper
GetStringPrinterEscapingHelper (lldb_private::formatters::StringPrinter::GetPrintableElementType);
+ virtual std::unique_ptr<TypeScavenger>
+ GetTypeScavenger ();
+
// These are accessors for general information about the Languages lldb knows about:
static lldb::LanguageType
@@ -91,7 +132,6 @@ public:
static bool
LanguageIsPascal (lldb::LanguageType language);
-
protected:
//------------------------------------------------------------------
Modified: lldb/trunk/source/Commands/CommandObjectType.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Commands/CommandObjectType.cpp?rev=249047&r1=249046&r2=249047&view=diff
==============================================================================
--- lldb/trunk/source/Commands/CommandObjectType.cpp (original)
+++ lldb/trunk/source/Commands/CommandObjectType.cpp Thu Oct 1 13:16:18 2015
@@ -4558,6 +4558,218 @@ CommandObjectTypeFilterAdd::CommandOptio
{ 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 (Co
#ifndef LLDB_DISABLE_PYTHON
LoadSubCommand ("synthetic", CommandObjectSP (new CommandObjectTypeSynth (interpreter)));
#endif
+ LoadSubCommand ("lookup", CommandObjectSP (new CommandObjectTypeLookup (interpreter)));
}
Modified: lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp?rev=249047&r1=249046&r2=249047&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.cpp Thu Oct 1 13:16:18 2015
@@ -656,3 +656,91 @@ ObjCLanguage::GetPossibleFormattersMatch
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());
+}
Modified: lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h?rev=249047&r1=249046&r2=249047&view=diff
==============================================================================
--- lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h (original)
+++ lldb/trunk/source/Plugins/Language/ObjC/ObjCLanguage.h Thu Oct 1 13:16:18 2015
@@ -146,6 +146,9 @@ public:
std::vector<ConstString>
GetPossibleFormattersMatches (ValueObject& valobj, lldb::DynamicValueType use_dynamic) override;
+ std::unique_ptr<TypeScavenger>
+ GetTypeScavenger () override;
+
//------------------------------------------------------------------
// Static Functions
//------------------------------------------------------------------
Modified: lldb/trunk/source/Target/Language.cpp
URL: http://llvm.org/viewvc/llvm-project/lldb/trunk/source/Target/Language.cpp?rev=249047&r1=249046&r2=249047&view=diff
==============================================================================
--- lldb/trunk/source/Target/Language.cpp (original)
+++ lldb/trunk/source/Target/Language.cpp Thu Oct 1 13:16:18 2015
@@ -287,6 +287,34 @@ Language::LanguageIsPascal (LanguageType
}
}
+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
//----------------------------------------------------------------------
More information about the lldb-commits
mailing list