//---------------------------------------------------------------------- // Compare the string values. //---------------------------------------------------------------------- int Mangled::Compare (const Mangled& a, const Mangled& b) { return ConstString::Compare(a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled), a.GetName(lldb::eLanguageTypeUnknown, ePreferMangled)); }
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; } } }
//---------------------------------------------------------------------- // Compare the the string values. //---------------------------------------------------------------------- int Mangled::Compare (const Mangled& a, const Mangled& b) { return ConstString::Compare(a.GetName(), a.GetName()); }