[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.

Zachary Turner via lldb-commits lldb-commits at lists.llvm.org
Thu Oct 1 12:49:01 PDT 2015


Hi Enrico,

Could you add some tests for this?  python API tests and appropriate
methods added to SBTarget would be ideal.

On Thu, Oct 1, 2015 at 11:17 AM Enrico Granata via lldb-commits <
lldb-commits at lists.llvm.org> wrote:

> 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
>  //----------------------------------------------------------------------
>
>
> _______________________________________________
> lldb-commits mailing list
> lldb-commits at lists.llvm.org
> http://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.llvm.org/pipermail/lldb-commits/attachments/20151001/b1ee51cd/attachment-0001.html>


More information about the lldb-commits mailing list