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 "llvm/DebugInfo/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 void DWARFCompileUnit::extractDIEsToVector( 151 bool AppendCUDie, bool AppendNonCUDies, 152 std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { 153 if (!AppendCUDie && !AppendNonCUDies) 154 return; 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 NextCUOffset = getNextCompileUnitOffset(); 160 DWARFDebugInfoEntryMinimal DIE; 161 uint32_t Depth = 0; 162 const uint8_t *FixedFormSizes = 163 DWARFFormValue::getFixedFormSizes(getAddressByteSize(), getVersion()); 164 bool IsCUDie = true; 165 166 while (Offset < NextCUOffset && 167 DIE.extractFast(this, FixedFormSizes, &Offset)) { 168 if (IsCUDie) { 169 if (AppendCUDie) 170 Dies.push_back(DIE); 171 if (!AppendNonCUDies) 172 break; 173 // The average bytes per DIE entry has been seen to be 174 // around 14-20 so let's pre-reserve the needed memory for 175 // our DIE entries accordingly. 176 Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 177 IsCUDie = false; 178 } else { 179 Dies.push_back(DIE); 180 } 181 182 const DWARFAbbreviationDeclaration *AbbrDecl = 183 DIE.getAbbreviationDeclarationPtr(); 184 if (AbbrDecl) { 185 // Normal DIE 186 if (AbbrDecl->hasChildren()) 187 ++Depth; 188 } else { 189 // NULL DIE. 190 if (Depth > 0) 191 --Depth; 192 if (Depth == 0) 193 break; // We are done with this compile unit! 194 } 195 } 196 197 // Give a little bit of info if we encounter corrupt DWARF (our offset 198 // should always terminate at or before the start of the next compilation 199 // unit header). 200 if (Offset > NextCUOffset) 201 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 202 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset); 203 } 204 205 size_t DWARFCompileUnit::extractDIEsIfNeeded(bool CUDieOnly) { 206 if ((CUDieOnly && DieArray.size() > 0) || 207 DieArray.size() > 1) 208 return 0; // Already parsed. 209 210 extractDIEsToVector(DieArray.empty(), !CUDieOnly, DieArray); 211 212 // Set the base address of current compile unit. 213 if (!DieArray.empty()) { 214 uint64_t BaseAddr = 215 DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_low_pc, -1U); 216 if (BaseAddr == -1U) 217 BaseAddr = DieArray[0].getAttributeValueAsUnsigned(this, DW_AT_entry_pc, 0); 218 setBaseAddress(BaseAddr); 219 } 220 221 setDIERelations(); 222 return DieArray.size(); 223 } 224 225 void DWARFCompileUnit::clearDIEs(bool KeepCUDie) { 226 if (DieArray.size() > (unsigned)KeepCUDie) { 227 // std::vectors never get any smaller when resized to a smaller size, 228 // or when clear() or erase() are called, the size will report that it 229 // is smaller, but the memory allocated remains intact (call capacity() 230 // to see this). So we need to create a temporary vector and swap the 231 // contents which will cause just the internal pointers to be swapped 232 // so that when temporary vector goes out of scope, it will destroy the 233 // contents. 234 std::vector<DWARFDebugInfoEntryMinimal> TmpArray; 235 DieArray.swap(TmpArray); 236 // Save at least the compile unit DIE 237 if (KeepCUDie) 238 DieArray.push_back(TmpArray.front()); 239 } 240 } 241 242 void 243 DWARFCompileUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, 244 bool clear_dies_if_already_not_parsed){ 245 // This function is usually called if there in no .debug_aranges section 246 // in order to produce a compile unit level set of address ranges that 247 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 248 // all compile units to stay loaded when they weren't needed. So we can end 249 // up parsing the DWARF and then throwing them all away to keep memory usage 250 // down. 251 const bool clear_dies = extractDIEsIfNeeded(false) > 1 && 252 clear_dies_if_already_not_parsed; 253 DieArray[0].buildAddressRangeTable(this, debug_aranges); 254 255 // Keep memory down by clearing DIEs if this generate function 256 // caused them to be parsed. 257 if (clear_dies) 258 clearDIEs(true); 259 } 260 261 DWARFDebugInfoEntryInlinedChain 262 DWARFCompileUnit::getInlinedChainForAddress(uint64_t Address) { 263 // First, find a subprogram that contains the given address (the root 264 // of inlined chain). 265 extractDIEsIfNeeded(false); 266 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 0; 267 for (size_t i = 0, n = DieArray.size(); i != n; i++) { 268 if (DieArray[i].isSubprogramDIE() && 269 DieArray[i].addressRangeContainsAddress(this, Address)) { 270 SubprogramDIE = &DieArray[i]; 271 break; 272 } 273 } 274 // Get inlined chain rooted at this subprogram DIE. 275 if (!SubprogramDIE) 276 return DWARFDebugInfoEntryInlinedChain(); 277 return SubprogramDIE->getInlinedChainForAddress(this, Address); 278 } 279