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