diff options
Diffstat (limited to 'lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp')
-rw-r--r-- | lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp | 1391 |
1 files changed, 668 insertions, 723 deletions
diff --git a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp index 346e2d63b90..2507465750c 100644 --- a/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp +++ b/lldb/source/Plugins/SymbolFile/DWARF/DWARFASTParserGo.cpp @@ -11,11 +11,11 @@ #include "DWARFASTParserGo.h" #include "DWARFCompileUnit.h" +#include "DWARFDIE.h" +#include "DWARFDIECollection.h" #include "DWARFDebugInfo.h" #include "DWARFDeclContext.h" #include "DWARFDefines.h" -#include "DWARFDIE.h" -#include "DWARFDIECollection.h" #include "SymbolFileDWARF.h" #include "SymbolFileDWARFDebugMap.h" #include "UniqueDWARFASTType.h" @@ -44,787 +44,732 @@ using namespace lldb; using namespace lldb_private; -DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast) - : m_ast(ast) -{ -} +DWARFASTParserGo::DWARFASTParserGo(GoASTContext &ast) : m_ast(ast) {} -DWARFASTParserGo::~DWARFASTParserGo() -{ -} +DWARFASTParserGo::~DWARFASTParserGo() {} -TypeSP -DWARFASTParserGo::ParseTypeFromDWARF(const lldb_private::SymbolContext &sc, const DWARFDIE &die, lldb_private::Log *log, - bool *type_is_new_ptr) -{ - TypeSP type_sp; +TypeSP DWARFASTParserGo::ParseTypeFromDWARF( + const lldb_private::SymbolContext &sc, const DWARFDIE &die, + lldb_private::Log *log, bool *type_is_new_ptr) { + TypeSP type_sp; - if (type_is_new_ptr) - *type_is_new_ptr = false; + if (type_is_new_ptr) + *type_is_new_ptr = false; - if (die) - { - SymbolFileDWARF *dwarf = die.GetDWARF(); - if (log) - { - dwarf->GetObjectFile()->GetModule()->LogMessage( - log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = '%s')", die.GetOffset(), - DW_TAG_value_to_name(die.Tag()), die.GetName()); - } + if (die) { + SymbolFileDWARF *dwarf = die.GetDWARF(); + if (log) { + dwarf->GetObjectFile()->GetModule()->LogMessage( + log, "DWARFASTParserGo::ParseTypeFromDWARF (die = 0x%8.8x) %s name = " + "'%s')", + die.GetOffset(), DW_TAG_value_to_name(die.Tag()), die.GetName()); + } - Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); - TypeList *type_list = dwarf->GetTypeList(); - if (type_ptr == NULL) - { - if (type_is_new_ptr) - *type_is_new_ptr = true; - - const dw_tag_t tag = die.Tag(); - - bool is_forward_declaration = false; - DWARFAttributes attributes; - const char *type_name_cstr = NULL; - ConstString type_name_const_str; - Type::ResolveState resolve_state = Type::eResolveStateUnresolved; - uint64_t byte_size = 0; - uint64_t go_kind = 0; - Declaration decl; - - Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; - CompilerType compiler_type; - DWARFFormValue form_value; - - dw_attr_t attr; - - switch (tag) - { - case DW_TAG_base_type: - case DW_TAG_pointer_type: - case DW_TAG_typedef: - case DW_TAG_unspecified_type: - { - // Set a bit that lets us know that we are currently parsing this - dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; - - const size_t num_attributes = die.GetAttributes(attributes); - lldb::user_id_t encoding_uid = LLDB_INVALID_UID; - - if (num_attributes > 0) - { - uint32_t i; - for (i = 0; i < num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - if (type_name_cstr) - type_name_const_str.SetCString(type_name_cstr); - break; - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - break; - case DW_AT_encoding: - // = form_value.Unsigned(); - break; - case DW_AT_type: - encoding_uid = form_value.Reference(); - break; - case DW_AT_go_kind: - go_kind = form_value.Unsigned(); - break; - default: - // Do we care about DW_AT_go_key or DW_AT_go_elem? - break; - } - } - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr, encoding_uid); - - switch (tag) - { - default: - break; - - case DW_TAG_unspecified_type: - resolve_state = Type::eResolveStateFull; - compiler_type = m_ast.CreateVoidType(type_name_const_str); - break; - - case DW_TAG_base_type: - resolve_state = Type::eResolveStateFull; - compiler_type = m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size); - break; - - case DW_TAG_pointer_type: - encoding_data_type = Type::eEncodingIsPointerUID; - break; - case DW_TAG_typedef: - encoding_data_type = Type::eEncodingIsTypedefUID; - CompilerType impl; - Type *type = dwarf->ResolveTypeUID(encoding_uid); - if (type) - { - if (go_kind == 0 && type->GetName() == type_name_const_str) - { - // Go emits extra typedefs as a forward declaration. Ignore these. - dwarf->m_die_to_type[die.GetDIE()] = type; - return type->shared_from_this(); - } - impl = type->GetForwardCompilerType(); - compiler_type = m_ast.CreateTypedefType (go_kind, type_name_const_str, impl); - } - break; - } - - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, - NULL, encoding_uid, encoding_data_type, &decl, compiler_type, resolve_state)); - - dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); - } + Type *type_ptr = dwarf->m_die_to_type.lookup(die.GetDIE()); + TypeList *type_list = dwarf->GetTypeList(); + if (type_ptr == NULL) { + if (type_is_new_ptr) + *type_is_new_ptr = true; + + const dw_tag_t tag = die.Tag(); + + bool is_forward_declaration = false; + DWARFAttributes attributes; + const char *type_name_cstr = NULL; + ConstString type_name_const_str; + Type::ResolveState resolve_state = Type::eResolveStateUnresolved; + uint64_t byte_size = 0; + uint64_t go_kind = 0; + Declaration decl; + + Type::EncodingDataType encoding_data_type = Type::eEncodingIsUID; + CompilerType compiler_type; + DWARFFormValue form_value; + + dw_attr_t attr; + + switch (tag) { + case DW_TAG_base_type: + case DW_TAG_pointer_type: + case DW_TAG_typedef: + case DW_TAG_unspecified_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + const size_t num_attributes = die.GetAttributes(attributes); + lldb::user_id_t encoding_uid = LLDB_INVALID_UID; + + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + if (type_name_cstr) + type_name_const_str.SetCString(type_name_cstr); + break; + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); break; + case DW_AT_encoding: + // = form_value.Unsigned(); + break; + case DW_AT_type: + encoding_uid = form_value.Reference(); + break; + case DW_AT_go_kind: + go_kind = form_value.Unsigned(); + break; + default: + // Do we care about DW_AT_go_key or DW_AT_go_elem? + break; + } + } + } + } - case DW_TAG_structure_type: - { - // Set a bit that lets us know that we are currently parsing this - dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; - bool byte_size_valid = false; - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) - { - uint32_t i; - for (i = 0; i < num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_byte_size: - byte_size = form_value.Unsigned(); - byte_size_valid = true; - break; - - case DW_AT_go_kind: - go_kind = form_value.Unsigned(); - break; - - // TODO: Should we use SLICETYPE's DW_AT_go_elem? - default: - break; - } - } - } - } - - // TODO(ribrdb): Do we need this? - - // UniqueDWARFASTType is large, so don't create a local variables on the - // stack, put it on the heap. This function is often called recursively - // and clang isn't good and sharing the stack space for variables in different blocks. - std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap(new UniqueDWARFASTType()); - - // Only try and unique the type if it has a name. - if (type_name_const_str && - dwarf->GetUniqueDWARFASTTypeMap().Find(type_name_const_str, die, decl, - byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) - { - // We have already parsed this type or from another - // compile unit. GCC loves to use the "one definition - // rule" which can result in multiple definitions - // of the same class over and over in each compile - // unit. - type_sp = unique_ast_entry_ap->m_type_sp; - if (type_sp) - { - dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); - return type_sp; - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - bool compiler_type_was_created = false; - compiler_type.SetCompilerType(&m_ast, dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE())); - if (!compiler_type) - { - compiler_type_was_created = true; - compiler_type = m_ast.CreateStructType(go_kind, type_name_const_str, byte_size); - } - - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, byte_size, - NULL, LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, - Type::eResolveStateForward)); - - // Add our type to the unique type map so we don't - // end up creating many copies of the same type over - // and over in the ASTContext for our module - unique_ast_entry_ap->m_type_sp = type_sp; - unique_ast_entry_ap->m_die = die; - unique_ast_entry_ap->m_declaration = decl; - unique_ast_entry_ap->m_byte_size = byte_size; - dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, *unique_ast_entry_ap); - - if (!is_forward_declaration) - { - // Always start the definition for a class type so that - // if the class has child classes or types that require - // the class to be created for use as their decl contexts - // the class will be ready to accept these child definitions. - if (die.HasChildren() == false) - { - // No children for this struct/union/class, lets finish it - m_ast.CompleteStructType(compiler_type); - } - else if (compiler_type_was_created) - { - // Leave this as a forward declaration until we need - // to know the details of the type. lldb_private::Type - // will automatically call the SymbolFile virtual function - // "SymbolFileDWARF::CompleteType(Type *)" - // When the definition needs to be defined. - dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = compiler_type.GetOpaqueQualType(); - dwarf->m_forward_decl_clang_type_to_die[compiler_type.GetOpaqueQualType()] = die.GetDIERef(); - // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true); - } - } - } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\") type => 0x%8.8lx\n", + die.GetID(), DW_TAG_value_to_name(tag), type_name_cstr, + encoding_uid); + + switch (tag) { + default: + break; + + case DW_TAG_unspecified_type: + resolve_state = Type::eResolveStateFull; + compiler_type = m_ast.CreateVoidType(type_name_const_str); + break; + + case DW_TAG_base_type: + resolve_state = Type::eResolveStateFull; + compiler_type = + m_ast.CreateBaseType(go_kind, type_name_const_str, byte_size); + break; + + case DW_TAG_pointer_type: + encoding_data_type = Type::eEncodingIsPointerUID; + break; + case DW_TAG_typedef: + encoding_data_type = Type::eEncodingIsTypedefUID; + CompilerType impl; + Type *type = dwarf->ResolveTypeUID(encoding_uid); + if (type) { + if (go_kind == 0 && type->GetName() == type_name_const_str) { + // Go emits extra typedefs as a forward declaration. Ignore these. + dwarf->m_die_to_type[die.GetDIE()] = type; + return type->shared_from_this(); + } + impl = type->GetForwardCompilerType(); + compiler_type = + m_ast.CreateTypedefType(go_kind, type_name_const_str, impl); + } + break; + } + + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, + byte_size, NULL, encoding_uid, + encoding_data_type, &decl, compiler_type, + resolve_state)); + + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + } break; + + case DW_TAG_structure_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + bool byte_size_valid = false; + + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); break; - case DW_TAG_subprogram: - case DW_TAG_subroutine_type: - { - // Set a bit that lets us know that we are currently parsing this - dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; - - bool is_variadic = false; - clang::StorageClass storage = clang::SC_None; //, Extern, Static, PrivateExtern - - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) - { - uint32_t i; - for (i = 0; i < num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_external: - if (form_value.Unsigned()) - { - if (storage == clang::SC_None) - storage = clang::SC_Extern; - else - storage = clang::SC_PrivateExtern; - } - break; - - case DW_AT_high_pc: - case DW_AT_low_pc: - break; - } - } - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - std::vector<CompilerType> function_param_types; - - // Parse the function children for the parameters - - if (die.HasChildren()) - { - ParseChildParameters(sc, die, is_variadic, function_param_types); - } - - // compiler_type will get the function prototype clang type after this call - compiler_type = m_ast.CreateFunctionType(type_name_const_str, function_param_types.data(), - function_param_types.size(), is_variadic); - - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, 0, NULL, - LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, compiler_type, - Type::eResolveStateFull)); - assert(type_sp.get()); - } + case DW_AT_byte_size: + byte_size = form_value.Unsigned(); + byte_size_valid = true; break; - case DW_TAG_array_type: - { - // Set a bit that lets us know that we are currently parsing this - dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; - - lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; - int64_t first_index = 0; - uint32_t byte_stride = 0; - uint32_t bit_stride = 0; - const size_t num_attributes = die.GetAttributes(attributes); - - if (num_attributes > 0) - { - uint32_t i; - for (i = 0; i < num_attributes; ++i) - { - attr = attributes.AttributeAtIndex(i); - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - case DW_AT_name: - type_name_cstr = form_value.AsCString(); - type_name_const_str.SetCString(type_name_cstr); - break; - - case DW_AT_type: - type_die_offset = form_value.Reference(); - break; - case DW_AT_byte_size: - break; // byte_size = form_value.Unsigned(); break; - case DW_AT_go_kind: - go_kind = form_value.Unsigned(); - break; - default: - break; - } - } - } - - DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), - DW_TAG_value_to_name(tag), type_name_cstr); - - Type *element_type = dwarf->ResolveTypeUID(type_die_offset); - - if (element_type) - { - std::vector<uint64_t> element_orders; - ParseChildArrayInfo(sc, die, first_index, element_orders, byte_stride, bit_stride); - if (byte_stride == 0) - byte_stride = element_type->GetByteSize(); - CompilerType array_element_type = element_type->GetForwardCompilerType(); - if (element_orders.size() > 0) - { - if (element_orders.size() > 1) - printf("golang: unsupported multi-dimensional array %s\n", type_name_cstr); - compiler_type = - m_ast.CreateArrayType(type_name_const_str, array_element_type, element_orders[0]); - } - else - { - compiler_type = m_ast.CreateArrayType(type_name_const_str, array_element_type, 0); - } - type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, - byte_stride, NULL, type_die_offset, Type::eEncodingIsUID, &decl, - compiler_type, Type::eResolveStateFull)); - type_sp->SetEncodingType(element_type); - } - } - } + case DW_AT_go_kind: + go_kind = form_value.Unsigned(); break; - default: - dwarf->GetObjectFile()->GetModule()->ReportError("{0x%8.8x}: unhandled type tag 0x%4.4x (%s), " - "please file a bug and attach the file at the " - "start of this error message", - die.GetOffset(), tag, DW_TAG_value_to_name(tag)); - break; + // TODO: Should we use SLICETYPE's DW_AT_go_elem? + default: + break; + } } + } + } - if (type_sp.get()) - { - DWARFDIE sc_parent_die = SymbolFileDWARF::GetParentSymbolContextDIE(die); - dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + // TODO(ribrdb): Do we need this? + + // UniqueDWARFASTType is large, so don't create a local variables on the + // stack, put it on the heap. This function is often called recursively + // and clang isn't good and sharing the stack space for variables in + // different blocks. + std::unique_ptr<UniqueDWARFASTType> unique_ast_entry_ap( + new UniqueDWARFASTType()); + + // Only try and unique the type if it has a name. + if (type_name_const_str && + dwarf->GetUniqueDWARFASTTypeMap().Find( + type_name_const_str, die, decl, + byte_size_valid ? byte_size : -1, *unique_ast_entry_ap)) { + // We have already parsed this type or from another + // compile unit. GCC loves to use the "one definition + // rule" which can result in multiple definitions + // of the same class over and over in each compile + // unit. + type_sp = unique_ast_entry_ap->m_type_sp; + if (type_sp) { + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + return type_sp; + } + } - SymbolContextScope *symbol_context_scope = NULL; - if (sc_parent_tag == DW_TAG_compile_unit) - { - symbol_context_scope = sc.comp_unit; - } - else if (sc.function != NULL && sc_parent_die) - { - symbol_context_scope = - sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); - if (symbol_context_scope == NULL) - symbol_context_scope = sc.function; - } + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + bool compiler_type_was_created = false; + compiler_type.SetCompilerType( + &m_ast, + dwarf->m_forward_decl_die_to_clang_type.lookup(die.GetDIE())); + if (!compiler_type) { + compiler_type_was_created = true; + compiler_type = + m_ast.CreateStructType(go_kind, type_name_const_str, byte_size); + } - if (symbol_context_scope != NULL) - { - type_sp->SetSymbolContextScope(symbol_context_scope); - } + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, + byte_size, NULL, LLDB_INVALID_UID, + Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateForward)); + + // Add our type to the unique type map so we don't + // end up creating many copies of the same type over + // and over in the ASTContext for our module + unique_ast_entry_ap->m_type_sp = type_sp; + unique_ast_entry_ap->m_die = die; + unique_ast_entry_ap->m_declaration = decl; + unique_ast_entry_ap->m_byte_size = byte_size; + dwarf->GetUniqueDWARFASTTypeMap().Insert(type_name_const_str, + *unique_ast_entry_ap); + + if (!is_forward_declaration) { + // Always start the definition for a class type so that + // if the class has child classes or types that require + // the class to be created for use as their decl contexts + // the class will be ready to accept these child definitions. + if (die.HasChildren() == false) { + // No children for this struct/union/class, lets finish it + m_ast.CompleteStructType(compiler_type); + } else if (compiler_type_was_created) { + // Leave this as a forward declaration until we need + // to know the details of the type. lldb_private::Type + // will automatically call the SymbolFile virtual function + // "SymbolFileDWARF::CompleteType(Type *)" + // When the definition needs to be defined. + dwarf->m_forward_decl_die_to_clang_type[die.GetDIE()] = + compiler_type.GetOpaqueQualType(); + dwarf->m_forward_decl_clang_type_to_die[compiler_type + .GetOpaqueQualType()] = + die.GetDIERef(); + // SetHasExternalStorage (compiler_type.GetOpaqueQualType(), true); + } + } + } break; + + case DW_TAG_subprogram: + case DW_TAG_subroutine_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + bool is_variadic = false; + clang::StorageClass storage = + clang::SC_None; //, Extern, Static, PrivateExtern + + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); + break; - // We are ready to put this type into the uniqued list up at the module level - type_list->Insert(type_sp); + case DW_AT_external: + if (form_value.Unsigned()) { + if (storage == clang::SC_None) + storage = clang::SC_Extern; + else + storage = clang::SC_PrivateExtern; + } + break; - dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + case DW_AT_high_pc: + case DW_AT_low_pc: + break; + } } + } } - else if (type_ptr != DIE_IS_BEING_PARSED) - { - type_sp = type_ptr->shared_from_this(); - } - } - return type_sp; -} -size_t -DWARFASTParserGo::ParseChildParameters(const SymbolContext &sc, + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); - const DWARFDIE &parent_die, bool &is_variadic, - std::vector<CompilerType> &function_param_types) -{ - if (!parent_die) - return 0; + std::vector<CompilerType> function_param_types; - size_t arg_idx = 0; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) - { + // Parse the function children for the parameters - dw_tag_t tag = die.Tag(); - switch (tag) - { - case DW_TAG_formal_parameter: - { - DWARFAttributes attributes; - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) - { - Declaration decl; - DWARFFormValue param_type_die_offset; - - uint32_t i; - for (i = 0; i < num_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - case DW_AT_name: - // = form_value.AsCString(); - break; - case DW_AT_type: - param_type_die_offset = form_value; - break; - case DW_AT_location: - // if (form_value.BlockData()) - // { - // const DWARFDataExtractor& debug_info_data = - // debug_info(); - // uint32_t block_length = form_value.Unsigned(); - // DWARFDataExtractor location(debug_info_data, - // form_value.BlockData() - debug_info_data.GetDataStart(), - // block_length); - // } - // else - // { - // } - // break; - default: - break; - } - } - } - - Type *type = parent_die.ResolveTypeUID(DIERef(param_type_die_offset)); - if (type) - { - function_param_types.push_back(type->GetForwardCompilerType()); - } - } - arg_idx++; - } - break; + if (die.HasChildren()) { + ParseChildParameters(sc, die, is_variadic, function_param_types); + } - case DW_TAG_unspecified_parameters: - is_variadic = true; + // compiler_type will get the function prototype clang type after this + // call + compiler_type = m_ast.CreateFunctionType( + type_name_const_str, function_param_types.data(), + function_param_types.size(), is_variadic); + + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, 0, NULL, + LLDB_INVALID_UID, Type::eEncodingIsUID, &decl, + compiler_type, Type::eResolveStateFull)); + assert(type_sp.get()); + } break; + + case DW_TAG_array_type: { + // Set a bit that lets us know that we are currently parsing this + dwarf->m_die_to_type[die.GetDIE()] = DIE_IS_BEING_PARSED; + + lldb::user_id_t type_die_offset = DW_INVALID_OFFSET; + int64_t first_index = 0; + uint32_t byte_stride = 0; + uint32_t bit_stride = 0; + const size_t num_attributes = die.GetAttributes(attributes); + + if (num_attributes > 0) { + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + attr = attributes.AttributeAtIndex(i); + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_name: + type_name_cstr = form_value.AsCString(); + type_name_const_str.SetCString(type_name_cstr); break; - default: + case DW_AT_type: + type_die_offset = form_value.Reference(); + break; + case DW_AT_byte_size: + break; // byte_size = form_value.Unsigned(); break; + case DW_AT_go_kind: + go_kind = form_value.Unsigned(); + break; + default: break; + } + } + } + + DEBUG_PRINTF("0x%8.8" PRIx64 ": %s (\"%s\")\n", die.GetID(), + DW_TAG_value_to_name(tag), type_name_cstr); + + Type *element_type = dwarf->ResolveTypeUID(type_die_offset); + + if (element_type) { + std::vector<uint64_t> element_orders; + ParseChildArrayInfo(sc, die, first_index, element_orders, + byte_stride, bit_stride); + if (byte_stride == 0) + byte_stride = element_type->GetByteSize(); + CompilerType array_element_type = + element_type->GetForwardCompilerType(); + if (element_orders.size() > 0) { + if (element_orders.size() > 1) + printf("golang: unsupported multi-dimensional array %s\n", + type_name_cstr); + compiler_type = m_ast.CreateArrayType( + type_name_const_str, array_element_type, element_orders[0]); + } else { + compiler_type = m_ast.CreateArrayType(type_name_const_str, + array_element_type, 0); + } + type_sp.reset(new Type(die.GetID(), dwarf, type_name_const_str, + byte_stride, NULL, type_die_offset, + Type::eEncodingIsUID, &decl, compiler_type, + Type::eResolveStateFull)); + type_sp->SetEncodingType(element_type); + } + } + } break; + + default: + dwarf->GetObjectFile()->GetModule()->ReportError( + "{0x%8.8x}: unhandled type tag 0x%4.4x (%s), " + "please file a bug and attach the file at the " + "start of this error message", + die.GetOffset(), tag, DW_TAG_value_to_name(tag)); + break; + } + + if (type_sp.get()) { + DWARFDIE sc_parent_die = + SymbolFileDWARF::GetParentSymbolContextDIE(die); + dw_tag_t sc_parent_tag = sc_parent_die.Tag(); + + SymbolContextScope *symbol_context_scope = NULL; + if (sc_parent_tag == DW_TAG_compile_unit) { + symbol_context_scope = sc.comp_unit; + } else if (sc.function != NULL && sc_parent_die) { + symbol_context_scope = + sc.function->GetBlock(true).FindBlockByID(sc_parent_die.GetID()); + if (symbol_context_scope == NULL) + symbol_context_scope = sc.function; } + + if (symbol_context_scope != NULL) { + type_sp->SetSymbolContextScope(symbol_context_scope); + } + + // We are ready to put this type into the uniqued list up at the module + // level + type_list->Insert(type_sp); + + dwarf->m_die_to_type[die.GetDIE()] = type_sp.get(); + } + } else if (type_ptr != DIE_IS_BEING_PARSED) { + type_sp = type_ptr->shared_from_this(); } - return arg_idx; + } + return type_sp; } -void -DWARFASTParserGo::ParseChildArrayInfo(const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, - std::vector<uint64_t> &element_orders, uint32_t &byte_stride, - uint32_t &bit_stride) -{ - if (!parent_die) - return; - - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) - { - const dw_tag_t tag = die.Tag(); - switch (tag) - { - case DW_TAG_subrange_type: - { - DWARFAttributes attributes; - const size_t num_child_attributes = die.GetAttributes(attributes); - if (num_child_attributes > 0) - { - uint64_t num_elements = 0; - uint32_t i; - for (i = 0; i < num_child_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - case DW_AT_count: - num_elements = form_value.Unsigned(); - break; - - default: - case DW_AT_type: - break; - } - } - } - - element_orders.push_back(num_elements); - } +size_t DWARFASTParserGo::ParseChildParameters( + const SymbolContext &sc, + + const DWARFDIE &parent_die, bool &is_variadic, + std::vector<CompilerType> &function_param_types) { + if (!parent_die) + return 0; + + size_t arg_idx = 0; + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); + die = die.GetSibling()) { + + dw_tag_t tag = die.Tag(); + switch (tag) { + case DW_TAG_formal_parameter: { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + Declaration decl; + DWARFFormValue param_type_die_offset; + + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_name: + // = form_value.AsCString(); + break; + case DW_AT_type: + param_type_die_offset = form_value; + break; + case DW_AT_location: + // if (form_value.BlockData()) + // { + // const DWARFDataExtractor& + // debug_info_data = + // debug_info(); + // uint32_t block_length = + // form_value.Unsigned(); + // DWARFDataExtractor + // location(debug_info_data, + // form_value.BlockData() - + // debug_info_data.GetDataStart(), + // block_length); + // } + // else + // { + // } + // break; + default: + break; } - break; + } + } + + Type *type = parent_die.ResolveTypeUID(DIERef(param_type_die_offset)); + if (type) { + function_param_types.push_back(type->GetForwardCompilerType()); } + } + arg_idx++; + } break; + + case DW_TAG_unspecified_parameters: + is_variadic = true; + break; + + default: + break; } + } + return arg_idx; } -bool -DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, lldb_private::Type *type, CompilerType &compiler_type) -{ - if (!die) - return false; +void DWARFASTParserGo::ParseChildArrayInfo( + const SymbolContext &sc, const DWARFDIE &parent_die, int64_t &first_index, + std::vector<uint64_t> &element_orders, uint32_t &byte_stride, + uint32_t &bit_stride) { + if (!parent_die) + return; + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); + die = die.GetSibling()) { const dw_tag_t tag = die.Tag(); + switch (tag) { + case DW_TAG_subrange_type: { + DWARFAttributes attributes; + const size_t num_child_attributes = die.GetAttributes(attributes); + if (num_child_attributes > 0) { + uint64_t num_elements = 0; + uint32_t i; + for (i = 0; i < num_child_attributes; ++i) { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + case DW_AT_count: + num_elements = form_value.Unsigned(); + break; - SymbolFileDWARF *dwarf = die.GetDWARF(); - Log *log = nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); - if (log) - dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( - log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", die.GetID(), - DW_TAG_value_to_name(tag), type->GetName().AsCString()); - assert(compiler_type); - DWARFAttributes attributes; - - switch (tag) - { - case DW_TAG_structure_type: - { - { - if (die.HasChildren()) - { - SymbolContext sc(die.GetLLDBCompileUnit()); - - ParseChildMembers(sc, die, compiler_type); - } + default: + case DW_AT_type: + break; } - m_ast.CompleteStructType(compiler_type); - return (bool)compiler_type; + } } - default: - assert(false && "not a forward go type decl!"); - break; + element_orders.push_back(num_elements); + } + } break; } + } +} +bool DWARFASTParserGo::CompleteTypeFromDWARF(const DWARFDIE &die, + lldb_private::Type *type, + CompilerType &compiler_type) { + if (!die) return false; -} -size_t -DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, const DWARFDIE &parent_die, CompilerType &class_compiler_type) -{ - size_t count = 0; - uint32_t member_idx = 0; + const dw_tag_t tag = die.Tag(); - ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); - GoASTContext *ast = llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem()); - if (ast == nullptr) - return 0; + SymbolFileDWARF *dwarf = die.GetDWARF(); + Log *log = + nullptr; // (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO|DWARF_LOG_TYPE_COMPLETION)); + if (log) + dwarf->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace( + log, "0x%8.8" PRIx64 ": %s '%s' resolving forward declaration...", + die.GetID(), DW_TAG_value_to_name(tag), type->GetName().AsCString()); + assert(compiler_type); + DWARFAttributes attributes; - for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); die = die.GetSibling()) + switch (tag) { + case DW_TAG_structure_type: { { - dw_tag_t tag = die.Tag(); - - switch (tag) - { - case DW_TAG_member: - { - DWARFAttributes attributes; - const size_t num_attributes = die.GetAttributes(attributes); - if (num_attributes > 0) - { - Declaration decl; - const char *name = NULL; - - DWARFFormValue encoding_uid; - uint32_t member_byte_offset = UINT32_MAX; - uint32_t i; - for (i = 0; i < num_attributes; ++i) - { - const dw_attr_t attr = attributes.AttributeAtIndex(i); - DWARFFormValue form_value; - if (attributes.ExtractFormValueAtIndex(i, form_value)) - { - switch (attr) - { - 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()) - { - Value initialValue(0); - Value memberOffset(0); - const DWARFDataExtractor &debug_info_data = - die.GetDWARF()->get_debug_info_data(); - uint32_t block_length = form_value.Unsigned(); - uint32_t block_offset = form_value.BlockData() - debug_info_data.GetDataStart(); - if (DWARFExpression::Evaluate(NULL, // ExecutionContext * - NULL, // ClangExpressionVariableList * - NULL, // ClangExpressionDeclMap * - NULL, // RegisterContext * - module_sp, debug_info_data, die.GetCU(), - block_offset, block_length, eRegisterKindDWARF, - &initialValue, NULL, memberOffset, NULL)) - { - member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); - } - } - else - { - // With DWARF 3 and later, if the value is an integer constant, - // this form value is the offset in bytes from the beginning - // of the containing entity. - member_byte_offset = form_value.Unsigned(); - } - break; - - default: - break; - } - } - } - - Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid)); - if (member_type) - { - CompilerType member_go_type = member_type->GetFullCompilerType(); - ConstString name_const_str(name); - m_ast.AddFieldToStruct(class_compiler_type, name_const_str, member_go_type, member_byte_offset); - } + if (die.HasChildren()) { + SymbolContext sc(die.GetLLDBCompileUnit()); + + ParseChildMembers(sc, die, compiler_type); + } + } + m_ast.CompleteStructType(compiler_type); + return (bool)compiler_type; + } + + default: + assert(false && "not a forward go type decl!"); + break; + } + + return false; +} + +size_t DWARFASTParserGo::ParseChildMembers(const SymbolContext &sc, + const DWARFDIE &parent_die, + CompilerType &class_compiler_type) { + size_t count = 0; + uint32_t member_idx = 0; + + ModuleSP module_sp = parent_die.GetDWARF()->GetObjectFile()->GetModule(); + GoASTContext *ast = + llvm::dyn_cast_or_null<GoASTContext>(class_compiler_type.GetTypeSystem()); + if (ast == nullptr) + return 0; + + for (DWARFDIE die = parent_die.GetFirstChild(); die.IsValid(); + die = die.GetSibling()) { + dw_tag_t tag = die.Tag(); + + switch (tag) { + case DW_TAG_member: { + DWARFAttributes attributes; + const size_t num_attributes = die.GetAttributes(attributes); + if (num_attributes > 0) { + Declaration decl; + const char *name = NULL; + + DWARFFormValue encoding_uid; + uint32_t member_byte_offset = UINT32_MAX; + uint32_t i; + for (i = 0; i < num_attributes; ++i) { + const dw_attr_t attr = attributes.AttributeAtIndex(i); + DWARFFormValue form_value; + if (attributes.ExtractFormValueAtIndex(i, form_value)) { + switch (attr) { + 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()) { + Value initialValue(0); + Value memberOffset(0); + const DWARFDataExtractor &debug_info_data = + die.GetDWARF()->get_debug_info_data(); + uint32_t block_length = form_value.Unsigned(); + uint32_t block_offset = + form_value.BlockData() - debug_info_data.GetDataStart(); + if (DWARFExpression::Evaluate( + NULL, // ExecutionContext * + NULL, // ClangExpressionVariableList * + NULL, // ClangExpressionDeclMap * + NULL, // RegisterContext * + module_sp, debug_info_data, die.GetCU(), block_offset, + block_length, eRegisterKindDWARF, &initialValue, NULL, + memberOffset, NULL)) { + member_byte_offset = memberOffset.ResolveValue(NULL).UInt(); } - ++member_idx; - } - break; + } else { + // With DWARF 3 and later, if the value is an integer constant, + // this form value is the offset in bytes from the beginning + // of the containing entity. + member_byte_offset = form_value.Unsigned(); + } + break; default: - break; + break; + } + } } + + Type *member_type = die.ResolveTypeUID(DIERef(encoding_uid)); + if (member_type) { + CompilerType member_go_type = member_type->GetFullCompilerType(); + ConstString name_const_str(name); + m_ast.AddFieldToStruct(class_compiler_type, name_const_str, + member_go_type, member_byte_offset); + } + } + ++member_idx; + } break; + + default: + break; } + } - return count; + return count; } -Function * -DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, const DWARFDIE &die) -{ - DWARFRangeList func_ranges; - const char *name = NULL; - const char *mangled = NULL; - int decl_file = 0; - int decl_line = 0; - int decl_column = 0; - int call_file = 0; - int call_line = 0; - int call_column = 0; - DWARFExpression frame_base(die.GetCU()); - - assert(die.Tag() == DW_TAG_subprogram); - - if (die.Tag() != DW_TAG_subprogram) - return NULL; - - 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); - } +Function *DWARFASTParserGo::ParseFunctionFromDWARF(const SymbolContext &sc, + const DWARFDIE &die) { + DWARFRangeList func_ranges; + const char *name = NULL; + const char *mangled = NULL; + int decl_file = 0; + int decl_line = 0; + int decl_column = 0; + int call_file = 0; + int call_line = 0; + int call_column = 0; + DWARFExpression frame_base(die.GetCU()); + + assert(die.Tag() == DW_TAG_subprogram); + + if (die.Tag() != DW_TAG_subprogram) + return NULL; - if (func_range.GetBaseAddress().IsValid()) - { - Mangled func_name; - func_name.SetValue(ConstString(name), false); - - FunctionSP func_sp; - 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)); - - SymbolFileDWARF *dwarf = die.GetDWARF(); - // Supply the type _only_ if it has already been parsed - Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE()); - - assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); - - if (dwarf->FixupAddress(func_range.GetBaseAddress())) - { - const user_id_t func_user_id = die.GetID(); - func_sp.reset(new Function(sc.comp_unit, - func_user_id, // UserID is the DIE offset - func_user_id, - func_name, - func_type, - func_range)); // first address range - - if (func_sp.get() != NULL) - { - if (frame_base.IsValid()) - func_sp->GetFrameBaseExpression() = frame_base; - sc.comp_unit->AddFunction(func_sp); - return func_sp.get(); - } - } + 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()) { + Mangled func_name; + func_name.SetValue(ConstString(name), false); + + FunctionSP func_sp; + 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)); + + SymbolFileDWARF *dwarf = die.GetDWARF(); + // Supply the type _only_ if it has already been parsed + Type *func_type = dwarf->m_die_to_type.lookup(die.GetDIE()); + + assert(func_type == NULL || func_type != DIE_IS_BEING_PARSED); + + if (dwarf->FixupAddress(func_range.GetBaseAddress())) { + const user_id_t func_user_id = die.GetID(); + func_sp.reset(new Function(sc.comp_unit, + func_user_id, // UserID is the DIE offset + func_user_id, func_name, func_type, + func_range)); // first address range + + if (func_sp.get() != NULL) { + if (frame_base.IsValid()) + func_sp->GetFrameBaseExpression() = frame_base; + sc.comp_unit->AddFunction(func_sp); + return func_sp.get(); } + } } - return NULL; + } + return NULL; } |