[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