1 //===-- DWARFCompileUnit.cpp ----------------------------------------------===// 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 "DWARFCompileUnit.h" 11 #include "DWARFContext.h" 12 #include "DWARFFormValue.h" 13 #include "llvm/Support/Dwarf.h" 14 #include "llvm/Support/Format.h" 15 #include "llvm/Support/raw_ostream.h" 16 using namespace llvm; 17 using namespace dwarf; 18 19 DataExtractor DWARFCompileUnit::getDebugInfoExtractor() const { 20 return DataExtractor(InfoSection, isLittleEndian, AddrSize); 21 } 22 23 bool DWARFCompileUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 24 clear(); 25 26 Offset = *offset_ptr; 27 28 if (debug_info.isValidOffset(*offset_ptr)) { 29 uint64_t abbrOffset; 30 Length = debug_info.getU32(offset_ptr); 31 Version = debug_info.getU16(offset_ptr); 32 abbrOffset = debug_info.getU32(offset_ptr); 33 AddrSize = debug_info.getU8(offset_ptr); 34 35 bool lengthOK = debug_info.isValidOffset(getNextCompileUnitOffset()-1); 36 bool versionOK = DWARFContext::isSupportedVersion(Version); 37 bool abbrOffsetOK = AbbrevSection.size() > abbrOffset; 38 bool addrSizeOK = AddrSize == 4 || AddrSize == 8; 39 40 if (lengthOK && versionOK && addrSizeOK && abbrOffsetOK && Abbrev != NULL) { 41 Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset); 42 return true; 43 } 44 45 // reset the offset to where we tried to parse from if anything went wrong 46 *offset_ptr = Offset; 47 } 48 49 return false; 50 } 51 52 uint32_t 53 DWARFCompileUnit::extract(uint32_t offset, DataExtractor debug_info_data, 54 const DWARFAbbreviationDeclarationSet *abbrevs) { 55 clear(); 56 57 Offset = offset; 58 59 if (debug_info_data.isValidOffset(offset)) { 60 Length = debug_info_data.getU32(&offset); 61 Version = debug_info_data.getU16(&offset); 62 bool abbrevsOK = debug_info_data.getU32(&offset) == abbrevs->getOffset(); 63 Abbrevs = abbrevs; 64 AddrSize = debug_info_data.getU8(&offset); 65 66 bool versionOK = DWARFContext::isSupportedVersion(Version); 67 bool addrSizeOK = AddrSize == 4 || AddrSize == 8; 68 69 if (versionOK && addrSizeOK && abbrevsOK && 70 debug_info_data.isValidOffset(offset)) 71 return offset; 72 } 73 return 0; 74 } 75 76 bool DWARFCompileUnit::extractRangeList(uint32_t RangeListOffset, 77 DWARFDebugRangeList &RangeList) const { 78 // Require that compile unit is extracted. 79 assert(DieArray.size() > 0); 80 DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); 81 return RangeList.extract(RangesData, &RangeListOffset); 82 } 83 84 void DWARFCompileUnit::clear() { 85 Offset = 0; 86 Length = 0; 87 Version = 0; 88 Abbrevs = 0; 89 AddrSize = 0; 90 BaseAddr = 0; 91 clearDIEs(false); 92 } 93 94 void DWARFCompileUnit::dump(raw_ostream &OS) { 95 OS << format("0x%08x", Offset) << ": Compile Unit:" 96 << " length = " << format("0x%08x", Length) 97 << " version = " << format("0x%04x", Version) 98 << " abbr_offset = " << format("0x%04x", Abbrevs->getOffset()) 99 << " addr_size = " << format("0x%02x", AddrSize) 100 << " (next CU at " << format("0x%08x", getNextCompileUnitOffset()) 101 << ")\n"; 102 103 const DWARFDebugInfoEntryMinimal *CU = getCompileUnitDIE(false); 104 assert(CU && "Null Compile Unit?"); 105 CU->dump(OS, this, -1U); 106 } 107 108 const char *DWARFCompileUnit::getCompilationDir() { 109 extractDIEsIfNeeded(true); 110 if (DieArray.empty()) 111 return 0; 112 return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); 113 } 114 115 void DWARFCompileUnit::setDIERelations() { 116 if (DieArray.empty()) 117 return; 118 DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); 119 DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); 120 DWARFDebugInfoEntryMinimal *curr_die; 121 // We purposely are skipping the last element in the array in the loop below 122 // so that we can always have a valid next item 123 for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { 124 // Since our loop doesn't include the last element, we can always 125 // safely access the next die in the array. 126 DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; 127 128 const DWARFAbbreviationDeclaration *curr_die_abbrev = 129 curr_die->getAbbreviationDeclarationPtr(); 130 131 if (curr_die_abbrev) { 132 // Normal DIE 133 if (curr_die_abbrev->hasChildren()) 134 next_die->setParent(curr_die); 135 else 136 curr_die->setSibling(next_die); 137 } else { 138 // NULL DIE that terminates a sibling chain 139 DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); 140 if (parent) 141 parent->setSibling(next_die); 142 } 143 } 144 145 // Since we skipped the last element, we need to fix it up! 146 if (die_array_begin < die_array_end) 147 curr_die->setParent(die_array_begin); 148 } 149 150 size_t DWARFCompileUnit::extractDIEsIfNeeded(bool cu_die_only) { 151 const size_t initial_die_array_size = DieArray.size(); 152 if ((cu_die_only && initial_die_array_size > 0) || 153 initial_die_array_size > 1) 154 return 0; // Already parsed 155 156 // Set the offset to that of the first DIE and calculate the start of the 157 // next compilation unit header. 158 uint32_t offset = getFirstDIEOffset(); 159 uint32_t next_cu_offset = getNextCompileUnitOffset(); 160 161 DWARFDebugInfoEntryMinimal die; 162 // Keep a flat array of the DIE for binary lookup by DIE offset 163 uint32_t depth = 0; 164 // We are in our compile unit, parse starting at the offset 165 // we were told to parse 166 167 const uint8_t *fixed_form_sizes = 168 DWARFFormValue::getFixedFormSizesForAddressSize(getAddressByteSize()); 169 170 while (offset < next_cu_offset && 171 die.extractFast(this, fixed_form_sizes, &offset)) { 172 173 if (depth == 0) { 174 uint64_t base_addr = 175 die.getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U); 176 if (base_addr == -1U) 177 base_addr = die.getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0); 178 setBaseAddress(base_addr); 179 } 180 181 if (cu_die_only) { 182 addDIE(die); 183 return 1; 184 } 185 else if (depth == 0 && initial_die_array_size == 1) 186 // Don't append the CU die as we already did that 187 ; 188 else 189 addDIE(die); 190 191 const DWARFAbbreviationDeclaration *abbrDecl = 192 die.getAbbreviationDeclarationPtr(); 193 if (abbrDecl) { 194 // Normal DIE 195 if (abbrDecl->hasChildren()) 196 ++depth; 197 } else { 198 // NULL DIE. 199 if (depth > 0) 200 --depth; 201 if (depth == 0) 202 break; // We are done with this compile unit! 203 } 204 205 } 206 207 // Give a little bit of info if we encounter corrupt DWARF (our offset 208 // should always terminate at or before the start of the next compilation 209 // unit header). 210 if (offset > next_cu_offset) 211 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 212 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), offset); 213 214 setDIERelations(); 215 return DieArray.size(); 216 } 217 218 void DWARFCompileUnit::clearDIEs(bool keep_compile_unit_die) { 219 if (DieArray.size() > (unsigned)keep_compile_unit_die) { 220 // std::vectors never get any smaller when resized to a smaller size, 221 // or when clear() or erase() are called, the size will report that it 222 // is smaller, but the memory allocated remains intact (call capacity() 223 // to see this). So we need to create a temporary vector and swap the 224 // contents which will cause just the internal pointers to be swapped 225 // so that when "tmp_array" goes out of scope, it will destroy the 226 // contents. 227 228 // Save at least the compile unit DIE 229 std::vector<DWARFDebugInfoEntryMinimal> tmpArray; 230 DieArray.swap(tmpArray); 231 if (keep_compile_unit_die) 232 DieArray.push_back(tmpArray.front()); 233 } 234 } 235 236 void 237 DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, 238 bool clear_dies_if_already_not_parsed){ 239 // This function is usually called if there in no .debug_aranges section 240 // in order to produce a compile unit level set of address ranges that 241 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 242 // all compile units to stay loaded when they weren't needed. So we can end 243 // up parsing the DWARF and then throwing them all away to keep memory usage 244 // down. 245 const bool clear_dies = extractDIEsIfNeeded(false) > 1 && 246 clear_dies_if_already_not_parsed; 247 DieArray[0].buildAddressRangeTable(this, debug_aranges); 248 249 // Keep memory down by clearing DIEs if this generate function 250 // caused them to be parsed. 251 if (clear_dies) 252 clearDIEs(true); 253 } 254 255 DWARFDebugInfoEntryMinimal::InlinedChain 256 DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) { 257 // First, find a subprogram that contains the given address (the root 258 // of inlined chain). 259 extractDIEsIfNeeded(false); 260 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0; 261 for (size_t i = 0, n = DieArray.size(); i != n; i++) { 262 if (DieArray[i].isSubprogramDIE() && 263 DieArray[i].addressRangeContainsAddress(this, Address)) { 264 SubprogramDIE = &DieArray[i]; 265 break; 266 } 267 } 268 // Get inlined chain rooted at this subprogram DIE. 269 if (!SubprogramDIE) 270 return DWARFDebugInfoEntryMinimal::InlinedChain(); 271 return SubprogramDIE->getInlinedChainForAddress(this, Address); 272 } 273