TypeSP DWARFASTParserOCaml::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, byte_size); return std::make_shared<Type>(die.GetID(), dwarf, type_name, byte_size, nullptr, LLDB_INVALID_UID, Type::eEncodingIsUID, decl, compiler_type, Type::eResolveStateFull); }
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); } } break; } } }
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; }
void DWARFCompileUnit::Index (const uint32_t cu_idx, NameToDIE& func_basenames, NameToDIE& func_fullnames, NameToDIE& func_methods, NameToDIE& func_selectors, NameToDIE& objc_class_selectors, NameToDIE& globals, NameToDIE& types, NameToDIE& namespaces) { DWARFFormValue::FixedFormSizes fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize(), m_is_dwarf64); Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS)); if (log) { m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log, "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]", GetOffset()); } const LanguageType cu_language = GetLanguageType(); DWARFDebugInfoEntry::const_iterator pos; DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); for (pos = begin; pos != end; ++pos) { const DWARFDebugInfoEntry &die = *pos; const dw_tag_t tag = die.Tag(); switch (tag) { case DW_TAG_subprogram: case DW_TAG_inlined_subroutine: 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_typedef: case DW_TAG_namespace: case DW_TAG_variable: case DW_TAG_unspecified_type: break; default: continue; } DWARFAttributes attributes; const char *name = NULL; const char *mangled_cstr = NULL; bool is_declaration = false; //bool is_artificial = false; bool has_address = false; bool has_location = false; bool is_global_or_static_variable = false; dw_offset_t specification_die_offset = DW_INVALID_OFFSET; const size_t num_attributes = die.GetAttributes(this, fixed_form_sizes, attributes); if (num_attributes > 0) { for (uint32_t i=0; i<num_attributes; ++i) { dw_attr_t attr = attributes.AttributeAtIndex(i); DWARFFormValue form_value; switch (attr) { case DW_AT_name: if (attributes.ExtractFormValueAtIndex(i, form_value)) name = form_value.AsCString(); break; case DW_AT_declaration: if (attributes.ExtractFormValueAtIndex(i, form_value)) is_declaration = form_value.Unsigned() != 0; break; // case DW_AT_artificial: // if (attributes.ExtractFormValueAtIndex(i, form_value)) // is_artificial = form_value.Unsigned() != 0; // break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: if (attributes.ExtractFormValueAtIndex(i, form_value)) mangled_cstr = form_value.AsCString(); break; case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges: has_address = true; break; case DW_AT_entry_pc: has_address = true; break; case DW_AT_location: has_location = true; if (tag == DW_TAG_variable) { const DWARFDebugInfoEntry* parent_die = die.GetParent(); while ( parent_die != NULL ) { switch (parent_die->Tag()) { case DW_TAG_subprogram: case DW_TAG_lexical_block: case DW_TAG_inlined_subroutine: // Even if this is a function level static, we don't add it. We could theoretically // add these if we wanted to by introspecting into the DW_AT_location and seeing // if the location describes a hard coded address, but we dont want the performance // penalty of that right now. is_global_or_static_variable = false; // if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) // { // // If we have valid block data, then we have location expression bytes // // that are fixed (not a location list). // const uint8_t *block_data = form_value.BlockData(); // if (block_data) // { // uint32_t block_length = form_value.Unsigned(); // if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) // { // if (block_data[0] == DW_OP_addr) // add_die = true; // } // } // } parent_die = NULL; // Terminate the while loop. break; case DW_TAG_compile_unit: is_global_or_static_variable = true; parent_die = NULL; // Terminate the while loop. break; default: parent_die = parent_die->GetParent(); // Keep going in the while loop. break; } } } break; case DW_AT_specification: if (attributes.ExtractFormValueAtIndex(i, form_value)) specification_die_offset = form_value.Reference(); break; } } } switch (tag) { case DW_TAG_subprogram: if (has_address) { if (name) { ObjCLanguage::MethodName objc_method(name, true); if (objc_method.IsValid(true)) { ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory()); ConstString objc_selector_name (objc_method.GetSelector()); ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true)); ConstString objc_class_name_no_category (objc_method.GetClassName()); func_fullnames.Insert (ConstString(name), die.GetOffset()); if (objc_class_name_with_category) objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset()); if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category) objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset()); if (objc_selector_name) func_selectors.Insert (objc_selector_name, die.GetOffset()); if (objc_fullname_no_category_name) func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset()); } // If we have a mangled name, then the DW_AT_name attribute // is usually the method name without the class or any parameters const DWARFDebugInfoEntry *parent = die.GetParent(); bool is_method = false; if (parent) { dw_tag_t parent_tag = parent->Tag(); if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) { is_method = true; } else { if (specification_die_offset != DW_INVALID_OFFSET) { DWARFDIE specification_die = m_dwarf2Data->DebugInfo()->GetDIE (specification_die_offset); if (specification_die.GetParent().IsStructOrClass()) is_method = true; } } } if (is_method) func_methods.Insert (ConstString(name), die.GetOffset()); else func_basenames.Insert (ConstString(name), die.GetOffset()); if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) func_fullnames.Insert (ConstString(name), die.GetOffset()); } if (mangled_cstr) { // Make sure our mangled name isn't the same string table entry // as our name. If it starts with '_', then it is ok, else compare // the string to make sure it isn't the same and we don't end up // with duplicate entries if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); ConstString demangled = mangled.GetDemangledName(cu_language); if (demangled) func_fullnames.Insert (demangled, die.GetOffset()); } } } break; case DW_TAG_inlined_subroutine: if (has_address) { if (name) func_basenames.Insert (ConstString(name), die.GetOffset()); if (mangled_cstr) { // Make sure our mangled name isn't the same string table entry // as our name. If it starts with '_', then it is ok, else compare // the string to make sure it isn't the same and we don't end up // with duplicate entries if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); ConstString demangled = mangled.GetDemangledName(cu_language); if (demangled) func_fullnames.Insert (demangled, die.GetOffset()); } } else func_fullnames.Insert (ConstString(name), die.GetOffset()); } break; 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_typedef: case DW_TAG_unspecified_type: if (name && is_declaration == false) { types.Insert (ConstString(name), die.GetOffset()); } break; case DW_TAG_namespace: if (name) namespaces.Insert (ConstString(name), die.GetOffset()); break; case DW_TAG_variable: if (name && has_location && is_global_or_static_variable) { globals.Insert (ConstString(name), die.GetOffset()); // Be sure to include variables by their mangled and demangled // names if they have any since a variable can have a basename // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled // mangled name "(anonymous namespace)::i"... // Make sure our mangled name isn't the same string table entry // as our name. If it starts with '_', then it is ok, else compare // the string to make sure it isn't the same and we don't end up // with duplicate entries if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { Mangled mangled (ConstString(mangled_cstr), true); globals.Insert (mangled.GetMangledName(), die.GetOffset()); ConstString demangled = mangled.GetDemangledName(cu_language); if (demangled) globals.Insert (demangled, die.GetOffset()); } } break; default: continue; } } }
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; lldb::user_id_t encoding_uid = LLDB_INVALID_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.Reference(); 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(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; }
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 (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", dwarf->MakeUserID(die.GetOffset()), 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(dwarf->MakeUserID(die.GetOffset()), 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_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", dwarf->MakeUserID(die.GetOffset()), 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(dwarf->MakeUserID(die.GetOffset()), 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; 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", dwarf->MakeUserID(die.GetOffset()), 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(dwarf->MakeUserID(die.GetOffset()), 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; 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", dwarf->MakeUserID(die.GetOffset()), 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(dwarf->MakeUserID(die.GetOffset()), 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(dwarf->MakeUserID(sc_parent_die.GetOffset())); 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 type_sp; }
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; dw_offset_t param_type_die_offset = DW_INVALID_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.Reference(); 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(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; }
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(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; }
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); bool artificial = true; 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: artificial = 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; } } }
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; }
void ManualDWARFIndex::IndexUnitImpl( DWARFUnit &unit, const LanguageType cu_language, const DWARFFormValue::FixedFormSizes &fixed_form_sizes, const dw_offset_t cu_offset, IndexSet &set) { for (const DWARFDebugInfoEntry &die : unit.dies()) { const dw_tag_t tag = die.Tag(); switch (tag) { 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_structure_type: case DW_TAG_subprogram: case DW_TAG_subroutine_type: case DW_TAG_typedef: case DW_TAG_union_type: case DW_TAG_unspecified_type: case DW_TAG_variable: break; default: continue; } DWARFAttributes attributes; const char *name = NULL; const char *mangled_cstr = NULL; bool is_declaration = false; // bool is_artificial = false; bool has_address = false; bool has_location_or_const_value = false; bool is_global_or_static_variable = false; DWARFFormValue specification_die_form; const size_t num_attributes = die.GetAttributes(&unit, fixed_form_sizes, attributes); if (num_attributes > 0) { for (uint32_t i = 0; i < num_attributes; ++i) { dw_attr_t attr = attributes.AttributeAtIndex(i); DWARFFormValue form_value; switch (attr) { case DW_AT_name: if (attributes.ExtractFormValueAtIndex(i, form_value)) name = form_value.AsCString(); break; case DW_AT_declaration: if (attributes.ExtractFormValueAtIndex(i, form_value)) is_declaration = form_value.Unsigned() != 0; break; // case DW_AT_artificial: // if (attributes.ExtractFormValueAtIndex(i, // form_value)) // is_artificial = form_value.Unsigned() != 0; // break; case DW_AT_MIPS_linkage_name: case DW_AT_linkage_name: if (attributes.ExtractFormValueAtIndex(i, form_value)) mangled_cstr = form_value.AsCString(); break; case DW_AT_low_pc: case DW_AT_high_pc: case DW_AT_ranges: has_address = true; break; case DW_AT_entry_pc: has_address = true; break; case DW_AT_location: case DW_AT_const_value: has_location_or_const_value = true; if (tag == DW_TAG_variable) { const DWARFDebugInfoEntry *parent_die = die.GetParent(); while (parent_die != NULL) { switch (parent_die->Tag()) { case DW_TAG_subprogram: case DW_TAG_lexical_block: case DW_TAG_inlined_subroutine: // Even if this is a function level static, we don't add it. We // could theoretically add these if we wanted to by // introspecting into the DW_AT_location and seeing if the // location describes a hard coded address, but we don't want // the performance penalty of that right now. is_global_or_static_variable = false; // if (attributes.ExtractFormValueAtIndex(dwarf, i, // form_value)) { // // If we have valid block data, then we have location // // expression bytesthat are fixed (not a location list). // const uint8_t *block_data = form_value.BlockData(); // if (block_data) { // uint32_t block_length = form_value.Unsigned(); // if (block_length == 1 + // attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) { // if (block_data[0] == DW_OP_addr) // add_die = true; // } // } // } parent_die = NULL; // Terminate the while loop. break; case DW_TAG_compile_unit: case DW_TAG_partial_unit: is_global_or_static_variable = true; parent_die = NULL; // Terminate the while loop. break; default: parent_die = parent_die->GetParent(); // Keep going in the while loop. break; } } } break; case DW_AT_specification: if (attributes.ExtractFormValueAtIndex(i, form_value)) specification_die_form = form_value; break; } } } switch (tag) { case DW_TAG_inlined_subroutine: case DW_TAG_subprogram: if (has_address) { if (name) { ObjCLanguage::MethodName objc_method(name, true); if (objc_method.IsValid(true)) { ConstString objc_class_name_with_category( objc_method.GetClassNameWithCategory()); ConstString objc_selector_name(objc_method.GetSelector()); ConstString objc_fullname_no_category_name( objc_method.GetFullNameWithoutCategory(true)); ConstString objc_class_name_no_category(objc_method.GetClassName()); set.function_fullnames.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); if (objc_class_name_with_category) set.objc_class_selectors.Insert( objc_class_name_with_category, DIERef(cu_offset, die.GetOffset())); if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category) set.objc_class_selectors.Insert( objc_class_name_no_category, DIERef(cu_offset, die.GetOffset())); if (objc_selector_name) set.function_selectors.Insert(objc_selector_name, DIERef(cu_offset, die.GetOffset())); if (objc_fullname_no_category_name) set.function_fullnames.Insert(objc_fullname_no_category_name, DIERef(cu_offset, die.GetOffset())); } // If we have a mangled name, then the DW_AT_name attribute is // usually the method name without the class or any parameters bool is_method = DWARFDIE(&unit, &die).IsMethod(); if (is_method) set.function_methods.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); else set.function_basenames.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) set.function_fullnames.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); } if (mangled_cstr) { // Make sure our mangled name isn't the same string table entry as // our name. If it starts with '_', then it is ok, else compare the // string to make sure it isn't the same and we don't end up with // duplicate entries if (name && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { set.function_fullnames.Insert(ConstString(mangled_cstr), DIERef(cu_offset, die.GetOffset())); } } } 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_structure_type: case DW_TAG_subroutine_type: case DW_TAG_typedef: case DW_TAG_union_type: case DW_TAG_unspecified_type: if (name && !is_declaration) set.types.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); if (mangled_cstr && !is_declaration) set.types.Insert(ConstString(mangled_cstr), DIERef(cu_offset, die.GetOffset())); break; case DW_TAG_namespace: if (name) set.namespaces.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); break; case DW_TAG_variable: if (name && has_location_or_const_value && is_global_or_static_variable) { set.globals.Insert(ConstString(name), DIERef(cu_offset, die.GetOffset())); // Be sure to include variables by their mangled and demangled names if // they have any since a variable can have a basename "i", a mangled // named "_ZN12_GLOBAL__N_11iE" and a demangled mangled name // "(anonymous namespace)::i"... // Make sure our mangled name isn't the same string table entry as our // name. If it starts with '_', then it is ok, else compare the string // to make sure it isn't the same and we don't end up with duplicate // entries if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) { set.globals.Insert(ConstString(mangled_cstr), DIERef(cu_offset, die.GetOffset())); } } break; default: continue; } } }