1//===-- DWARFDebugPubnames.cpp ----------------------------------*- C++ -*-===// 2// 3// The LLVM Compiler Infrastructure 4// 5// This file is distributed under the University of Illinois Open Source 6// License. See LICENSE.TXT for details. 7// 8//===----------------------------------------------------------------------===// 9 10#include "DWARFDebugPubnames.h" 11 12#include "lldb/Core/Stream.h" 13#include "lldb/Core/Timer.h" 14 15#include "DWARFDebugInfo.h" 16#include "DWARFDIECollection.h" 17#include "DWARFFormValue.h" 18#include "DWARFCompileUnit.h" 19#include "LogChannelDWARF.h" 20#include "SymbolFileDWARF.h" 21 22 23using namespace lldb; 24using namespace lldb_private; 25 26DWARFDebugPubnames::DWARFDebugPubnames() : 27 m_sets() 28{ 29} 30 31bool 32DWARFDebugPubnames::Extract(const DWARFDataExtractor& data) 33{ 34 Timer scoped_timer (__PRETTY_FUNCTION__, 35 "DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", 36 (uint64_t)data.GetByteSize()); 37 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES)); 38 if (log) 39 log->Printf("DWARFDebugPubnames::Extract (byte_size = %" PRIu64 ")", (uint64_t)data.GetByteSize()); 40 41 if (data.ValidOffset(0)) 42 { 43 lldb::offset_t offset = 0; 44 45 DWARFDebugPubnamesSet set; 46 while (data.ValidOffset(offset)) 47 { 48 if (set.Extract(data, &offset)) 49 { 50 m_sets.push_back(set); 51 offset = set.GetOffsetOfNextEntry(); 52 } 53 else 54 break; 55 } 56 if (log) 57 Dump (log); 58 return true; 59 } 60 return false; 61} 62 63 64bool 65DWARFDebugPubnames::GeneratePubnames(SymbolFileDWARF* dwarf2Data) 66{ 67 Timer scoped_timer (__PRETTY_FUNCTION__, 68 "DWARFDebugPubnames::GeneratePubnames (data = %p)", 69 static_cast<void*>(dwarf2Data)); 70 71 Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_PUBNAMES)); 72 if (log) 73 log->Printf("DWARFDebugPubnames::GeneratePubnames (data = %p)", 74 static_cast<void*>(dwarf2Data)); 75 76 m_sets.clear(); 77 DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); 78 if (debug_info) 79 { 80 uint32_t cu_idx = 0; 81 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); 82 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) 83 { 84 85 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); 86 87 DWARFFormValue::FixedFormSizes fixed_form_sizes = 88 DWARFFormValue::GetFixedFormSizesForAddressSize (cu->GetAddressByteSize(), 89 cu->IsDWARF64()); 90 91 bool clear_dies = cu->ExtractDIEsIfNeeded (false) > 1; 92 93 DWARFDIECollection dies; 94 const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_subprogram, dies) + 95 cu->AppendDIEsWithTag (DW_TAG_variable, dies); 96 97 dw_offset_t cu_offset = cu->GetOffset(); 98 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset); 99 100 size_t die_idx; 101 for (die_idx = 0; die_idx < die_count; ++die_idx) 102 { 103 DWARFDIE die = dies.GetDIEAtIndex(die_idx); 104 DWARFAttributes attributes; 105 const char *name = NULL; 106 const char *mangled = NULL; 107 bool add_die = false; 108 const size_t num_attributes = die.GetDIE()->GetAttributes(die.GetCU(), fixed_form_sizes, attributes); 109 if (num_attributes > 0) 110 { 111 uint32_t i; 112 113 dw_tag_t tag = die.Tag(); 114 115 for (i=0; i<num_attributes; ++i) 116 { 117 dw_attr_t attr = attributes.AttributeAtIndex(i); 118 DWARFFormValue form_value; 119 switch (attr) 120 { 121 case DW_AT_name: 122 if (attributes.ExtractFormValueAtIndex(i, form_value)) 123 name = form_value.AsCString(); 124 break; 125 126 case DW_AT_MIPS_linkage_name: 127 case DW_AT_linkage_name: 128 if (attributes.ExtractFormValueAtIndex(i, form_value)) 129 mangled = form_value.AsCString(); 130 break; 131 132 case DW_AT_low_pc: 133 case DW_AT_ranges: 134 case DW_AT_entry_pc: 135 if (tag == DW_TAG_subprogram) 136 add_die = true; 137 break; 138 139 case DW_AT_location: 140 if (tag == DW_TAG_variable) 141 { 142 DWARFDIE parent_die = die.GetParent(); 143 while ( parent_die ) 144 { 145 switch (parent_die.Tag()) 146 { 147 case DW_TAG_subprogram: 148 case DW_TAG_lexical_block: 149 case DW_TAG_inlined_subroutine: 150 // Even if this is a function level static, we don't add it. We could theoretically 151 // add these if we wanted to by introspecting into the DW_AT_location and seeing 152 // if the location describes a hard coded address, but we don't want the performance 153 // penalty of that right now. 154 add_die = false; 155 parent_die.Clear(); // Terminate the while loop. 156 break; 157 158 case DW_TAG_compile_unit: 159 add_die = true; 160 parent_die.Clear(); // Terminate the while loop. 161 break; 162 163 default: 164 parent_die = parent_die.GetParent(); // Keep going in the while loop. 165 break; 166 } 167 } 168 } 169 break; 170 } 171 } 172 } 173 174 if (add_die && (name || mangled)) 175 { 176 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), mangled ? mangled : name); 177 } 178 } 179 180 if (pubnames_set.NumDescriptors() > 0) 181 { 182 m_sets.push_back(pubnames_set); 183 } 184 185 // Keep memory down by clearing DIEs if this generate function 186 // caused them to be parsed 187 if (clear_dies) 188 cu->ClearDIEs (true); 189 } 190 } 191 if (m_sets.empty()) 192 return false; 193 if (log) 194 Dump (log); 195 return true; 196} 197 198bool 199DWARFDebugPubnames::GeneratePubBaseTypes(SymbolFileDWARF* dwarf2Data) 200{ 201 m_sets.clear(); 202 DWARFDebugInfo* debug_info = dwarf2Data->DebugInfo(); 203 if (debug_info) 204 { 205 uint32_t cu_idx = 0; 206 const uint32_t num_compile_units = dwarf2Data->GetNumCompileUnits(); 207 for (cu_idx = 0; cu_idx < num_compile_units; ++cu_idx) 208 { 209 DWARFCompileUnit* cu = debug_info->GetCompileUnitAtIndex(cu_idx); 210 DWARFDIECollection dies; 211 const size_t die_count = cu->AppendDIEsWithTag (DW_TAG_base_type, dies); 212 dw_offset_t cu_offset = cu->GetOffset(); 213 DWARFDebugPubnamesSet pubnames_set(DW_INVALID_OFFSET, cu_offset, cu->GetNextCompileUnitOffset() - cu_offset); 214 215 size_t die_idx; 216 for (die_idx = 0; die_idx < die_count; ++die_idx) 217 { 218 DWARFDIE die = dies.GetDIEAtIndex (die_idx); 219 const char *name = die.GetName(); 220 221 if (name) 222 pubnames_set.AddDescriptor(die.GetCompileUnitRelativeOffset(), name); 223 } 224 225 if (pubnames_set.NumDescriptors() > 0) 226 { 227 m_sets.push_back(pubnames_set); 228 } 229 } 230 } 231 return !m_sets.empty(); 232} 233 234void 235DWARFDebugPubnames::Dump(Log *s) const 236{ 237 if (m_sets.empty()) 238 s->PutCString("< EMPTY >\n"); 239 else 240 { 241 const_iterator pos; 242 const_iterator end = m_sets.end(); 243 244 for (pos = m_sets.begin(); pos != end; ++pos) 245 (*pos).Dump(s); 246 } 247} 248 249bool 250DWARFDebugPubnames::Find(const char* name, bool ignore_case, std::vector<dw_offset_t>& die_offsets) const 251{ 252 const_iterator pos; 253 const_iterator end = m_sets.end(); 254 255 die_offsets.clear(); 256 257 for (pos = m_sets.begin(); pos != end; ++pos) 258 { 259 (*pos).Find(name, ignore_case, die_offsets); 260 } 261 262 return !die_offsets.empty(); 263} 264 265bool 266DWARFDebugPubnames::Find(const RegularExpression& regex, std::vector<dw_offset_t>& die_offsets) const 267{ 268 const_iterator pos; 269 const_iterator end = m_sets.end(); 270 271 die_offsets.clear(); 272 273 for (pos = m_sets.begin(); pos != end; ++pos) 274 { 275 (*pos).Find(regex, die_offsets); 276 } 277 278 return !die_offsets.empty(); 279} 280