diff options
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp')
-rw-r--r-- | source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp | 555 |
1 files changed, 555 insertions, 0 deletions
diff --git a/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp new file mode 100644 index 0000000000000..b21bf2ded4899 --- /dev/null +++ b/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp @@ -0,0 +1,555 @@ +//===-- DWARFASTParserJava.cpp ----------------------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "DWARFASTParserJava.h" +#include "DWARFAttribute.h" +#include "DWARFCompileUnit.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDebugInfoEntry.h" +#include "DWARFDeclContext.h" +#include "SymbolFileDWARF.h" + +#include "lldb/Core/Module.h" +#include "lldb/Symbol/CompileUnit.h" +#include "lldb/Symbol/SymbolContextScope.h" +#include "lldb/Symbol/TypeList.h" + +using namespace lldb; +using namespace lldb_private; + +DWARFASTParserJava::DWARFASTParserJava(JavaASTContext &ast) : m_ast(ast) +{ +} + +DWARFASTParserJava::~DWARFASTParserJava() +{ +} + +TypeSP +DWARFASTParserJava::ParseBaseTypeFromDIE(const DWARFDIE &die) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ConstString type_name; + uint64_t byte_size = 0; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + type_name.SetCString(form_value.AsCString()); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_encoding: + break; + default: + assert(false && "Unsupported attribute for DW_TAG_base_type"); + } + } + } + + Declaration decl; + CompilerType compiler_type = m_ast.CreateBaseType(type_name); + return std::make_shared<Type>(die.GetID(), dwarf, type_name, byte_size, nullptr, LLDB_INVALID_UID, + Type::eEncodingIsUID, decl, compiler_type, Type::eResolveStateFull); +} + +TypeSP +DWARFASTParserJava::ParseArrayTypeFromDIE(const DWARFDIE &die) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + ConstString linkage_name; + DWARFFormValue type_attr_value; + lldb::addr_t data_offset = LLDB_INVALID_ADDRESS; + DWARFExpression length_expression(die.GetCU()); + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_linkage_name: + linkage_name.SetCString(form_value.AsCString()); + break; + case DW_AT_type: + type_attr_value = form_value; + break; + case DW_AT_data_member_location: + data_offset = form_value.Unsigned(); + break; + case DW_AT_declaration: + break; + default: + assert(false && "Unsupported attribute for DW_TAG_array_type"); + } + } + } + + for (DWARFDIE child_die = die.GetFirstChild(); child_die.IsValid(); child_die = child_die.GetSibling()) + { + if (child_die.Tag() == DW_TAG_subrange_type) + { + DWARFAttributes attributes; + const size_t num_attributes = child_die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_count: + if (form_value.BlockData()) + length_expression.CopyOpcodeData(form_value.BlockData(), form_value.Unsigned(), + child_die.GetCU()->GetByteOrder(), + child_die.GetCU()->GetAddressByteSize()); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_subrange_type"); + } + } + } + } + else + { + assert(false && "Unsupported child for DW_TAG_array_type"); + } + } + + DIERef type_die_ref(type_attr_value); + Type *element_type = dwarf->ResolveTypeUID(type_die_ref); + if (!element_type) + return nullptr; + + CompilerType element_compiler_type = element_type->GetForwardCompilerType(); + CompilerType array_compiler_type = + 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, + type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl, + array_compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(element_type); + return type_sp; +} + +TypeSP +DWARFASTParserJava::ParseReferenceTypeFromDIE(const DWARFDIE &die) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + Declaration decl; + DWARFFormValue type_attr_value; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_type: + type_attr_value = form_value; + break; + default: + assert(false && "Unsupported attribute for DW_TAG_array_type"); + } + } + } + + DIERef type_die_ref(type_attr_value); + Type *pointee_type = dwarf->ResolveTypeUID(type_die_ref); + if (!pointee_type) + return nullptr; + + CompilerType pointee_compiler_type = pointee_type->GetForwardCompilerType(); + CompilerType reference_compiler_type = m_ast.CreateReferenceType(pointee_compiler_type); + TypeSP type_sp(new Type(die.GetID(), dwarf, reference_compiler_type.GetTypeName(), -1, nullptr, + type_die_ref.GetUID(dwarf), Type::eEncodingIsUID, &decl, + reference_compiler_type, Type::eResolveStateFull)); + type_sp->SetEncodingType(pointee_type); + return type_sp; +} + +lldb::TypeSP +DWARFASTParserJava::ParseClassTypeFromDIE(const DWARFDIE &die, bool &is_new_type) +{ + SymbolFileDWARF *dwarf = die.GetDWARF(); + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + Declaration decl; + ConstString name; + ConstString linkage_name; + bool is_forward_declaration = false; + uint32_t byte_size = 0; + + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + for (uint32_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + dw_attr_t attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attr) + { + case DW_AT_name: + name.SetCString(form_value.AsCString()); + break; + case DW_AT_declaration: + is_forward_declaration = form_value.Boolean(); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + break; + case DW_AT_linkage_name: + linkage_name.SetCString(form_value.AsCString()); + break; + default: + assert(false && "Unsupported attribute for DW_TAG_class_type"); + } + } + } + + UniqueDWARFASTType unique_ast_entry; + if (name) + { + std::string qualified_name; + if (die.GetQualifiedName(qualified_name)) + { + name.SetCString(qualified_name.c_str()); + if (dwarf->GetUniqueDWARFASTTypeMap().Find(name, die, Declaration(), -1, unique_ast_entry)) + { + if (unique_ast_entry.m_type_sp) + { + dwarf->GetDIEToType()[die.GetDIE()] = unique_ast_entry.m_type_sp.get(); + is_new_type = false; + return unique_ast_entry.m_type_sp; + } + } + } + } + + if (is_forward_declaration) + { + DWARFDeclContext die_decl_ctx; + die.GetDWARFDeclContext(die_decl_ctx); + + TypeSP type_sp = dwarf->FindDefinitionTypeForDWARFDeclContext(die_decl_ctx); + if (type_sp) + { + // We found a real definition for this type elsewhere so lets use it + dwarf->GetDIEToType()[die.GetDIE()] = type_sp.get(); + is_new_type = false; + return type_sp; + } + } + + CompilerType compiler_type(&m_ast, dwarf->GetForwardDeclDieToClangType().lookup(die.GetDIE())); + if (!compiler_type) + compiler_type = m_ast.CreateObjectType(name, linkage_name, byte_size); + + is_new_type = true; + TypeSP type_sp(new Type(die.GetID(), dwarf, name, + -1, // byte size isn't specified + nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateForward)); + + // Add our type to the unique type map + unique_ast_entry.m_type_sp = type_sp; + unique_ast_entry.m_die = die; + unique_ast_entry.m_declaration = decl; + unique_ast_entry.m_byte_size = -1; + dwarf->GetUniqueDWARFASTTypeMap().Insert(name, unique_ast_entry); + + if (!is_forward_declaration) + { + // Leave this as a forward declaration until we need to know the details of the type + dwarf->GetForwardDeclDieToClangType()[die.GetDIE()] = compiler_type.GetOpaqueQualType(); + dwarf->GetForwardDeclClangTypeToDie()[compiler_type.GetOpaqueQualType()] = die.GetDIERef(); + } + return type_sp; +} + +lldb::TypeSP +DWARFASTParserJava::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, + lldb_private::Log *log, bool *type_is_new_ptr) +{ + if (type_is_new_ptr) + *type_is_new_ptr = false; + + if (!die) + return nullptr; + + SymbolFileDWARF *dwarf = die.GetDWARF(); + + Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); + if (type_ptr == DIE_IS_BEING_PARSED) + return nullptr; + if (type_ptr != nullptr) + return type_ptr->shared_from_this(); + + TypeSP type_sp; + if (type_is_new_ptr) + *type_is_new_ptr = true; + + switch (die.Tag()) + { + case DW_TAG_base_type: + { + type_sp = ParseBaseTypeFromDIE(die); + break; + } + case DW_TAG_array_type: + { + type_sp = ParseArrayTypeFromDIE(die); + break; + } + case DW_TAG_class_type: + { + bool is_new_type = false; + type_sp = ParseClassTypeFromDIE(die, is_new_type); + if (!is_new_type) + return type_sp; + break; + } + case DW_TAG_reference_type: + { + type_sp = ParseReferenceTypeFromDIE(die); + break; + } + } + + if (!type_sp) + return nullptr; + + DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = nullptr; + if (sc_parent_tag == DW_TAG_compile_unit) + { + symbol_context_scope = sc.comp_unit; + } + else if (sc.function != nullptr && sc_parent_die) + { + symbol_context_scope = sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == nullptr) + symbol_context_scope = sc.function; + } + + if (symbol_context_scope != nullptr) + type_sp->SetSymbolContextScope(symbol_context_scope); + + dwarf->GetTypeList()->Insert(type_sp); + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + + return type_sp; +} + +lldb_private::Function * +DWARFASTParserJava::ParseFunctionFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die) +{ + assert(die.Tag() == DW_TAG_subprogram); + + const char *name = nullptr; + const char *mangled = nullptr; + int decl_file = 0; + int decl_line = 0; + int decl_column = 0; + int call_file = 0; + int call_line = 0; + int call_column = 0; + DWARFRangeList func_ranges; + DWARFExpression frame_base(die.GetCU()); + + if (die.GetDIENamesAndRanges(name, mangled, func_ranges, decl_file, decl_line, decl_column, call_file, call_line, + call_column, &frame_base)) + { + // Union of all ranges in the function DIE (if the function is discontiguous) + AddressRange func_range; + lldb::addr_t lowest_func_addr = func_ranges.GetMinRangeBase(0); + lldb::addr_t highest_func_addr = func_ranges.GetMaxRangeEnd(0); + if (lowest_func_addr != LLDB_INVALID_ADDRESS && lowest_func_addr <= highest_func_addr) + { + ModuleSP module_sp(die.GetModule()); + func_range.GetBaseAddress().ResolveAddressUsingFileSections(lowest_func_addr, module_sp->GetSectionList()); + if (func_range.GetBaseAddress().IsValid()) + func_range.SetByteSize(highest_func_addr - lowest_func_addr); + } + + if (func_range.GetBaseAddress().IsValid()) + { + std::unique_ptr<Declaration> decl_ap; + if (decl_file != 0 || decl_line != 0 || decl_column != 0) + decl_ap.reset(new Declaration(sc.comp_unit->GetSupportFiles().GetFileSpecAtIndex(decl_file), decl_line, + decl_column)); + + if (die.GetDWARF()->FixupAddress(func_range.GetBaseAddress())) + { + FunctionSP func_sp(new Function(sc.comp_unit, die.GetID(), die.GetID(), + Mangled(ConstString(name), false), + nullptr, // No function types in java + func_range)); + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + + return func_sp.get(); + } + } + } + return nullptr; +} + +bool +DWARFASTParserJava::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, + lldb_private::CompilerType &java_type) +{ + switch (die.Tag()) + { + case DW_TAG_class_type: + { + if (die.GetAttributeValueAsUnsigned(DW_AT_declaration, 0) == 0) + { + if (die.HasChildren()) + ParseChildMembers(die, java_type); + m_ast.CompleteObjectType(java_type); + return java_type.IsValid(); + } + } + break; + default: + assert(false && "Not a forward java type declaration!"); + break; + } + return false; +} + +void +DWARFASTParserJava::ParseChildMembers(const DWARFDIE &parent_die, CompilerType &compiler_type) +{ + DWARFCompileUnit *dwarf_cu = parent_die.GetCU(); + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + { + switch (die.Tag()) + { + case DW_TAG_member: + { + const char *name = nullptr; + DWARFFormValue encoding_uid; + uint32_t member_byte_offset = UINT32_MAX; + DWARFExpression member_location_expression(dwarf_cu); + + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attributes.AttributeAtIndex(i)) + { + case DW_AT_name: + name = form_value.AsCString(); + break; + case DW_AT_type: + encoding_uid = form_value; + break; + case DW_AT_data_member_location: + if (form_value.BlockData()) + member_location_expression.CopyOpcodeData( + form_value.BlockData(), form_value.Unsigned(), dwarf_cu->GetByteOrder(), + dwarf_cu->GetAddressByteSize()); + else + member_byte_offset = form_value.Unsigned(); + break; + case DW_AT_artificial: + static_cast<void>(form_value.Boolean()); + break; + case DW_AT_accessibility: + // TODO: Handle when needed + break; + default: + assert(false && "Unhandled attribute for DW_TAG_member"); + break; + } + } + } + + if (strcmp(name, ".dynamic_type") == 0) + m_ast.SetDynamicTypeId(compiler_type, member_location_expression); + else + { + if (Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid))) + m_ast.AddMemberToObject(compiler_type, ConstString(name), member_type->GetFullCompilerType(), + member_byte_offset); + } + break; + } + case DW_TAG_inheritance: + { + DWARFFormValue encoding_uid; + uint32_t member_byte_offset = UINT32_MAX; + + DWARFAttributes attributes; + size_t num_attributes = die.GetAttributes(attributes); + for (size_t i = 0; i < num_attributes; ++i) + { + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) + { + switch (attributes.AttributeAtIndex(i)) + { + case DW_AT_type: + encoding_uid = form_value; + break; + case DW_AT_data_member_location: + member_byte_offset = form_value.Unsigned(); + break; + case DW_AT_accessibility: + // In java all base class is public so we can ignore this attribute + break; + default: + assert(false && "Unhandled attribute for DW_TAG_member"); + break; + } + } + } + if (Type *base_type = die.ResolveTypeUID(DIERef(encoding_uid))) + m_ast.AddBaseClassToObject(compiler_type, base_type->GetFullCompilerType(), member_byte_offset); + break; + } + default: + break; + } + } +} |