1 //===-- DWARFUnit.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 "llvm/DebugInfo/DWARF/DWARFUnit.h" 11 #include "llvm/DebugInfo/DWARF/DWARFContext.h" 12 #include "llvm/DebugInfo/DWARF/DWARFFormValue.h" 13 #include "llvm/Support/Dwarf.h" 14 #include "llvm/Support/Path.h" 15 #include <cstdio> 16 17 namespace llvm { 18 using namespace dwarf; 19 20 void DWARFUnitSectionBase::parse(DWARFContext &C, const DWARFSection &Section) { 21 parseImpl(C, Section, C.getDebugAbbrev(), C.getRangeSection(), 22 C.getStringSection(), StringRef(), C.getAddrSection(), 23 C.getLineSection().Data, C.isLittleEndian()); 24 } 25 26 void DWARFUnitSectionBase::parseDWO(DWARFContext &C, 27 const DWARFSection &DWOSection, 28 DWARFUnitIndex *Index) { 29 parseImpl(C, DWOSection, C.getDebugAbbrevDWO(), C.getRangeDWOSection(), 30 C.getStringDWOSection(), C.getStringOffsetDWOSection(), 31 C.getAddrSection(), C.getLineDWOSection().Data, C.isLittleEndian()); 32 } 33 34 DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFSection &Section, 35 const DWARFDebugAbbrev *DA, StringRef RS, StringRef SS, 36 StringRef SOS, StringRef AOS, StringRef LS, bool LE, 37 const DWARFUnitSectionBase &UnitSection, 38 const DWARFUnitIndex::Entry *IndexEntry) 39 : Context(DC), InfoSection(Section), Abbrev(DA), RangeSection(RS), 40 LineSection(LS), StringSection(SS), StringOffsetSection([&]() { 41 if (IndexEntry) 42 if (const auto *C = IndexEntry->getOffset(DW_SECT_STR_OFFSETS)) 43 return SOS.slice(C->Offset, C->Offset + C->Length); 44 return SOS; 45 }()), 46 AddrOffsetSection(AOS), isLittleEndian(LE), UnitSection(UnitSection), 47 IndexEntry(IndexEntry) { 48 clear(); 49 } 50 51 DWARFUnit::~DWARFUnit() { 52 } 53 54 bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, 55 uint64_t &Result) const { 56 uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; 57 if (AddrOffsetSection.size() < Offset + AddrSize) 58 return false; 59 DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize); 60 Result = DA.getAddress(&Offset); 61 return true; 62 } 63 64 bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, 65 uint32_t &Result) const { 66 // FIXME: string offset section entries are 8-byte for DWARF64. 67 const uint32_t ItemSize = 4; 68 uint32_t Offset = Index * ItemSize; 69 if (StringOffsetSection.size() < Offset + ItemSize) 70 return false; 71 DataExtractor DA(StringOffsetSection, isLittleEndian, 0); 72 Result = DA.getU32(&Offset); 73 return true; 74 } 75 76 bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { 77 Length = debug_info.getU32(offset_ptr); 78 Version = debug_info.getU16(offset_ptr); 79 uint64_t AbbrOffset = debug_info.getU32(offset_ptr); 80 if (IndexEntry) { 81 if (AbbrOffset) 82 return false; 83 auto *UnitContrib = IndexEntry->getOffset(); 84 if (!UnitContrib || UnitContrib->Length != (Length + 4)) 85 return false; 86 auto *AbbrEntry = IndexEntry->getOffset(DW_SECT_ABBREV); 87 if (!AbbrEntry) 88 return false; 89 AbbrOffset = AbbrEntry->Offset; 90 } 91 AddrSize = debug_info.getU8(offset_ptr); 92 93 bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); 94 bool VersionOK = DWARFContext::isSupportedVersion(Version); 95 bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; 96 97 if (!LengthOK || !VersionOK || !AddrSizeOK) 98 return false; 99 100 Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); 101 return Abbrevs != nullptr; 102 } 103 104 bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 105 clear(); 106 107 Offset = *offset_ptr; 108 109 if (debug_info.isValidOffset(*offset_ptr)) { 110 if (extractImpl(debug_info, offset_ptr)) 111 return true; 112 113 // reset the offset to where we tried to parse from if anything went wrong 114 *offset_ptr = Offset; 115 } 116 117 return false; 118 } 119 120 bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, 121 DWARFDebugRangeList &RangeList) const { 122 // Require that compile unit is extracted. 123 assert(DieArray.size() > 0); 124 DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); 125 uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 126 return RangeList.extract(RangesData, &ActualRangeListOffset); 127 } 128 129 void DWARFUnit::clear() { 130 Offset = 0; 131 Length = 0; 132 Version = 0; 133 Abbrevs = nullptr; 134 AddrSize = 0; 135 BaseAddr = 0; 136 RangeSectionBase = 0; 137 AddrOffsetSectionBase = 0; 138 clearDIEs(false); 139 DWO.reset(); 140 } 141 142 const char *DWARFUnit::getCompilationDir() { 143 extractDIEsIfNeeded(true); 144 if (DieArray.empty()) 145 return nullptr; 146 return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); 147 } 148 149 uint64_t DWARFUnit::getDWOId() { 150 extractDIEsIfNeeded(true); 151 const uint64_t FailValue = -1ULL; 152 if (DieArray.empty()) 153 return FailValue; 154 return DieArray[0] 155 .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); 156 } 157 158 void DWARFUnit::setDIERelations() { 159 if (DieArray.size() <= 1) 160 return; 161 162 std::vector<DWARFDebugInfoEntryMinimal *> ParentChain; 163 DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; 164 for (auto &DIE : DieArray) { 165 if (SiblingChain) { 166 SiblingChain->setSibling(&DIE); 167 } 168 if (const DWARFAbbreviationDeclaration *AbbrDecl = 169 DIE.getAbbreviationDeclarationPtr()) { 170 // Normal DIE. 171 if (AbbrDecl->hasChildren()) { 172 ParentChain.push_back(&DIE); 173 SiblingChain = nullptr; 174 } else { 175 SiblingChain = &DIE; 176 } 177 } else { 178 // NULL entry terminates the sibling chain. 179 SiblingChain = ParentChain.back(); 180 ParentChain.pop_back(); 181 } 182 } 183 assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); 184 assert(ParentChain.empty()); 185 } 186 187 void DWARFUnit::extractDIEsToVector( 188 bool AppendCUDie, bool AppendNonCUDies, 189 std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { 190 if (!AppendCUDie && !AppendNonCUDies) 191 return; 192 193 // Set the offset to that of the first DIE and calculate the start of the 194 // next compilation unit header. 195 uint32_t DIEOffset = Offset + getHeaderSize(); 196 uint32_t NextCUOffset = getNextUnitOffset(); 197 DWARFDebugInfoEntryMinimal DIE; 198 uint32_t Depth = 0; 199 bool IsCUDie = true; 200 201 while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { 202 if (IsCUDie) { 203 if (AppendCUDie) 204 Dies.push_back(DIE); 205 if (!AppendNonCUDies) 206 break; 207 // The average bytes per DIE entry has been seen to be 208 // around 14-20 so let's pre-reserve the needed memory for 209 // our DIE entries accordingly. 210 Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 211 IsCUDie = false; 212 } else { 213 Dies.push_back(DIE); 214 } 215 216 if (const DWARFAbbreviationDeclaration *AbbrDecl = 217 DIE.getAbbreviationDeclarationPtr()) { 218 // Normal DIE 219 if (AbbrDecl->hasChildren()) 220 ++Depth; 221 } else { 222 // NULL DIE. 223 if (Depth > 0) 224 --Depth; 225 if (Depth == 0) 226 break; // We are done with this compile unit! 227 } 228 } 229 230 // Give a little bit of info if we encounter corrupt DWARF (our offset 231 // should always terminate at or before the start of the next compilation 232 // unit header). 233 if (DIEOffset > NextCUOffset) 234 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 235 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); 236 } 237 238 size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 239 if ((CUDieOnly && DieArray.size() > 0) || 240 DieArray.size() > 1) 241 return 0; // Already parsed. 242 243 bool HasCUDie = DieArray.size() > 0; 244 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 245 246 if (DieArray.empty()) 247 return 0; 248 249 // If CU DIE was just parsed, copy several attribute values from it. 250 if (!HasCUDie) { 251 uint64_t BaseAddr = 252 DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); 253 if (BaseAddr == -1ULL) 254 BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); 255 setBaseAddress(BaseAddr); 256 AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 257 this, DW_AT_GNU_addr_base, 0); 258 RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 259 this, DW_AT_ranges_base, 0); 260 // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 261 // skeleton CU DIE, so that DWARF users not aware of it are not broken. 262 } 263 264 setDIERelations(); 265 return DieArray.size(); 266 } 267 268 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) 269 : DWOFile(), DWOContext(), DWOU(nullptr) { 270 auto Obj = object::ObjectFile::createObjectFile(DWOPath); 271 if (!Obj) 272 return; 273 DWOFile = std::move(Obj.get()); 274 DWOContext.reset( 275 cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary()))); 276 if (DWOContext->getNumDWOCompileUnits() > 0) 277 DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 278 } 279 280 bool DWARFUnit::parseDWO() { 281 if (DWO.get()) 282 return false; 283 extractDIEsIfNeeded(true); 284 if (DieArray.empty()) 285 return false; 286 const char *DWOFileName = 287 DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); 288 if (!DWOFileName) 289 return false; 290 const char *CompilationDir = 291 DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); 292 SmallString<16> AbsolutePath; 293 if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { 294 sys::path::append(AbsolutePath, CompilationDir); 295 } 296 sys::path::append(AbsolutePath, DWOFileName); 297 DWO = llvm::make_unique<DWOHolder>(AbsolutePath); 298 DWARFUnit *DWOCU = DWO->getUnit(); 299 // Verify that compile unit in .dwo file is valid. 300 if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { 301 DWO.reset(); 302 return false; 303 } 304 // Share .debug_addr and .debug_ranges section with compile unit in .dwo 305 DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 306 uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); 307 DWOCU->setRangesSection(RangeSection, DWORangesBase); 308 return true; 309 } 310 311 void DWARFUnit::clearDIEs(bool KeepCUDie) { 312 if (DieArray.size() > (unsigned)KeepCUDie) { 313 // std::vectors never get any smaller when resized to a smaller size, 314 // or when clear() or erase() are called, the size will report that it 315 // is smaller, but the memory allocated remains intact (call capacity() 316 // to see this). So we need to create a temporary vector and swap the 317 // contents which will cause just the internal pointers to be swapped 318 // so that when temporary vector goes out of scope, it will destroy the 319 // contents. 320 std::vector<DWARFDebugInfoEntryMinimal> TmpArray; 321 DieArray.swap(TmpArray); 322 // Save at least the compile unit DIE 323 if (KeepCUDie) 324 DieArray.push_back(TmpArray.front()); 325 } 326 } 327 328 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { 329 const auto *U = getUnitDIE(); 330 if (U == nullptr) 331 return; 332 // First, check if unit DIE describes address ranges for the whole unit. 333 const auto &CUDIERanges = U->getAddressRanges(this); 334 if (!CUDIERanges.empty()) { 335 CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); 336 return; 337 } 338 339 // This function is usually called if there in no .debug_aranges section 340 // in order to produce a compile unit level set of address ranges that 341 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 342 // all compile units to stay loaded when they weren't needed. So we can end 343 // up parsing the DWARF and then throwing them all away to keep memory usage 344 // down. 345 const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; 346 DieArray[0].collectChildrenAddressRanges(this, CURanges); 347 348 // Collect address ranges from DIEs in .dwo if necessary. 349 bool DWOCreated = parseDWO(); 350 if (DWO.get()) 351 DWO->getUnit()->collectAddressRanges(CURanges); 352 if (DWOCreated) 353 DWO.reset(); 354 355 // Keep memory down by clearing DIEs if this generate function 356 // caused them to be parsed. 357 if (ClearDIEs) 358 clearDIEs(true); 359 } 360 361 const DWARFDebugInfoEntryMinimal * 362 DWARFUnit::getSubprogramForAddress(uint64_t Address) { 363 extractDIEsIfNeeded(false); 364 for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { 365 if (DIE.isSubprogramDIE() && 366 DIE.addressRangeContainsAddress(this, Address)) { 367 return &DIE; 368 } 369 } 370 return nullptr; 371 } 372 373 DWARFDebugInfoEntryInlinedChain 374 DWARFUnit::getInlinedChainForAddress(uint64_t Address) { 375 // First, find a subprogram that contains the given address (the root 376 // of inlined chain). 377 const DWARFUnit *ChainCU = nullptr; 378 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 379 getSubprogramForAddress(Address); 380 if (SubprogramDIE) { 381 ChainCU = this; 382 } else { 383 // Try to look for subprogram DIEs in the DWO file. 384 parseDWO(); 385 if (DWO.get()) { 386 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 387 if (SubprogramDIE) 388 ChainCU = DWO->getUnit(); 389 } 390 } 391 392 // Get inlined chain rooted at this subprogram DIE. 393 if (!SubprogramDIE) 394 return DWARFDebugInfoEntryInlinedChain(); 395 return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); 396 } 397 398 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, 399 DWARFSectionKind Kind) { 400 if (Kind == DW_SECT_INFO) 401 return Context.getCUIndex(); 402 assert(Kind == DW_SECT_TYPES); 403 return Context.getTUIndex(); 404 } 405 } 406