Index: lldb/trunk/include/lldb/Expression/ExpressionVariable.h =================================================================== --- lldb/trunk/include/lldb/Expression/ExpressionVariable.h +++ lldb/trunk/include/lldb/Expression/ExpressionVariable.h @@ -232,6 +232,9 @@ virtual void RemovePersistentVariable(lldb::ExpressionVariableSP variable) = 0; + virtual llvm::Optional + GetCompilerTypeFromPersistentDecl(ConstString type_name) = 0; + virtual lldb::addr_t LookupSymbol(ConstString name); void RegisterExecutionUnit(lldb::IRExecutionUnitSP &execution_unit_sp); Index: lldb/trunk/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py =================================================================== --- lldb/trunk/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py +++ lldb/trunk/packages/Python/lldbsuite/test/expression_command/persistent_types/TestPersistentTypes.py @@ -56,6 +56,16 @@ "d = 'l'"]) # persistent types are OK to use for memory read self.expect( + "memory read foo -t $foobar -x c", + substrs=[ + '($foobar) 0x', + ' = ', + "a = 'H'", + "b = 'e'", + "c = 'l'", + "d = 'l'"]) # persistent types are OK to use for memory read + + self.expect( "memory read foo -t foobar", substrs=[ '($foobar) 0x', Index: lldb/trunk/source/Commands/CMakeLists.txt =================================================================== --- lldb/trunk/source/Commands/CMakeLists.txt +++ lldb/trunk/source/Commands/CMakeLists.txt @@ -41,7 +41,6 @@ lldbSymbol lldbTarget lldbUtility - lldbPluginExpressionParserClang LINK_COMPONENTS Support Index: lldb/trunk/source/Commands/CommandObjectMemory.cpp =================================================================== --- lldb/trunk/source/Commands/CommandObjectMemory.cpp +++ lldb/trunk/source/Commands/CommandObjectMemory.cpp @@ -6,16 +6,14 @@ // //===----------------------------------------------------------------------===// -#include "clang/AST/Decl.h" - #include "CommandObjectMemory.h" -#include "Plugins/ExpressionParser/Clang/ClangPersistentVariables.h" #include "lldb/Core/Debugger.h" #include "lldb/Core/DumpDataExtractor.h" #include "lldb/Core/Module.h" #include "lldb/Core/Section.h" #include "lldb/Core/ValueObjectMemory.h" #include "lldb/DataFormatters/ValueObjectPrinter.h" +#include "lldb/Expression/ExpressionVariable.h" #include "lldb/Host/OptionParser.h" #include "lldb/Interpreter/CommandInterpreter.h" #include "lldb/Interpreter/CommandReturnObject.h" @@ -23,15 +21,17 @@ #include "lldb/Interpreter/OptionGroupFormat.h" #include "lldb/Interpreter/OptionGroupOutputFile.h" #include "lldb/Interpreter/OptionGroupValueObjectDisplay.h" +#include "lldb/Interpreter/OptionValueLanguage.h" #include "lldb/Interpreter/OptionValueString.h" #include "lldb/Interpreter/Options.h" -#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Symbol/SymbolFile.h" #include "lldb/Symbol/TypeList.h" +#include "lldb/Target/Language.h" #include "lldb/Target/MemoryHistory.h" #include "lldb/Target/MemoryRegionInfo.h" #include "lldb/Target/Process.h" #include "lldb/Target/StackFrame.h" +#include "lldb/Target/Target.h" #include "lldb/Target/Thread.h" #include "lldb/Utility/Args.h" #include "lldb/Utility/DataBufferHeap.h" @@ -51,7 +51,9 @@ {LLDB_OPT_SET_1, false, "num-per-line", 'l', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNumberPerLine, "The number of items per line to display." }, {LLDB_OPT_SET_2, false, "binary", 'b', OptionParser::eNoArgument, nullptr, {}, 0, eArgTypeNone, "If true, memory will be saved as binary. If false, the memory is saved save as an ASCII dump that " "uses the format, size, count and number per line settings." }, - {LLDB_OPT_SET_3, true , "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeNone, "The name of a type to view memory as." }, + {LLDB_OPT_SET_3 | + LLDB_OPT_SET_4, true , "type", 't', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeName, "The name of a type to view memory as." }, + {LLDB_OPT_SET_4, false, "language", 'x', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeLanguage, "The language of the type to view memory as."}, {LLDB_OPT_SET_3, false, "offset", 'E', OptionParser::eRequiredArgument, nullptr, {}, 0, eArgTypeCount, "How many elements of the specified type to skip before starting to display data." }, {LLDB_OPT_SET_1 | LLDB_OPT_SET_2 | @@ -63,7 +65,7 @@ public: OptionGroupReadMemory() : m_num_per_line(1, 1), m_output_as_binary(false), m_view_as_type(), - m_offset(0, 0) {} + m_offset(0, 0), m_language_for_type(eLanguageTypeUnknown) {} ~OptionGroupReadMemory() override = default; @@ -97,6 +99,10 @@ m_force = true; break; + case 'x': + error = m_language_for_type.SetValueFromString(option_value); + break; + case 'E': error = m_offset.SetValueFromString(option_value); break; @@ -115,6 +121,7 @@ m_view_as_type.Clear(); m_force = false; m_offset.Clear(); + m_language_for_type.Clear(); } Status FinalizeSettings(Target *target, OptionGroupFormat &format_options) { @@ -277,7 +284,8 @@ bool AnyOptionWasSet() const { return m_num_per_line.OptionWasSet() || m_output_as_binary || - m_view_as_type.OptionWasSet() || m_offset.OptionWasSet(); + m_view_as_type.OptionWasSet() || m_offset.OptionWasSet() || + m_language_for_type.OptionWasSet(); } OptionValueUInt64 m_num_per_line; @@ -285,6 +293,7 @@ OptionValueString m_view_as_type; bool m_force; OptionValueUInt64 m_offset; + OptionValueLanguage m_language_for_type; }; // Read memory from the inferior process @@ -372,7 +381,7 @@ return false; } - CompilerType clang_ast_type; + CompilerType compiler_type; Status error; const char *view_as_type_cstr = @@ -472,26 +481,43 @@ exact_match, 1, searched_symbol_files, type_list); - if (type_list.GetSize() == 0 && lookup_type_name.GetCString() && - *lookup_type_name.GetCString() == '$') { - if (ClangPersistentVariables *persistent_vars = - llvm::dyn_cast_or_null( - target->GetPersistentExpressionStateForLanguage( - lldb::eLanguageTypeC))) { - clang::TypeDecl *tdecl = llvm::dyn_cast_or_null( - persistent_vars->GetPersistentDecl( - ConstString(lookup_type_name))); - - if (tdecl) { - clang_ast_type.SetCompilerType( - ClangASTContext::GetASTContext(&tdecl->getASTContext()), - reinterpret_cast( - const_cast(tdecl->getTypeForDecl()))); + if (type_list.GetSize() == 0 && lookup_type_name.GetCString()) { + LanguageType language_for_type = + m_memory_options.m_language_for_type.GetCurrentValue(); + std::set languages_to_check; + if (language_for_type != eLanguageTypeUnknown) { + languages_to_check.insert(language_for_type); + } else { + languages_to_check = Language::GetSupportedLanguages(); + } + + std::set user_defined_types; + for (auto lang : languages_to_check) { + if (auto *persistent_vars = + target->GetPersistentExpressionStateForLanguage(lang)) { + if (llvm::Optional type = + persistent_vars->GetCompilerTypeFromPersistentDecl( + lookup_type_name)) { + user_defined_types.emplace(*type); + } } } + + if (user_defined_types.size() > 1) { + result.AppendErrorWithFormat( + "Mutiple types found matching raw type '%s', please disambiguate " + "by specifying the language with -x", + lookup_type_name.GetCString()); + result.SetStatus(eReturnStatusFailed); + return false; + } + + if (user_defined_types.size() == 1) { + compiler_type = *user_defined_types.begin(); + } } - if (!clang_ast_type.IsValid()) { + if (!compiler_type.IsValid()) { if (type_list.GetSize() == 0) { result.AppendErrorWithFormat("unable to find any types that match " "the raw type '%s' for full type '%s'\n", @@ -501,14 +527,14 @@ return false; } else { TypeSP type_sp(type_list.GetTypeAtIndex(0)); - clang_ast_type = type_sp->GetFullCompilerType(); + compiler_type = type_sp->GetFullCompilerType(); } } while (pointer_count > 0) { - CompilerType pointer_type = clang_ast_type.GetPointerType(); + CompilerType pointer_type = compiler_type.GetPointerType(); if (pointer_type.IsValid()) - clang_ast_type = pointer_type; + compiler_type = pointer_type; else { result.AppendError("unable make a pointer type\n"); result.SetStatus(eReturnStatusFailed); @@ -517,7 +543,7 @@ --pointer_count; } - llvm::Optional size = clang_ast_type.GetByteSize(nullptr); + llvm::Optional size = compiler_type.GetByteSize(nullptr); if (!size) { result.AppendErrorWithFormat( "unable to get the byte size of the type '%s'\n", @@ -547,7 +573,7 @@ // options have been set addr = m_next_addr; total_byte_size = m_prev_byte_size; - clang_ast_type = m_prev_clang_ast_type; + compiler_type = m_prev_compiler_type; if (!m_format_options.AnyOptionWasSet() && !m_memory_options.AnyOptionWasSet() && !m_outfile_options.AnyOptionWasSet() && @@ -634,13 +660,13 @@ DataBufferSP data_sp; size_t bytes_read = 0; - if (clang_ast_type.GetOpaqueQualType()) { + if (compiler_type.GetOpaqueQualType()) { // Make sure we don't display our type as ASCII bytes like the default // memory read if (!m_format_options.GetFormatValue().OptionWasSet()) m_format_options.GetFormatValue().SetCurrentValue(eFormatDefault); - llvm::Optional size = clang_ast_type.GetByteSize(nullptr); + llvm::Optional size = compiler_type.GetByteSize(nullptr); if (!size) { result.AppendError("can't get size of type"); return false; @@ -750,7 +776,7 @@ m_prev_memory_options = m_memory_options; m_prev_outfile_options = m_outfile_options; m_prev_varobj_options = m_varobj_options; - m_prev_clang_ast_type = clang_ast_type; + m_prev_compiler_type = compiler_type; StreamFile outfile_stream; Stream *output_stream = nullptr; @@ -800,14 +826,14 @@ } ExecutionContextScope *exe_scope = m_exe_ctx.GetBestExecutionContextScope(); - if (clang_ast_type.GetOpaqueQualType()) { + if (compiler_type.GetOpaqueQualType()) { for (uint32_t i = 0; i < item_count; ++i) { addr_t item_addr = addr + (i * item_byte_size); Address address(item_addr); StreamString name_strm; name_strm.Printf("0x%" PRIx64, item_addr); ValueObjectSP valobj_sp(ValueObjectMemory::Create( - exe_scope, name_strm.GetString(), address, clang_ast_type)); + exe_scope, name_strm.GetString(), address, compiler_type)); if (valobj_sp) { Format format = m_format_options.GetFormat(); if (format != eFormatDefault) @@ -877,7 +903,7 @@ OptionGroupReadMemory m_prev_memory_options; OptionGroupOutputFile m_prev_outfile_options; OptionGroupValueObjectDisplay m_prev_varobj_options; - CompilerType m_prev_clang_ast_type; + CompilerType m_prev_compiler_type; }; static constexpr OptionDefinition g_memory_find_option_table[] = { Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.h @@ -50,6 +50,9 @@ return "$"; } + llvm::Optional + GetCompilerTypeFromPersistentDecl(ConstString type_name) override; + void RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl); clang::NamedDecl *GetPersistentDecl(ConstString name); Index: lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp =================================================================== --- lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp +++ lldb/trunk/source/Plugins/ExpressionParser/Clang/ClangPersistentVariables.cpp @@ -9,6 +9,7 @@ #include "ClangPersistentVariables.h" #include "lldb/Core/Value.h" +#include "lldb/Symbol/ClangASTContext.h" #include "lldb/Target/Target.h" #include "lldb/Utility/DataExtractor.h" #include "lldb/Utility/Log.h" @@ -52,6 +53,21 @@ m_next_persistent_variable_id--; } +llvm::Optional +ClangPersistentVariables::GetCompilerTypeFromPersistentDecl( + ConstString type_name) { + CompilerType compiler_type; + if (clang::TypeDecl *tdecl = llvm::dyn_cast_or_null( + GetPersistentDecl(type_name))) { + compiler_type.SetCompilerType( + ClangASTContext::GetASTContext(&tdecl->getASTContext()), + reinterpret_cast( + const_cast(tdecl->getTypeForDecl()))); + return compiler_type; + } + return llvm::None; +} + void ClangPersistentVariables::RegisterPersistentDecl(ConstString name, clang::NamedDecl *decl) { m_persistent_decls.insert(