DWARFCompileUnit.cpp revision 258054
1893SN/A//===-- DWARFCompileUnit.cpp ------------------------------------*- C++ -*-===// 214643Salanb// 3893SN/A// The LLVM Compiler Infrastructure 4893SN/A// 5893SN/A// This file is distributed under the University of Illinois Open Source 6893SN/A// License. See LICENSE.TXT for details. 72362SN/A// 8893SN/A//===----------------------------------------------------------------------===// 92362SN/A 10893SN/A#include "DWARFCompileUnit.h" 11893SN/A 12893SN/A#include "lldb/Core/Mangled.h" 13893SN/A#include "lldb/Core/Module.h" 14893SN/A#include "lldb/Core/Stream.h" 15893SN/A#include "lldb/Core/Timer.h" 16893SN/A#include "lldb/Symbol/CompileUnit.h" 17893SN/A#include "lldb/Symbol/LineTable.h" 18893SN/A#include "lldb/Symbol/ObjectFile.h" 19893SN/A#include "lldb/Target/ObjCLanguageRuntime.h" 20893SN/A 212362SN/A#include "DWARFDebugAbbrev.h" 222362SN/A#include "DWARFDebugAranges.h" 232362SN/A#include "DWARFDebugInfo.h" 24893SN/A#include "DWARFDIECollection.h" 25893SN/A#include "DWARFFormValue.h" 26893SN/A#include "LogChannelDWARF.h" 27893SN/A#include "NameToDIE.h" 28893SN/A#include "SymbolFileDWARF.h" 29893SN/A#include "SymbolFileDWARFDebugMap.h" 30893SN/A 31893SN/Ausing namespace lldb; 32893SN/Ausing namespace lldb_private; 33893SN/Ausing namespace std; 34893SN/A 35893SN/A 36893SN/Aextern int g_verbose; 37893SN/A 38893SN/ADWARFCompileUnit::DWARFCompileUnit(SymbolFileDWARF* dwarf2Data) : 39893SN/A m_dwarf2Data (dwarf2Data), 40893SN/A m_abbrevs (NULL), 41893SN/A m_user_data (NULL), 4211179Sbpb m_die_array (), 43893SN/A m_func_aranges_ap (), 44893SN/A m_base_addr (0), 45893SN/A m_offset (DW_INVALID_OFFSET), 46893SN/A m_length (0), 47893SN/A m_version (0), 48893SN/A m_addr_size (DWARFCompileUnit::GetDefaultAddressSize()), 49893SN/A m_producer (eProducerInvalid), 50893SN/A m_producer_version_major (0), 51893SN/A m_producer_version_minor (0), 52893SN/A m_producer_version_update (0) 53893SN/A{ 54893SN/A} 55893SN/A 56893SN/Avoid 57893SN/ADWARFCompileUnit::Clear() 58893SN/A{ 59893SN/A m_offset = DW_INVALID_OFFSET; 60893SN/A m_length = 0; 61893SN/A m_version = 0; 62893SN/A m_abbrevs = NULL; 63893SN/A m_addr_size = DWARFCompileUnit::GetDefaultAddressSize(); 64893SN/A m_base_addr = 0; 65893SN/A m_die_array.clear(); 66893SN/A m_func_aranges_ap.reset(); 67893SN/A m_user_data = NULL; 68893SN/A m_producer = eProducerInvalid; 69893SN/A} 70893SN/A 71893SN/Abool 72893SN/ADWARFCompileUnit::Extract(const DWARFDataExtractor &debug_info, lldb::offset_t *offset_ptr) 73893SN/A{ 74893SN/A Clear(); 75893SN/A 76893SN/A m_offset = *offset_ptr; 77907SN/A 78907SN/A if (debug_info.ValidOffset(*offset_ptr)) 79907SN/A { 80907SN/A dw_offset_t abbr_offset; 81893SN/A const DWARFDebugAbbrev *abbr = m_dwarf2Data->DebugAbbrev(); 82893SN/A m_length = debug_info.GetU32(offset_ptr); 83893SN/A m_version = debug_info.GetU16(offset_ptr); 84893SN/A abbr_offset = debug_info.GetU32(offset_ptr); 85893SN/A m_addr_size = debug_info.GetU8 (offset_ptr); 86893SN/A 87893SN/A bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); 88893SN/A bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 89907SN/A bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(abbr_offset); 90893SN/A bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 91893SN/A 92893SN/A if (length_OK && version_OK && addr_size_OK && abbr_offset_OK && abbr != NULL) 93893SN/A { 94893SN/A m_abbrevs = abbr->GetAbbreviationDeclarationSet(abbr_offset); 95893SN/A return true; 96893SN/A } 97907SN/A 98893SN/A // reset the offset to where we tried to parse from if anything went wrong 99907SN/A *offset_ptr = m_offset; 100907SN/A } 101907SN/A 102907SN/A return false; 103893SN/A} 104893SN/A 105893SN/A 106907SN/Avoid 107907SN/ADWARFCompileUnit::ClearDIEs(bool keep_compile_unit_die) 108907SN/A{ 109907SN/A if (m_die_array.size() > 1) 110907SN/A { 111907SN/A // std::vectors never get any smaller when resized to a smaller size, 112907SN/A // or when clear() or erase() are called, the size will report that it 113907SN/A // is smaller, but the memory allocated remains intact (call capacity() 114907SN/A // to see this). So we need to create a temporary vector and swap the 115907SN/A // contents which will cause just the internal pointers to be swapped 116907SN/A // so that when "tmp_array" goes out of scope, it will destroy the 117907SN/A // contents. 118893SN/A 119893SN/A // Save at least the compile unit DIE 120893SN/A DWARFDebugInfoEntry::collection tmp_array; 121893SN/A m_die_array.swap(tmp_array); 122893SN/A if (keep_compile_unit_die) 123907SN/A m_die_array.push_back(tmp_array.front()); 124907SN/A } 125907SN/A} 126907SN/A 127907SN/A//---------------------------------------------------------------------- 128907SN/A// ParseCompileUnitDIEsIfNeeded 129907SN/A// 130907SN/A// Parses a compile unit and indexes its DIEs if it hasn't already been 131907SN/A// done. 132907SN/A//---------------------------------------------------------------------- 133907SN/Asize_t 1349720SN/ADWARFCompileUnit::ExtractDIEsIfNeeded (bool cu_die_only) 135907SN/A{ 136907SN/A const size_t initial_die_array_size = m_die_array.size(); 137907SN/A if ((cu_die_only && initial_die_array_size > 0) || initial_die_array_size > 1) 138907SN/A return 0; // Already parsed 139907SN/A 140907SN/A Timer scoped_timer (__PRETTY_FUNCTION__, 141907SN/A "%8.8x: DWARFCompileUnit::ExtractDIEsIfNeeded( cu_die_only = %i )", 142907SN/A m_offset, 143907SN/A cu_die_only); 144907SN/A 145907SN/A // Set the offset to that of the first DIE and calculate the start of the 146907SN/A // next compilation unit header. 147907SN/A lldb::offset_t offset = GetFirstDIEOffset(); 148907SN/A lldb::offset_t next_cu_offset = GetNextCompileUnitOffset(); 149907SN/A 150907SN/A DWARFDebugInfoEntry die; 151907SN/A // Keep a flat array of the DIE for binary lookup by DIE offset 152907SN/A if (!cu_die_only) 153907SN/A { 154907SN/A Log *log (LogChannelDWARF::GetLogIfAny(DWARF_LOG_DEBUG_INFO | DWARF_LOG_LOOKUPS)); 155907SN/A if (log) 156907SN/A { 157907SN/A m_dwarf2Data->GetObjectFile()->GetModule()->LogMessageVerboseBacktrace (log, 158907SN/A "DWARFCompileUnit::ExtractDIEsIfNeeded () for compile unit at .debug_info[0x%8.8x]", 159907SN/A GetOffset()); 1601319SN/A } 1611319SN/A } 162907SN/A 163907SN/A uint32_t depth = 0; 164893SN/A // We are in our compile unit, parse starting at the offset 165893SN/A // we were told to parse 166893SN/A const DWARFDataExtractor& debug_info_data = m_dwarf2Data->get_debug_info_data(); 167893SN/A std::vector<uint32_t> die_index_stack; 168893SN/A die_index_stack.reserve(32); 169893SN/A die_index_stack.push_back(0); 170893SN/A bool prev_die_had_children = false; 171893SN/A const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); 172893SN/A while (offset < next_cu_offset && 173893SN/A die.FastExtract (debug_info_data, this, fixed_form_sizes, &offset)) 174893SN/A { 175893SN/A// if (log) 176893SN/A// log->Printf("0x%8.8x: %*.*s%s%s", 177893SN/A// die.GetOffset(), 178893SN/A// depth * 2, depth * 2, "", 179893SN/A// DW_TAG_value_to_name (die.Tag()), 180893SN/A// die.HasChildren() ? " *" : ""); 181893SN/A 182893SN/A const bool null_die = die.IsNULL(); 183893SN/A if (depth == 0) 184893SN/A { 185893SN/A uint64_t base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_low_pc, LLDB_INVALID_ADDRESS); 186893SN/A if (base_addr == LLDB_INVALID_ADDRESS) 187893SN/A base_addr = die.GetAttributeValueAsUnsigned(m_dwarf2Data, this, DW_AT_entry_pc, 0); 188893SN/A SetBaseAddress (base_addr); 189893SN/A if (initial_die_array_size == 0) 190893SN/A AddDIE (die); 191893SN/A if (cu_die_only) 192893SN/A return 1; 193893SN/A } 194893SN/A else 195893SN/A { 196893SN/A if (null_die) 197893SN/A { 198893SN/A if (prev_die_had_children) 199893SN/A { 200893SN/A // This will only happen if a DIE says is has children 201893SN/A // but all it contains is a NULL tag. Since we are removing 202893SN/A // the NULL DIEs from the list (saves up to 25% in C++ code), 203893SN/A // we need a way to let the DIE know that it actually doesn't 204893SN/A // have children. 205893SN/A if (!m_die_array.empty()) 206893SN/A m_die_array.back().SetEmptyChildren(true); 207893SN/A } 208893SN/A } 209893SN/A else 210893SN/A { 211893SN/A die.SetParentIndex(m_die_array.size() - die_index_stack[depth-1]); 212893SN/A 213893SN/A if (die_index_stack.back()) 214893SN/A m_die_array[die_index_stack.back()].SetSiblingIndex(m_die_array.size()-die_index_stack.back()); 215893SN/A 216893SN/A // Only push the DIE if it isn't a NULL DIE 217893SN/A m_die_array.push_back(die); 218893SN/A } 219893SN/A } 220893SN/A 221893SN/A if (null_die) 222893SN/A { 223893SN/A // NULL DIE. 2243471SN/A if (!die_index_stack.empty()) 2253471SN/A die_index_stack.pop_back(); 226893SN/A 227893SN/A if (depth > 0) 228893SN/A --depth; 229893SN/A if (depth == 0) 230893SN/A break; // We are done with this compile unit! 231893SN/A 232893SN/A prev_die_had_children = false; 233893SN/A } 234893SN/A else 235893SN/A { 236893SN/A die_index_stack.back() = m_die_array.size() - 1; 237893SN/A // Normal DIE 238893SN/A const bool die_has_children = die.HasChildren(); 239893SN/A if (die_has_children) 240893SN/A { 241893SN/A die_index_stack.push_back(0); 242893SN/A ++depth; 243893SN/A } 244893SN/A prev_die_had_children = die_has_children; 245893SN/A } 24614853Salanb } 24714853Salanb 24814853Salanb // Give a little bit of info if we encounter corrupt DWARF (our offset 24914853Salanb // should always terminate at or before the start of the next compilation 250893SN/A // unit header). 25114853Salanb if (offset > next_cu_offset) 252893SN/A { 253893SN/A m_dwarf2Data->GetObjectFile()->GetModule()->ReportWarning ("DWARF compile unit extends beyond its bounds cu 0x%8.8x at 0x%8.8" PRIx64 "\n", 254893SN/A GetOffset(), 255893SN/A offset); 256893SN/A } 257893SN/A 258893SN/A // Since std::vector objects will double their size, we really need to 259893SN/A // make a new array with the perfect size so we don't end up wasting 260893SN/A // space. So here we copy and swap to make sure we don't have any extra 261893SN/A // memory taken up. 262893SN/A 263893SN/A if (m_die_array.size () < m_die_array.capacity()) 264893SN/A { 265893SN/A DWARFDebugInfoEntry::collection exact_size_die_array (m_die_array.begin(), m_die_array.end()); 266893SN/A exact_size_die_array.swap (m_die_array); 267893SN/A } 268893SN/A Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_DEBUG_INFO | DWARF_LOG_VERBOSE)); 269893SN/A if (log) 270893SN/A { 271893SN/A StreamString strm; 272893SN/A DWARFDebugInfoEntry::DumpDIECollection (strm, m_die_array); 273893SN/A log->PutCString (strm.GetString().c_str()); 274893SN/A } 275893SN/A 276893SN/A return m_die_array.size(); 277893SN/A} 278893SN/A 279893SN/A 280893SN/Adw_offset_t 281893SN/ADWARFCompileUnit::GetAbbrevOffset() const 282893SN/A{ 2833471SN/A return m_abbrevs ? m_abbrevs->GetOffset() : DW_INVALID_OFFSET; 2847115SN/A} 285893SN/A 286893SN/A 287893SN/A 288893SN/Abool 289893SN/ADWARFCompileUnit::Verify(Stream *s) const 290893SN/A{ 291893SN/A const DWARFDataExtractor& debug_info = m_dwarf2Data->get_debug_info_data(); 292893SN/A bool valid_offset = debug_info.ValidOffset(m_offset); 293893SN/A bool length_OK = debug_info.ValidOffset(GetNextCompileUnitOffset()-1); 294893SN/A bool version_OK = SymbolFileDWARF::SupportedVersion(m_version); 295893SN/A bool abbr_offset_OK = m_dwarf2Data->get_debug_abbrev_data().ValidOffset(GetAbbrevOffset()); 296893SN/A bool addr_size_OK = ((m_addr_size == 4) || (m_addr_size == 8)); 297893SN/A bool verbose = s->GetVerbose(); 298893SN/A if (valid_offset && length_OK && version_OK && addr_size_OK && abbr_offset_OK) 299893SN/A { 300893SN/A if (verbose) 3013471SN/A s->Printf(" 0x%8.8x: OK\n", m_offset); 3023471SN/A return true; 3033471SN/A } 3043471SN/A else 3053471SN/A { 3063471SN/A s->Printf(" 0x%8.8x: ", m_offset); 3073471SN/A 3083471SN/A m_dwarf2Data->get_debug_info_data().Dump (s, m_offset, lldb::eFormatHex, 1, Size(), 32, LLDB_INVALID_ADDRESS, 0, 0); 309893SN/A s->EOL(); 3103471SN/A if (valid_offset) 3113471SN/A { 3123471SN/A if (!length_OK) 3133471SN/A s->Printf(" The length (0x%8.8x) for this compile unit is too large for the .debug_info provided.\n", m_length); 3143471SN/A if (!version_OK) 315893SN/A s->Printf(" The 16 bit compile unit header version is not supported.\n"); 3163471SN/A if (!abbr_offset_OK) 317893SN/A s->Printf(" The offset into the .debug_abbrev section (0x%8.8x) is not valid.\n", GetAbbrevOffset()); 318893SN/A if (!addr_size_OK) 319893SN/A s->Printf(" The address size is unsupported: 0x%2.2x\n", m_addr_size); 320893SN/A } 321893SN/A else 322893SN/A s->Printf(" The start offset of the compile unit header in the .debug_info is invalid.\n"); 323893SN/A } 324893SN/A return false; 325893SN/A} 326893SN/A 327893SN/A 328893SN/Avoid 329893SN/ADWARFCompileUnit::Dump(Stream *s) const 330893SN/A{ 331893SN/A s->Printf("0x%8.8x: Compile Unit: length = 0x%8.8x, version = 0x%4.4x, abbr_offset = 0x%8.8x, addr_size = 0x%2.2x (next CU at {0x%8.8x})\n", 332893SN/A m_offset, m_length, m_version, GetAbbrevOffset(), m_addr_size, GetNextCompileUnitOffset()); 333893SN/A} 334893SN/A 335893SN/A 336893SN/Astatic uint8_t g_default_addr_size = 4; 337893SN/A 338893SN/Auint8_t 339893SN/ADWARFCompileUnit::GetAddressByteSize(const DWARFCompileUnit* cu) 340893SN/A{ 341893SN/A if (cu) 342893SN/A return cu->GetAddressByteSize(); 343893SN/A return DWARFCompileUnit::GetDefaultAddressSize(); 344893SN/A} 345893SN/A 346893SN/Auint8_t 347893SN/ADWARFCompileUnit::GetDefaultAddressSize() 348893SN/A{ 3493471SN/A return g_default_addr_size; 3503471SN/A} 3513471SN/A 3523471SN/Avoid 3533471SN/ADWARFCompileUnit::SetDefaultAddressSize(uint8_t addr_size) 354893SN/A{ 355893SN/A g_default_addr_size = addr_size; 356893SN/A} 357893SN/A 358907SN/Avoid 359907SN/ADWARFCompileUnit::BuildAddressRangeTable (SymbolFileDWARF* dwarf2Data, 360907SN/A DWARFDebugAranges* debug_aranges, 361907SN/A bool clear_dies_if_already_not_parsed) 362907SN/A{ 363907SN/A // This function is usually called if there in no .debug_aranges section 364893SN/A // in order to produce a compile unit level set of address ranges that 365893SN/A // is accurate. If the DIEs weren't parsed, then we don't want all dies for 366893SN/A // all compile units to stay loaded when they weren't needed. So we can end 367893SN/A // up parsing the DWARF and then throwing them all away to keep memory usage 368893SN/A // down. 3693471SN/A const bool clear_dies = ExtractDIEsIfNeeded (false) > 1; 370893SN/A 371893SN/A const DWARFDebugInfoEntry* die = DIE(); 372893SN/A if (die) 373893SN/A die->BuildAddressRangeTable(dwarf2Data, this, debug_aranges); 374893SN/A 375893SN/A if (debug_aranges->IsEmpty()) 376893SN/A { 377893SN/A // We got nothing from the functions, maybe we have a line tables only 37815459Salanb // situation. Check the line tables and build the arange table from this. 37915459Salanb SymbolContext sc; 38015459Salanb sc.comp_unit = dwarf2Data->GetCompUnitForDWARFCompUnit(this); 38115459Salanb if (sc.comp_unit) 38215459Salanb { 38315459Salanb SymbolFileDWARFDebugMap *debug_map_sym_file = m_dwarf2Data->GetDebugMapSymfile(); 38415459Salanb if (debug_map_sym_file == NULL) 38515459Salanb { 38615459Salanb LineTable *line_table = sc.comp_unit->GetLineTable(); 38715459Salanb 38815459Salanb if (line_table) 38915459Salanb { 39015459Salanb LineTable::FileAddressRanges file_ranges; 39115459Salanb const bool append = true; 392893SN/A const size_t num_ranges = line_table->GetContiguousFileAddressRanges (file_ranges, append); 393893SN/A for (uint32_t idx=0; idx<num_ranges; ++idx) 39415459Salanb { 39515459Salanb const LineTable::FileAddressRanges::Entry &range = file_ranges.GetEntryRef(idx); 3963471SN/A debug_aranges->AppendRange(GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); 397893SN/A printf ("0x%8.8x: [0x%16.16" PRIx64 " - 0x%16.16" PRIx64 ")\n", GetOffset(), range.GetRangeBase(), range.GetRangeEnd()); 398893SN/A } 39915459Salanb } 400893SN/A } 401893SN/A else 402893SN/A debug_map_sym_file->AddOSOARanges(dwarf2Data,debug_aranges); 40315459Salanb } 404893SN/A } 405893SN/A 40611372Sbpb // Keep memory down by clearing DIEs if this generate function 40711372Sbpb // caused them to be parsed 40815459Salanb if (clear_dies) 40915459Salanb ClearDIEs (true); 41011372Sbpb 41115459Salanb} 41215459Salanb 41315459Salanb 41415459Salanbconst DWARFDebugAranges & 41515459SalanbDWARFCompileUnit::GetFunctionAranges () 41615459Salanb{ 41715459Salanb if (m_func_aranges_ap.get() == NULL) 41815459Salanb { 419893SN/A m_func_aranges_ap.reset (new DWARFDebugAranges()); 420893SN/A Log *log (LogChannelDWARF::GetLogIfAll(DWARF_LOG_DEBUG_ARANGES)); 42115459Salanb 422893SN/A if (log) 423893SN/A { 42415459Salanb m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log, 425893SN/A "DWARFCompileUnit::GetFunctionAranges() for compile unit at .debug_info[0x%8.8x]", 426893SN/A GetOffset()); 427893SN/A } 428893SN/A const DWARFDebugInfoEntry* die = DIE(); 42915459Salanb if (die) 43015459Salanb die->BuildFunctionAddressRangeTable (m_dwarf2Data, this, m_func_aranges_ap.get()); 43115459Salanb const bool minimize = false; 43215459Salanb m_func_aranges_ap->Sort(minimize); 43315459Salanb } 43415459Salanb return *m_func_aranges_ap.get(); 43515459Salanb} 43615459Salanb 43715459Salanbbool 43815459SalanbDWARFCompileUnit::LookupAddress 43915459Salanb( 44015459Salanb const dw_addr_t address, 44115459Salanb DWARFDebugInfoEntry** function_die_handle, 44215459Salanb DWARFDebugInfoEntry** block_die_handle 44315459Salanb) 44415459Salanb{ 44515459Salanb bool success = false; 44615459Salanb 44715459Salanb if (function_die_handle != NULL && DIE()) 44815459Salanb { 44915459Salanb 45015459Salanb const DWARFDebugAranges &func_aranges = GetFunctionAranges (); 45115459Salanb 45215459Salanb // Re-check the aranges auto pointer contents in case it was created above 45315459Salanb if (!func_aranges.IsEmpty()) 45415459Salanb { 45515459Salanb *function_die_handle = GetDIEPtr(func_aranges.FindAddress(address)); 45615459Salanb if (*function_die_handle != NULL) 45715459Salanb { 45815459Salanb success = true; 45915459Salanb if (block_die_handle != NULL) 460893SN/A { 46115459Salanb DWARFDebugInfoEntry* child = (*function_die_handle)->GetFirstChild(); 462893SN/A while (child) 463893SN/A { 464893SN/A if (child->LookupAddress(address, m_dwarf2Data, this, NULL, block_die_handle)) 465893SN/A break; 46615459Salanb child = child->GetSibling(); 46715459Salanb } 46815459Salanb } 46914853Salanb } 47014853Salanb } 471893SN/A } 472893SN/A return success; 47315459Salanb} 474893SN/A 475893SN/A//---------------------------------------------------------------------- 476893SN/A// Compare function DWARFDebugAranges::Range structures 477893SN/A//---------------------------------------------------------------------- 478893SN/Astatic bool CompareDIEOffset (const DWARFDebugInfoEntry& die1, const DWARFDebugInfoEntry& die2) 47915459Salanb{ 480893SN/A return die1.GetOffset() < die2.GetOffset(); 4813471SN/A} 482893SN/A 483893SN/A//---------------------------------------------------------------------- 484893SN/A// GetDIEPtr() 485893SN/A// 486893SN/A// Get the DIE (Debug Information Entry) with the specified offset. 4878565SN/A//---------------------------------------------------------------------- 488893SN/ADWARFDebugInfoEntry* 489893SN/ADWARFCompileUnit::GetDIEPtr(dw_offset_t die_offset) 490893SN/A{ 491893SN/A if (die_offset != DW_INVALID_OFFSET) 492893SN/A { 493893SN/A ExtractDIEsIfNeeded (false); 494893SN/A DWARFDebugInfoEntry compare_die; 495893SN/A compare_die.SetOffset(die_offset); 496893SN/A DWARFDebugInfoEntry::iterator end = m_die_array.end(); 497893SN/A DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); 498893SN/A if (pos != end) 499893SN/A { 500893SN/A if (die_offset == (*pos).GetOffset()) 501893SN/A return &(*pos); 502893SN/A } 503893SN/A } 504893SN/A return NULL; // Not found in any compile units 505893SN/A} 506893SN/A 507893SN/A//---------------------------------------------------------------------- 508893SN/A// GetDIEPtrContainingOffset() 509893SN/A// 510893SN/A// Get the DIE (Debug Information Entry) that contains the specified 511893SN/A// .debug_info offset. 512893SN/A//---------------------------------------------------------------------- 513893SN/Aconst DWARFDebugInfoEntry* 514893SN/ADWARFCompileUnit::GetDIEPtrContainingOffset(dw_offset_t die_offset) 515893SN/A{ 516893SN/A if (die_offset != DW_INVALID_OFFSET) 517893SN/A { 518893SN/A ExtractDIEsIfNeeded (false); 519893SN/A DWARFDebugInfoEntry compare_die; 520893SN/A compare_die.SetOffset(die_offset); 521893SN/A DWARFDebugInfoEntry::iterator end = m_die_array.end(); 522893SN/A DWARFDebugInfoEntry::iterator pos = lower_bound(m_die_array.begin(), end, compare_die, CompareDIEOffset); 523893SN/A if (pos != end) 524893SN/A { 525893SN/A if (die_offset >= (*pos).GetOffset()) 526893SN/A { 527893SN/A DWARFDebugInfoEntry::iterator next = pos + 1; 528893SN/A if (next != end) 529893SN/A { 530893SN/A if (die_offset < (*next).GetOffset()) 531893SN/A return &(*pos); 532893SN/A } 533893SN/A } 534893SN/A } 535893SN/A } 536893SN/A return NULL; // Not found in any compile units 537893SN/A} 538893SN/A 539893SN/A 540893SN/A 541893SN/Asize_t 542893SN/ADWARFCompileUnit::AppendDIEsWithTag (const dw_tag_t tag, DWARFDIECollection& dies, uint32_t depth) const 543893SN/A{ 544893SN/A size_t old_size = dies.Size(); 545893SN/A DWARFDebugInfoEntry::const_iterator pos; 546893SN/A DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 547893SN/A for (pos = m_die_array.begin(); pos != end; ++pos) 548893SN/A { 549893SN/A if (pos->Tag() == tag) 550893SN/A dies.Append (&(*pos)); 551893SN/A } 552893SN/A 553893SN/A // Return the number of DIEs added to the collection 554893SN/A return dies.Size() - old_size; 555893SN/A} 556893SN/A 557893SN/A//void 558893SN/A//DWARFCompileUnit::AddGlobalDIEByIndex (uint32_t die_idx) 5593471SN/A//{ 560893SN/A// m_global_die_indexes.push_back (die_idx); 561893SN/A//} 562893SN/A// 563893SN/A// 564893SN/A//void 565893SN/A//DWARFCompileUnit::AddGlobal (const DWARFDebugInfoEntry* die) 566893SN/A//{ 567893SN/A// // Indexes to all file level global and static variables 5683471SN/A// m_global_die_indexes; 569893SN/A// 570893SN/A// if (m_die_array.empty()) 571893SN/A// return; 572893SN/A// 573893SN/A// const DWARFDebugInfoEntry* first_die = &m_die_array[0]; 574893SN/A// const DWARFDebugInfoEntry* end = first_die + m_die_array.size(); 575893SN/A// if (first_die <= die && die < end) 576893SN/A// m_global_die_indexes.push_back (die - first_die); 577893SN/A//} 578893SN/A 579893SN/A 5803471SN/Avoid 5813471SN/ADWARFCompileUnit::Index (const uint32_t cu_idx, 582893SN/A NameToDIE& func_basenames, 583893SN/A NameToDIE& func_fullnames, 584893SN/A NameToDIE& func_methods, 585893SN/A NameToDIE& func_selectors, 586893SN/A NameToDIE& objc_class_selectors, 587893SN/A NameToDIE& globals, 588893SN/A NameToDIE& types, 589893SN/A NameToDIE& namespaces) 590893SN/A{ 591893SN/A const DWARFDataExtractor* debug_str = &m_dwarf2Data->get_debug_str_data(); 592893SN/A 593893SN/A const uint8_t *fixed_form_sizes = DWARFFormValue::GetFixedFormSizesForAddressSize (GetAddressByteSize()); 594893SN/A 595893SN/A Log *log (LogChannelDWARF::GetLogIfAll (DWARF_LOG_LOOKUPS)); 596893SN/A 597893SN/A if (log) 598893SN/A { 599893SN/A m_dwarf2Data->GetObjectFile()->GetModule()->LogMessage (log, 600893SN/A "DWARFCompileUnit::Index() for compile unit at .debug_info[0x%8.8x]", 601893SN/A GetOffset()); 602893SN/A } 603893SN/A 604893SN/A DWARFDebugInfoEntry::const_iterator pos; 605893SN/A DWARFDebugInfoEntry::const_iterator begin = m_die_array.begin(); 606893SN/A DWARFDebugInfoEntry::const_iterator end = m_die_array.end(); 607893SN/A for (pos = begin; pos != end; ++pos) 608893SN/A { 609893SN/A const DWARFDebugInfoEntry &die = *pos; 610893SN/A 611893SN/A const dw_tag_t tag = die.Tag(); 612893SN/A 613893SN/A switch (tag) 614893SN/A { 615893SN/A case DW_TAG_subprogram: 616893SN/A case DW_TAG_inlined_subroutine: 617893SN/A case DW_TAG_base_type: 618893SN/A case DW_TAG_class_type: 619893SN/A case DW_TAG_constant: 620893SN/A case DW_TAG_enumeration_type: 621893SN/A case DW_TAG_string_type: 622893SN/A case DW_TAG_subroutine_type: 623893SN/A case DW_TAG_structure_type: 624893SN/A case DW_TAG_union_type: 625893SN/A case DW_TAG_typedef: 626893SN/A case DW_TAG_namespace: 627893SN/A case DW_TAG_variable: 628893SN/A case DW_TAG_unspecified_type: 629893SN/A break; 630893SN/A 631893SN/A default: 632893SN/A continue; 6333471SN/A } 6343471SN/A 6353471SN/A DWARFDebugInfoEntry::Attributes attributes; 6363471SN/A const char *name = NULL; 6373471SN/A const char *mangled_cstr = NULL; 6383471SN/A bool is_declaration = false; 6393471SN/A //bool is_artificial = false; 6403471SN/A bool has_address = false; 6413471SN/A bool has_location = false; 6423471SN/A bool is_global_or_static_variable = false; 6433471SN/A 6443471SN/A dw_offset_t specification_die_offset = DW_INVALID_OFFSET; 6453471SN/A const size_t num_attributes = die.GetAttributes(m_dwarf2Data, this, fixed_form_sizes, attributes); 6463471SN/A if (num_attributes > 0) 6473471SN/A { 6483471SN/A for (uint32_t i=0; i<num_attributes; ++i) 649893SN/A { 650893SN/A dw_attr_t attr = attributes.AttributeAtIndex(i); 651893SN/A DWARFFormValue form_value; 652893SN/A switch (attr) 653893SN/A { 654893SN/A case DW_AT_name: 655893SN/A if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 656893SN/A name = form_value.AsCString(debug_str); 657893SN/A break; 658893SN/A 659893SN/A case DW_AT_declaration: 660893SN/A if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 661893SN/A is_declaration = form_value.Unsigned() != 0; 662893SN/A break; 663893SN/A 664893SN/A// case DW_AT_artificial: 665893SN/A// if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 666893SN/A// is_artificial = form_value.Unsigned() != 0; 667893SN/A// break; 668893SN/A 669893SN/A case DW_AT_MIPS_linkage_name: 670893SN/A case DW_AT_linkage_name: 671893SN/A if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 672893SN/A mangled_cstr = form_value.AsCString(debug_str); 673893SN/A break; 674893SN/A 675893SN/A case DW_AT_low_pc: 676893SN/A case DW_AT_high_pc: 677893SN/A case DW_AT_ranges: 678893SN/A has_address = true; 679893SN/A break; 680893SN/A 681893SN/A case DW_AT_entry_pc: 682893SN/A has_address = true; 683893SN/A break; 684893SN/A 685893SN/A case DW_AT_location: 686893SN/A has_location = true; 687893SN/A if (tag == DW_TAG_variable) 688893SN/A { 689893SN/A const DWARFDebugInfoEntry* parent_die = die.GetParent(); 690893SN/A while ( parent_die != NULL ) 691893SN/A { 692893SN/A switch (parent_die->Tag()) 693893SN/A { 694893SN/A case DW_TAG_subprogram: 695893SN/A case DW_TAG_lexical_block: 696893SN/A case DW_TAG_inlined_subroutine: 697893SN/A // Even if this is a function level static, we don't add it. We could theoretically 698893SN/A // add these if we wanted to by introspecting into the DW_AT_location and seeing 699893SN/A // if the location describes a hard coded address, but we dont want the performance 700893SN/A // penalty of that right now. 701893SN/A is_global_or_static_variable = false; 702893SN/A// if (attributes.ExtractFormValueAtIndex(dwarf2Data, i, form_value)) 703893SN/A// { 7043779SN/A// // If we have valid block data, then we have location expression bytes 7053779SN/A// // that are fixed (not a location list). 7063779SN/A// const uint8_t *block_data = form_value.BlockData(); 707893SN/A// if (block_data) 708893SN/A// { 7093471SN/A// uint32_t block_length = form_value.Unsigned(); 710893SN/A// if (block_length == 1 + attributes.CompileUnitAtIndex(i)->GetAddressByteSize()) 7113471SN/A// { 7123471SN/A// if (block_data[0] == DW_OP_addr) 7133471SN/A// add_die = true; 7143471SN/A// } 7153471SN/A// } 716893SN/A// } 717893SN/A parent_die = NULL; // Terminate the while loop. 718893SN/A break; 719893SN/A 720893SN/A case DW_TAG_compile_unit: 721893SN/A is_global_or_static_variable = true; 722893SN/A parent_die = NULL; // Terminate the while loop. 723893SN/A break; 724893SN/A 725893SN/A default: 726893SN/A parent_die = parent_die->GetParent(); // Keep going in the while loop. 727893SN/A break; 728893SN/A } 729893SN/A } 730893SN/A } 731893SN/A break; 732893SN/A 733893SN/A case DW_AT_specification: 734893SN/A if (attributes.ExtractFormValueAtIndex(m_dwarf2Data, i, form_value)) 7353779SN/A specification_die_offset = form_value.Reference(this); 7363779SN/A break; 7373779SN/A } 738893SN/A } 739893SN/A } 7403471SN/A 741893SN/A switch (tag) 742893SN/A { 743893SN/A case DW_TAG_subprogram: 7443471SN/A if (has_address) 7453471SN/A { 7463471SN/A if (name) 7473471SN/A { 7483471SN/A // Note, this check is also done in ParseMethodName, but since this is a hot loop, we do the 749893SN/A // simple inlined check outside the call. 750893SN/A ObjCLanguageRuntime::MethodName objc_method(name, true); 751893SN/A if (objc_method.IsValid(true)) 752893SN/A { 753893SN/A ConstString objc_class_name_with_category (objc_method.GetClassNameWithCategory()); 754893SN/A ConstString objc_selector_name (objc_method.GetSelector()); 755893SN/A ConstString objc_fullname_no_category_name (objc_method.GetFullNameWithoutCategory(true)); 756893SN/A ConstString objc_class_name_no_category (objc_method.GetClassName()); 757893SN/A func_fullnames.Insert (ConstString(name), die.GetOffset()); 758893SN/A if (objc_class_name_with_category) 759893SN/A objc_class_selectors.Insert(objc_class_name_with_category, die.GetOffset()); 760893SN/A if (objc_class_name_no_category && objc_class_name_no_category != objc_class_name_with_category) 761893SN/A objc_class_selectors.Insert(objc_class_name_no_category, die.GetOffset()); 762893SN/A if (objc_selector_name) 763893SN/A func_selectors.Insert (objc_selector_name, die.GetOffset()); 764893SN/A if (objc_fullname_no_category_name) 765893SN/A func_fullnames.Insert (objc_fullname_no_category_name, die.GetOffset()); 766893SN/A } 767893SN/A // If we have a mangled name, then the DW_AT_name attribute 768893SN/A // is usually the method name without the class or any parameters 769893SN/A const DWARFDebugInfoEntry *parent = die.GetParent(); 770893SN/A bool is_method = false; 771893SN/A if (parent) 772893SN/A { 773893SN/A dw_tag_t parent_tag = parent->Tag(); 774893SN/A if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) 775893SN/A { 776893SN/A is_method = true; 777893SN/A } 778893SN/A else 779893SN/A { 780893SN/A if (specification_die_offset != DW_INVALID_OFFSET) 781893SN/A { 782893SN/A const DWARFDebugInfoEntry *specification_die = m_dwarf2Data->DebugInfo()->GetDIEPtr (specification_die_offset, NULL); 783893SN/A if (specification_die) 784893SN/A { 785893SN/A parent = specification_die->GetParent(); 786893SN/A if (parent) 787893SN/A { 788893SN/A parent_tag = parent->Tag(); 789893SN/A 790893SN/A if (parent_tag == DW_TAG_class_type || parent_tag == DW_TAG_structure_type) 791893SN/A is_method = true; 792893SN/A } 793893SN/A } 794893SN/A } 795893SN/A } 796893SN/A } 797893SN/A 798893SN/A 799893SN/A if (is_method) 800893SN/A func_methods.Insert (ConstString(name), die.GetOffset()); 801893SN/A else 802893SN/A func_basenames.Insert (ConstString(name), die.GetOffset()); 803893SN/A 804893SN/A if (!is_method && !mangled_cstr && !objc_method.IsValid(true)) 805893SN/A func_fullnames.Insert (ConstString(name), die.GetOffset()); 806893SN/A } 807893SN/A if (mangled_cstr) 808893SN/A { 809893SN/A // Make sure our mangled name isn't the same string table entry 810893SN/A // as our name. If it starts with '_', then it is ok, else compare 811893SN/A // the string to make sure it isn't the same and we don't end up 812893SN/A // with duplicate entries 813893SN/A if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (name && ::strcmp(name, mangled_cstr) != 0))) 814893SN/A { 815893SN/A Mangled mangled (ConstString(mangled_cstr), true); 816893SN/A func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); 817893SN/A if (mangled.GetDemangledName()) 818893SN/A func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset()); 819893SN/A } 820893SN/A } 821893SN/A } 822893SN/A break; 823893SN/A 824893SN/A case DW_TAG_inlined_subroutine: 825893SN/A if (has_address) 826893SN/A { 827893SN/A if (name) 828893SN/A func_basenames.Insert (ConstString(name), die.GetOffset()); 829893SN/A if (mangled_cstr) 830893SN/A { 831893SN/A // Make sure our mangled name isn't the same string table entry 832893SN/A // as our name. If it starts with '_', then it is ok, else compare 833893SN/A // the string to make sure it isn't the same and we don't end up 83414168Sredestad // with duplicate entries 835893SN/A if (name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 836893SN/A { 837893SN/A Mangled mangled (ConstString(mangled_cstr), true); 838893SN/A func_fullnames.Insert (mangled.GetMangledName(), die.GetOffset()); 839893SN/A if (mangled.GetDemangledName()) 840893SN/A func_fullnames.Insert (mangled.GetDemangledName(), die.GetOffset()); 841893SN/A } 842893SN/A } 843893SN/A else 844893SN/A func_fullnames.Insert (ConstString(name), die.GetOffset()); 845893SN/A } 846893SN/A break; 847893SN/A 848893SN/A case DW_TAG_base_type: 849893SN/A case DW_TAG_class_type: 850893SN/A case DW_TAG_constant: 851893SN/A case DW_TAG_enumeration_type: 852893SN/A case DW_TAG_string_type: 853893SN/A case DW_TAG_subroutine_type: 854893SN/A case DW_TAG_structure_type: 855893SN/A case DW_TAG_union_type: 856893SN/A case DW_TAG_typedef: 857893SN/A case DW_TAG_unspecified_type: 858893SN/A if (name && is_declaration == false) 859893SN/A { 860893SN/A types.Insert (ConstString(name), die.GetOffset()); 861893SN/A } 862893SN/A break; 863893SN/A 864893SN/A case DW_TAG_namespace: 865893SN/A if (name) 866893SN/A namespaces.Insert (ConstString(name), die.GetOffset()); 867893SN/A break; 868893SN/A 869893SN/A case DW_TAG_variable: 870893SN/A if (name && has_location && is_global_or_static_variable) 871893SN/A { 872893SN/A globals.Insert (ConstString(name), die.GetOffset()); 873893SN/A // Be sure to include variables by their mangled and demangled 874893SN/A // names if they have any since a variable can have a basename 875893SN/A // "i", a mangled named "_ZN12_GLOBAL__N_11iE" and a demangled 876893SN/A // mangled name "(anonymous namespace)::i"... 877893SN/A 878893SN/A // Make sure our mangled name isn't the same string table entry 879893SN/A // as our name. If it starts with '_', then it is ok, else compare 880893SN/A // the string to make sure it isn't the same and we don't end up 881893SN/A // with duplicate entries 882893SN/A if (mangled_cstr && name != mangled_cstr && ((mangled_cstr[0] == '_') || (::strcmp(name, mangled_cstr) != 0))) 883893SN/A { 884893SN/A Mangled mangled (ConstString(mangled_cstr), true); 885893SN/A globals.Insert (mangled.GetMangledName(), die.GetOffset()); 886893SN/A if (mangled.GetDemangledName()) 887893SN/A globals.Insert (mangled.GetDemangledName(), die.GetOffset()); 888893SN/A } 8893899SN/A } 890893SN/A break; 8913899SN/A 892893SN/A default: 893893SN/A continue; 894893SN/A } 895893SN/A } 896893SN/A} 897893SN/A 898893SN/Abool 899893SN/ADWARFCompileUnit::Supports_unnamed_objc_bitfields () 900893SN/A{ 901893SN/A if (GetProducer() == eProducerClang) 902893SN/A { 903893SN/A const uint32_t major_version = GetProducerVersionMajor(); 904893SN/A if (major_version > 425 || (major_version == 425 && GetProducerVersionUpdate() >= 13)) 905893SN/A return true; 906893SN/A else 907893SN/A return false; 908893SN/A } 909893SN/A return true; // Assume all other compilers didn't have incorrect ObjC bitfield info 910893SN/A} 911893SN/A 912893SN/Abool 913893SN/ADWARFCompileUnit::Supports_DW_AT_APPLE_objc_complete_type () 914893SN/A{ 915893SN/A if (GetProducer() == eProducerLLVMGCC) 916893SN/A return false; 917893SN/A return true; 91814643Salanb} 919893SN/A 920893SN/Abool 921893SN/ADWARFCompileUnit::DW_AT_decl_file_attributes_are_invalid() 922893SN/A{ 923893SN/A // llvm-gcc makes completely invalid decl file attributes and won't ever 924893SN/A // be fixed, so we need to know to ignore these. 925893SN/A return GetProducer() == eProducerLLVMGCC; 926893SN/A} 927893SN/A 928893SN/Avoid 929893SN/ADWARFCompileUnit::ParseProducerInfo () 930893SN/A{ 931893SN/A m_producer_version_major = UINT32_MAX; 932893SN/A m_producer_version_minor = UINT32_MAX; 933 m_producer_version_update = UINT32_MAX; 934 935 const DWARFDebugInfoEntry *die = GetCompileUnitDIEOnly(); 936 if (die) 937 { 938 939 const char *producer_cstr = die->GetAttributeValueAsString(m_dwarf2Data, this, DW_AT_producer, NULL); 940 if (producer_cstr) 941 { 942 RegularExpression llvm_gcc_regex("^4\\.[012]\\.[01] \\(Based on Apple Inc\\. build [0-9]+\\) \\(LLVM build [\\.0-9]+\\)$"); 943 if (llvm_gcc_regex.Execute (producer_cstr)) 944 { 945 m_producer = eProducerLLVMGCC; 946 } 947 else if (strstr(producer_cstr, "clang")) 948 { 949 static RegularExpression g_clang_version_regex("clang-([0-9]+)\\.([0-9]+)\\.([0-9]+)"); 950 RegularExpression::Match regex_match(3); 951 if (g_clang_version_regex.Execute (producer_cstr, ®ex_match)) 952 { 953 std::string str; 954 if (regex_match.GetMatchAtIndex (producer_cstr, 1, str)) 955 m_producer_version_major = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); 956 if (regex_match.GetMatchAtIndex (producer_cstr, 2, str)) 957 m_producer_version_minor = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); 958 if (regex_match.GetMatchAtIndex (producer_cstr, 3, str)) 959 m_producer_version_update = Args::StringToUInt32(str.c_str(), UINT32_MAX, 10); 960 } 961 m_producer = eProducerClang; 962 } 963 else if (strstr(producer_cstr, "GNU")) 964 m_producer = eProducerGCC; 965 } 966 } 967 if (m_producer == eProducerInvalid) 968 m_producer = eProcucerOther; 969} 970 971DWARFCompileUnit::Producer 972DWARFCompileUnit::GetProducer () 973{ 974 if (m_producer == eProducerInvalid) 975 ParseProducerInfo (); 976 return m_producer; 977} 978 979 980uint32_t 981DWARFCompileUnit::GetProducerVersionMajor() 982{ 983 if (m_producer_version_major == 0) 984 ParseProducerInfo (); 985 return m_producer_version_major; 986} 987 988uint32_t 989DWARFCompileUnit::GetProducerVersionMinor() 990{ 991 if (m_producer_version_minor == 0) 992 ParseProducerInfo (); 993 return m_producer_version_minor; 994} 995 996uint32_t 997DWARFCompileUnit::GetProducerVersionUpdate() 998{ 999 if (m_producer_version_update == 0) 1000 ParseProducerInfo (); 1001 return m_producer_version_update; 1002} 1003 1004