bool DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data) { m_sets.clear(); DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); if (debug_info) { uint32_t cu_idx = 0; const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); DWARFDIECollection dies; const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies); dw_offset_t cu_offset = cu->GetOffset(); DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset); size_t die_idx; for (die_idx = 0; die_idx < die_count; ++die_idx) { const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); const char *name = die->GetAttributeValueAsString(dwarf2Data, cu, DW_AT_name, NULL); if (name) { pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, name); } } if (pubnames_set.NumDescriptors() > 0) { m_sets.push_back(pubnames_set); } } } return !m_sets.empty(); }
bool DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) { Timer scoped_timer (__PRETTY_FUNCTION__, "DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data); LogSP log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES)); if (log) log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", dwarf2Data); m_sets.clear(); DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); if (debug_info) { const DataExtractor* debug_str = &dwarf2Data->get_debug_str_data(); uint32_t cu_idx = 0; const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) { DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize()); bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; DWARFDIECollection dies; const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) + cu->AppendDIEsWithTag (DW_TAG_variable, dies); dw_offset_t cu_offset = cu->GetOffset(); DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset); size_t die_idx; for (die_idx = 0; die_idx < die_count; ++die_idx) { const DWARFDebugInfoEntry *die = dies.GetDIEPtrAtIndex(die_idx); DWARFDebugInfoEntry::Attributes attributes; const char *name = NULL; const char *mangled = NULL; bool add_die = false; bool is_variable = false; const size_t num_attributes = die->GetAttributes(dwarf2Data, cu, fixed_form_sizes, attributes); if (num_attributes > 0) { uint32_t i; dw_tag_t tag = die->Tag(); is_variable = tag == DW_TAG_variable; for (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(dwarf2Data, i, form_value)) name = form_value.AsCString(debug_str); break; case DW_AT_MIPS_linkage_name: if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) mangled = form_value.AsCString(debug_str); break; case DW_AT_low_pc: case DW_AT_ranges: case DW_AT_entry_pc: if (tag == DW_TAG_subprogram) add_die = true; break; case DW_AT_location: 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. add_die = 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: add_die = true; parent_die = NULL; // Terminate the while loop. break; default: parent_die = parent_die->GetParent(); // Keep going in the while loop. break; } } } break; } } } if (add_die && (name || mangled)) { pubnames_set.AddDescriptor(die->GetOffset() - cu_offset, mangled ? mangled : name); } } if (pubnames_set.NumDescriptors() > 0) { m_sets.push_back(pubnames_set); } // Keep memory down by clearing DIEs if this generate function // caused them to be parsed if (clear_dies) cu->ClearDIEs (true); } } if (m_sets.empty()) return false; if (log) Dump (log.get()); return true; }