Index: lldb/trunk/include/lldb/Symbol/JavaASTContext.h =================================================================== --- lldb/trunk/include/lldb/Symbol/JavaASTContext.h +++ lldb/trunk/include/lldb/Symbol/JavaASTContext.h @@ -335,8 +335,8 @@ CreateObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size); CompilerType - CreateArrayType(const CompilerType &element_type, const DWARFExpression &length_expression, - const lldb::addr_t data_offset); + CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type, + const DWARFExpression &length_expression, const lldb::addr_t data_offset); CompilerType CreateReferenceType(const CompilerType &pointee_type); @@ -360,6 +360,12 @@ static ConstString GetLinkageName(const CompilerType &type); + static uint32_t + CalculateArraySize(const CompilerType &type, ValueObject &in_value); + + static uint64_t + CalculateArrayElementOffset(const CompilerType &type, size_t index); + //------------------------------------------------------------------ // llvm casting support //------------------------------------------------------------------ Index: lldb/trunk/source/Plugins/Language/Java/JavaFormatterFunctions.h =================================================================== --- lldb/trunk/source/Plugins/Language/Java/JavaFormatterFunctions.h +++ lldb/trunk/source/Plugins/Language/Java/JavaFormatterFunctions.h @@ -24,6 +24,12 @@ bool JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); +bool +JavaArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options); + +SyntheticChildrenFrontEnd* +JavaArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp); + } // namespace formatters } // namespace lldb_private Index: lldb/trunk/source/Plugins/Language/Java/JavaFormatterFunctions.cpp =================================================================== --- lldb/trunk/source/Plugins/Language/Java/JavaFormatterFunctions.cpp +++ lldb/trunk/source/Plugins/Language/Java/JavaFormatterFunctions.cpp @@ -14,11 +14,100 @@ #include "JavaFormatterFunctions.h" #include "lldb/DataFormatters/FormattersHelpers.h" #include "lldb/DataFormatters/StringPrinter.h" +#include "lldb/Symbol/JavaASTContext.h" using namespace lldb; using namespace lldb_private; using namespace lldb_private::formatters; +namespace +{ + +class JavaArraySyntheticFrontEnd : public SyntheticChildrenFrontEnd +{ +public: + JavaArraySyntheticFrontEnd(lldb::ValueObjectSP valobj_sp) : + SyntheticChildrenFrontEnd(*valobj_sp) + { + if (valobj_sp) + Update(); + } + + size_t + CalculateNumChildren() override + { + ValueObjectSP valobj = GetDereferencedValueObject(); + if (!valobj) + return 0; + + CompilerType type = valobj->GetCompilerType(); + uint32_t size = JavaASTContext::CalculateArraySize(type, *valobj); + if (size == UINT32_MAX) + return 0; + return size; + } + + lldb::ValueObjectSP + GetChildAtIndex(size_t idx) override + { + ValueObjectSP valobj = GetDereferencedValueObject(); + if (!valobj) + return nullptr; + + ProcessSP process_sp = valobj->GetProcessSP(); + if (!process_sp) + return nullptr; + + CompilerType type = valobj->GetCompilerType(); + CompilerType element_type = type.GetArrayElementType(); + lldb::addr_t address = valobj->GetAddressOf() + JavaASTContext::CalculateArrayElementOffset(type, idx); + + Error error; + size_t byte_size = element_type.GetByteSize(nullptr); + DataBufferSP buffer_sp(new DataBufferHeap(byte_size, 0)); + size_t bytes_read = process_sp->ReadMemory(address, buffer_sp->GetBytes(), byte_size, error); + if (error.Fail() || byte_size != bytes_read) + return nullptr; + + StreamString name; + name.Printf("[%" PRIu64 "]", (uint64_t)idx); + DataExtractor data(buffer_sp, process_sp->GetByteOrder(), process_sp->GetAddressByteSize()); + return CreateValueObjectFromData(name.GetData(), data, valobj->GetExecutionContextRef(), + element_type); + } + + bool + Update() override + { + return false; + } + + bool + MightHaveChildren() override + { + return true; + } + + size_t + GetIndexOfChildWithName(const ConstString &name) override + { + return ExtractIndexFromString(name.GetCString()); + } + +private: + ValueObjectSP + GetDereferencedValueObject() + { + if (!m_backend.IsPointerOrReferenceType()) + m_backend.GetSP(); + + Error error; + return m_backend.Dereference(error); + } +}; + +} // end of anonymous namespace + bool lldb_private::formatters::JavaStringSummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &opts) { @@ -69,3 +158,29 @@ stream.Printf("Summary Unavailable"); return true; } + +bool +lldb_private::formatters::JavaArraySummaryProvider(ValueObject &valobj, Stream &stream, const TypeSummaryOptions &options) +{ + if (valobj.IsPointerOrReferenceType()) + { + Error error; + ValueObjectSP deref = valobj.Dereference(error); + if (error.Fail()) + return false; + return JavaArraySummaryProvider(*deref, stream, options); + } + + CompilerType type = valobj.GetCompilerType(); + uint32_t size = JavaASTContext::CalculateArraySize(type, valobj); + if (size == UINT32_MAX) + return false; + stream.Printf("[%u]{...}", size); + return true; +} + +SyntheticChildrenFrontEnd* +lldb_private::formatters::JavaArraySyntheticFrontEndCreator (CXXSyntheticChildren*, lldb::ValueObjectSP valobj_sp) +{ + return valobj_sp ? new JavaArraySyntheticFrontEnd(valobj_sp) : nullptr; +} Index: lldb/trunk/source/Plugins/Language/Java/JavaLanguage.cpp =================================================================== --- lldb/trunk/source/Plugins/Language/Java/JavaLanguage.cpp +++ lldb/trunk/source/Plugins/Language/Java/JavaLanguage.cpp @@ -88,11 +88,22 @@ DataVisualization::Categories::GetCategory(GetPluginName(), g_category); if (g_category) { + const char* array_regexp = "^.*\\[\\]&?$"; + lldb::TypeSummaryImplSP string_summary_sp(new CXXFunctionSummaryFormat( TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaStringSummaryProvider, "java.lang.String summary provider")); - g_category->GetTypeSummariesContainer()->Add(ConstString("java::lang::String"), string_summary_sp); + + lldb::TypeSummaryImplSP array_summary_sp(new CXXFunctionSummaryFormat( + TypeSummaryImpl::Flags().SetDontShowChildren(true), lldb_private::formatters::JavaArraySummaryProvider, + "Java array summary provider")); + g_category->GetRegexTypeSummariesContainer()->Add(RegularExpressionSP(new RegularExpression(array_regexp)), + array_summary_sp); + + AddCXXSynthetic(g_category, lldb_private::formatters::JavaArraySyntheticFrontEndCreator, + "Java array synthetic children", ConstString(array_regexp), + SyntheticChildren::Flags().SetCascades(true), true); } }); return g_category; Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp @@ -147,7 +147,7 @@ CompilerType element_compiler_type = element_type->GetForwardCompilerType(); CompilerType array_compiler_type = - m_ast.CreateArrayType(element_compiler_type, length_expression, data_offset); + m_ast.CreateArrayType(linkage_name, element_compiler_type, length_expression, data_offset); Declaration decl; TypeSP type_sp(new Type(die.GetID(), dwarf, array_compiler_type.GetTypeName(), -1, nullptr, Index: lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp =================================================================== --- lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp +++ lldb/trunk/source/Plugins/SymbolFile/DWARF/DWARFCompileUnit.cpp @@ -755,20 +755,21 @@ switch (tag) { - case DW_TAG_subprogram: - case DW_TAG_inlined_subroutine: + case DW_TAG_array_type: case DW_TAG_base_type: case DW_TAG_class_type: case DW_TAG_constant: case DW_TAG_enumeration_type: + case DW_TAG_inlined_subroutine: + case DW_TAG_namespace: case DW_TAG_string_type: - case DW_TAG_subroutine_type: case DW_TAG_structure_type: - case DW_TAG_union_type: + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: case DW_TAG_typedef: - case DW_TAG_namespace: - case DW_TAG_variable: + case DW_TAG_union_type: case DW_TAG_unspecified_type: + case DW_TAG_variable: break; default: @@ -980,15 +981,16 @@ } break; + case DW_TAG_array_type: case DW_TAG_base_type: case DW_TAG_class_type: case DW_TAG_constant: case DW_TAG_enumeration_type: case DW_TAG_string_type: - case DW_TAG_subroutine_type: case DW_TAG_structure_type: - case DW_TAG_union_type: + case DW_TAG_subroutine_type: case DW_TAG_typedef: + case DW_TAG_union_type: case DW_TAG_unspecified_type: if (name && !is_declaration) types.Insert (ConstString(name), DIERef(cu_offset, die.GetOffset())); Index: lldb/trunk/source/Symbol/JavaASTContext.cpp =================================================================== --- lldb/trunk/source/Symbol/JavaASTContext.cpp +++ lldb/trunk/source/Symbol/JavaASTContext.cpp @@ -141,7 +141,60 @@ const TypeKind m_type_kind; }; -class JavaObjectType : public JavaASTContext::JavaType +class JavaDynamicType : public JavaASTContext::JavaType +{ +public: + JavaDynamicType(LLVMCastKind kind, const ConstString &linkage_name) : + JavaType(kind), + m_linkage_name(linkage_name), + m_dynamic_type_id(nullptr) + { + } + + ConstString + GetLinkageName() const + { + return m_linkage_name; + } + + void + SetDynamicTypeId(const DWARFExpression &type_id) + { + m_dynamic_type_id = type_id; + } + + uint64_t + CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj) + { + if (!m_dynamic_type_id.IsValid()) + return UINT64_MAX; + + Value obj_load_address = value_obj.GetValue(); + obj_load_address.ResolveValue(exe_ctx); + obj_load_address.SetValueType(Value::eValueTypeLoadAddress); + + Value result; + if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address, + nullptr, result, nullptr)) + { + Error error; + + lldb::addr_t type_id_addr = result.GetScalar().UInt(); + lldb::ProcessSP process_sp = exe_ctx->GetProcessSP(); + if (process_sp) + return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(), + UINT64_MAX, error); + } + + return UINT64_MAX; + } + +public: + ConstString m_linkage_name; + DWARFExpression m_dynamic_type_id; +}; + +class JavaObjectType : public JavaDynamicType { public: struct Field @@ -152,13 +205,11 @@ }; JavaObjectType(const ConstString &name, const ConstString &linkage_name, uint32_t byte_size) - : JavaType(JavaType::eKindObject), + : JavaDynamicType(JavaType::eKindObject, linkage_name), m_name(name), - m_linkage_name(linkage_name), m_byte_size(byte_size), m_base_class_offset(0), - m_is_complete(false), - m_dynamic_type_id(nullptr) + m_is_complete(false) { } @@ -168,12 +219,6 @@ return m_name; } - ConstString - GetLinkageName() const - { - return m_linkage_name; - } - uint32_t GetByteSize() const { @@ -270,38 +315,6 @@ m_fields.push_back({name, type, offset}); } - void - SetDynamicTypeId(const DWARFExpression &type_id) - { - m_dynamic_type_id = type_id; - } - - uint64_t - CalculateDynamicTypeId(ExecutionContext *exe_ctx, ValueObject &value_obj) - { - if (!m_dynamic_type_id.IsValid()) - return UINT64_MAX; - - Value obj_load_address = value_obj.GetValue(); - obj_load_address.ResolveValue(exe_ctx); - obj_load_address.SetValueType(Value::eValueTypeLoadAddress); - - Value result; - if (m_dynamic_type_id.Evaluate(exe_ctx->GetBestExecutionContextScope(), nullptr, nullptr, 0, &obj_load_address, - nullptr, result, nullptr)) - { - Error error; - - lldb::addr_t type_id_addr = result.GetScalar().UInt(); - lldb::ProcessSP process_sp = exe_ctx->GetProcessSP(); - if (process_sp) - return process_sp->ReadUnsignedIntegerFromMemory(type_id_addr, process_sp->GetAddressByteSize(), - UINT64_MAX, error); - } - - return UINT64_MAX; - } - static bool classof(const JavaType *jt) { @@ -310,14 +323,12 @@ private: ConstString m_name; - ConstString m_linkage_name; uint32_t m_byte_size; CompilerType m_base_class; uint32_t m_base_class_offset; std::vector m_interfaces; std::vector m_fields; bool m_is_complete; - DWARFExpression m_dynamic_type_id; }; class JavaReferenceType : public JavaASTContext::JavaType @@ -360,13 +371,15 @@ CompilerType m_pointee_type; }; -class JavaArrayType : public JavaASTContext::JavaType +class JavaArrayType : public JavaDynamicType { public: - JavaArrayType(CompilerType element_type, const DWARFExpression &length_expression, const lldb::addr_t data_offset) - : JavaType(JavaType::eKindArray), + JavaArrayType(const ConstString& linkage_name, CompilerType element_type, const DWARFExpression &length_expression, + lldb::addr_t data_offset) + : JavaDynamicType(JavaType::eKindArray, linkage_name), m_element_type(element_type), - m_length_expression(length_expression) + m_length_expression(length_expression), + m_data_offset(data_offset) { } @@ -402,25 +415,37 @@ } uint32_t - GetNumElements(const ValueObject *value_obj) + GetNumElements(ValueObject *value_obj) { if (!m_length_expression.IsValid()) - return false; + return UINT32_MAX; + + Error error; + ValueObjectSP address_obj = value_obj->AddressOf(error); + if (error.Fail()) + return UINT32_MAX; - Value obj_load_address = value_obj->GetValue(); + Value obj_load_address = address_obj->GetValue(); obj_load_address.SetValueType(Value::eValueTypeLoadAddress); Value result; - if (m_length_expression.Evaluate(nullptr, nullptr, nullptr, nullptr, 0, nullptr, &obj_load_address, result, - nullptr)) + ExecutionContextScope* exec_ctx_scope = value_obj->GetExecutionContextRef().Lock(true).GetBestExecutionContextScope(); + if (m_length_expression.Evaluate(exec_ctx_scope, nullptr, nullptr, 0, nullptr, &obj_load_address, result, nullptr)) return result.GetScalar().UInt(); - return 0; + return UINT32_MAX; + } + + uint64_t + GetElementOffset(size_t idx) + { + return m_data_offset + idx * m_element_type.GetByteSize(nullptr); } private: CompilerType m_element_type; DWARFExpression m_length_expression; + lldb::addr_t m_data_offset; }; } // end of anonymous namespace @@ -998,6 +1023,10 @@ { return 32; // References are always 4 byte long in java } + else if (llvm::isa(static_cast(type))) + { + return 64; + } else if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type))) { return obj->GetByteSize() * 8; @@ -1450,14 +1479,15 @@ } CompilerType -JavaASTContext::CreateArrayType(const CompilerType &element_type, const DWARFExpression &length_expression, - const lldb::addr_t data_offset) +JavaASTContext::CreateArrayType(const ConstString &linkage_name, const CompilerType &element_type, + const DWARFExpression &length_expression, const lldb::addr_t data_offset) { ConstString name = element_type.GetTypeName(); auto it = m_array_type_map.find(name); if (it == m_array_type_map.end()) { - std::unique_ptr array_type(new JavaArrayType(element_type, length_expression, data_offset)); + std::unique_ptr array_type(new JavaArrayType(linkage_name, element_type, length_expression, + data_offset)); it = m_array_type_map.emplace(name, std::move(array_type)).first; } return CompilerType(this, it->second.get()); @@ -1512,6 +1542,24 @@ { if (JavaObjectType *obj = llvm::dyn_cast(static_cast(type.GetOpaqueQualType()))) return obj->CalculateDynamicTypeId(exe_ctx, in_value); + if (JavaArrayType *arr = llvm::dyn_cast(static_cast(type.GetOpaqueQualType()))) + return arr->CalculateDynamicTypeId(exe_ctx, in_value); + return UINT64_MAX; +} + +uint32_t +JavaASTContext::CalculateArraySize(const CompilerType &type, ValueObject &in_value) +{ + if (JavaArrayType *arr = llvm::dyn_cast(static_cast(type.GetOpaqueQualType()))) + return arr->GetNumElements(&in_value); + return UINT32_MAX; +} + +uint64_t +JavaASTContext::CalculateArrayElementOffset(const CompilerType &type, size_t index) +{ + if (JavaArrayType *arr = llvm::dyn_cast(static_cast(type.GetOpaqueQualType()))) + return arr->GetElementOffset(index); return UINT64_MAX; }