summaryrefslogtreecommitdiff
path: root/source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp')
-rw-r--r--source/Plugins/SymbolFile/DWARF/DWARFASTParserJava.cpp555
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;
+ }
+ }
+}