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 // TODO: Actually report errors helpfully. 273 consumeError(Obj.takeError()); 274 return; 275 } 276 DWOFile = std::move(Obj.get()); 277 DWOContext.reset( 278 cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary()))); 279 if (DWOContext->getNumDWOCompileUnits() > 0) 280 DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 281 } 282 283 bool DWARFUnit::parseDWO() { 284 if (DWO.get()) 285 return false; 286 extractDIEsIfNeeded(true); 287 if (DieArray.empty()) 288 return false; 289 const char *DWOFileName = 290 DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); 291 if (!DWOFileName) 292 return false; 293 const char *CompilationDir = 294 DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); 295 SmallString<16> AbsolutePath; 296 if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { 297 sys::path::append(AbsolutePath, CompilationDir); 298 } 299 sys::path::append(AbsolutePath, DWOFileName); 300 DWO = llvm::make_unique<DWOHolder>(AbsolutePath); 301 DWARFUnit *DWOCU = DWO->getUnit(); 302 // Verify that compile unit in .dwo file is valid. 303 if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { 304 DWO.reset(); 305 return false; 306 } 307 // Share .debug_addr and .debug_ranges section with compile unit in .dwo 308 DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 309 uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); 310 DWOCU->setRangesSection(RangeSection, DWORangesBase); 311 return true; 312 } 313 314 void DWARFUnit::clearDIEs(bool KeepCUDie) { 315 if (DieArray.size() > (unsigned)KeepCUDie) { 316 // std::vectors never get any smaller when resized to a smaller size, 317 // or when clear() or erase() are called, the size will report that it 318 // is smaller, but the memory allocated remains intact (call capacity() 319 // to see this). So we need to create a temporary vector and swap the 320 // contents which will cause just the internal pointers to be swapped 321 // so that when temporary vector goes out of scope, it will destroy the 322 // contents. 323 std::vector<DWARFDebugInfoEntryMinimal> TmpArray; 324 DieArray.swap(TmpArray); 325 // Save at least the compile unit DIE 326 if (KeepCUDie) 327 DieArray.push_back(TmpArray.front()); 328 } 329 } 330 331 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { 332 const auto *U = getUnitDIE(); 333 if (U == nullptr) 334 return; 335 // First, check if unit DIE describes address ranges for the whole unit. 336 const auto &CUDIERanges = U->getAddressRanges(this); 337 if (!CUDIERanges.empty()) { 338 CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); 339 return; 340 } 341 342 // This function is usually called if there in no .debug_aranges section 343 // in order to produce a compile unit level set of address ranges that 344 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 345 // all compile units to stay loaded when they weren't needed. So we can end 346 // up parsing the DWARF and then throwing them all away to keep memory usage 347 // down. 348 const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; 349 DieArray[0].collectChildrenAddressRanges(this, CURanges); 350 351 // Collect address ranges from DIEs in .dwo if necessary. 352 bool DWOCreated = parseDWO(); 353 if (DWO.get()) 354 DWO->getUnit()->collectAddressRanges(CURanges); 355 if (DWOCreated) 356 DWO.reset(); 357 358 // Keep memory down by clearing DIEs if this generate function 359 // caused them to be parsed. 360 if (ClearDIEs) 361 clearDIEs(true); 362 } 363 364 const DWARFDebugInfoEntryMinimal * 365 DWARFUnit::getSubprogramForAddress(uint64_t Address) { 366 extractDIEsIfNeeded(false); 367 for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { 368 if (DIE.isSubprogramDIE() && 369 DIE.addressRangeContainsAddress(this, Address)) { 370 return &DIE; 371 } 372 } 373 return nullptr; 374 } 375 376 DWARFDebugInfoEntryInlinedChain 377 DWARFUnit::getInlinedChainForAddress(uint64_t Address) { 378 // First, find a subprogram that contains the given address (the root 379 // of inlined chain). 380 const DWARFUnit *ChainCU = nullptr; 381 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 382 getSubprogramForAddress(Address); 383 if (SubprogramDIE) { 384 ChainCU = this; 385 } else { 386 // Try to look for subprogram DIEs in the DWO file. 387 parseDWO(); 388 if (DWO.get()) { 389 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 390 if (SubprogramDIE) 391 ChainCU = DWO->getUnit(); 392 } 393 } 394 395 // Get inlined chain rooted at this subprogram DIE. 396 if (!SubprogramDIE) 397 return DWARFDebugInfoEntryInlinedChain(); 398 return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); 399 } 400 401 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, 402 DWARFSectionKind Kind) { 403 if (Kind == DW_SECT_INFO) 404 return Context.getCUIndex(); 405 assert(Kind == DW_SECT_TYPES); 406 return Context.getTUIndex(); 407 } 408 } 409