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 return getUnitDIE().getAttributeValueAsString(DW_AT_comp_dir, nullptr); 155 } 156 157 Optional<uint64_t> DWARFUnit::getDWOId() { 158 return getUnitDIE().getAttributeValueAsUnsignedConstant(DW_AT_GNU_dwo_id); 159 } 160 161 void DWARFUnit::extractDIEsToVector( 162 bool AppendCUDie, bool AppendNonCUDies, 163 std::vector<DWARFDebugInfoEntry> &Dies) const { 164 if (!AppendCUDie && !AppendNonCUDies) 165 return; 166 167 // Set the offset to that of the first DIE and calculate the start of the 168 // next compilation unit header. 169 uint32_t DIEOffset = Offset + getHeaderSize(); 170 uint32_t NextCUOffset = getNextUnitOffset(); 171 DWARFDebugInfoEntry DIE; 172 DataExtractor DebugInfoData = getDebugInfoExtractor(); 173 uint32_t Depth = 0; 174 bool IsCUDie = true; 175 176 while (DIE.extractFast(*this, &DIEOffset, DebugInfoData, NextCUOffset, 177 Depth)) { 178 if (IsCUDie) { 179 if (AppendCUDie) 180 Dies.push_back(DIE); 181 if (!AppendNonCUDies) 182 break; 183 // The average bytes per DIE entry has been seen to be 184 // around 14-20 so let's pre-reserve the needed memory for 185 // our DIE entries accordingly. 186 Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 187 IsCUDie = false; 188 } else { 189 Dies.push_back(DIE); 190 } 191 192 if (const DWARFAbbreviationDeclaration *AbbrDecl = 193 DIE.getAbbreviationDeclarationPtr()) { 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 // Give a little bit of info if we encounter corrupt DWARF (our offset 207 // should always terminate at or before the start of the next compilation 208 // unit header). 209 if (DIEOffset > NextCUOffset) 210 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 211 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); 212 } 213 214 size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 215 if ((CUDieOnly && !DieArray.empty()) || 216 DieArray.size() > 1) 217 return 0; // Already parsed. 218 219 bool HasCUDie = !DieArray.empty(); 220 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 221 222 if (DieArray.empty()) 223 return 0; 224 225 // If CU DIE was just parsed, copy several attribute values from it. 226 if (!HasCUDie) { 227 DWARFDie UnitDie = getUnitDIE(); 228 auto BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_low_pc); 229 if (!BaseAddr) 230 BaseAddr = UnitDie.getAttributeValueAsAddress(DW_AT_entry_pc); 231 if (BaseAddr) 232 setBaseAddress(*BaseAddr); 233 AddrOffsetSectionBase = UnitDie.getAttributeValueAsSectionOffset( 234 DW_AT_GNU_addr_base, 0); 235 RangeSectionBase = UnitDie.getAttributeValueAsSectionOffset( 236 DW_AT_rnglists_base, 0); 237 // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 238 // skeleton CU DIE, so that DWARF users not aware of it are not broken. 239 } 240 241 return DieArray.size(); 242 } 243 244 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) 245 : DWOU(nullptr) { 246 auto Obj = object::ObjectFile::createObjectFile(DWOPath); 247 if (!Obj) { 248 // TODO: Actually report errors helpfully. 249 consumeError(Obj.takeError()); 250 return; 251 } 252 DWOFile = std::move(Obj.get()); 253 DWOContext.reset( 254 cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary()))); 255 if (DWOContext->getNumDWOCompileUnits() > 0) 256 DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 257 } 258 259 bool DWARFUnit::parseDWO() { 260 if (isDWO) 261 return false; 262 if (DWO.get()) 263 return false; 264 DWARFDie UnitDie = getUnitDIE(); 265 if (!UnitDie) 266 return false; 267 const char *DWOFileName = 268 UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); 269 if (!DWOFileName) 270 return false; 271 const char *CompilationDir = 272 UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); 273 SmallString<16> AbsolutePath; 274 if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { 275 sys::path::append(AbsolutePath, CompilationDir); 276 } 277 sys::path::append(AbsolutePath, DWOFileName); 278 DWO = llvm::make_unique<DWOHolder>(AbsolutePath); 279 DWARFUnit *DWOCU = DWO->getUnit(); 280 // Verify that compile unit in .dwo file is valid. 281 if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { 282 DWO.reset(); 283 return false; 284 } 285 // Share .debug_addr and .debug_ranges section with compile unit in .dwo 286 DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 287 auto DWORangesBase = UnitDie.getRangesBaseAttribute(); 288 DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); 289 return true; 290 } 291 292 void DWARFUnit::clearDIEs(bool KeepCUDie) { 293 if (DieArray.size() > (unsigned)KeepCUDie) { 294 // std::vectors never get any smaller when resized to a smaller size, 295 // or when clear() or erase() are called, the size will report that it 296 // is smaller, but the memory allocated remains intact (call capacity() 297 // to see this). So we need to create a temporary vector and swap the 298 // contents which will cause just the internal pointers to be swapped 299 // so that when temporary vector goes out of scope, it will destroy the 300 // contents. 301 std::vector<DWARFDebugInfoEntry> TmpArray; 302 DieArray.swap(TmpArray); 303 // Save at least the compile unit DIE 304 if (KeepCUDie) 305 DieArray.push_back(TmpArray.front()); 306 } 307 } 308 309 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { 310 DWARFDie UnitDie = getUnitDIE(); 311 if (!UnitDie) 312 return; 313 // First, check if unit DIE describes address ranges for the whole unit. 314 const auto &CUDIERanges = UnitDie.getAddressRanges(); 315 if (!CUDIERanges.empty()) { 316 CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); 317 return; 318 } 319 320 // This function is usually called if there in no .debug_aranges section 321 // in order to produce a compile unit level set of address ranges that 322 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 323 // all compile units to stay loaded when they weren't needed. So we can end 324 // up parsing the DWARF and then throwing them all away to keep memory usage 325 // down. 326 const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; 327 getUnitDIE().collectChildrenAddressRanges(CURanges); 328 329 // Collect address ranges from DIEs in .dwo if necessary. 330 bool DWOCreated = parseDWO(); 331 if (DWO.get()) 332 DWO->getUnit()->collectAddressRanges(CURanges); 333 if (DWOCreated) 334 DWO.reset(); 335 336 // Keep memory down by clearing DIEs if this generate function 337 // caused them to be parsed. 338 if (ClearDIEs) 339 clearDIEs(true); 340 } 341 342 DWARFDie 343 DWARFUnit::getSubprogramForAddress(uint64_t Address) { 344 extractDIEsIfNeeded(false); 345 for (const DWARFDebugInfoEntry &D : DieArray) { 346 DWARFDie DIE(this, &D); 347 if (DIE.isSubprogramDIE() && 348 DIE.addressRangeContainsAddress(Address)) { 349 return DIE; 350 } 351 } 352 return DWARFDie(); 353 } 354 355 void 356 DWARFUnit::getInlinedChainForAddress(uint64_t Address, 357 SmallVectorImpl<DWARFDie> &InlinedChain) { 358 // First, find a subprogram that contains the given address (the root 359 // of inlined chain). 360 DWARFDie SubprogramDIE; 361 // Try to look for subprogram DIEs in the DWO file. 362 parseDWO(); 363 if (DWO) 364 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 365 else 366 SubprogramDIE = getSubprogramForAddress(Address); 367 368 // Get inlined chain rooted at this subprogram DIE. 369 if (SubprogramDIE) 370 SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain); 371 else 372 InlinedChain.clear(); 373 } 374 375 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, 376 DWARFSectionKind Kind) { 377 if (Kind == DW_SECT_INFO) 378 return Context.getCUIndex(); 379 assert(Kind == DW_SECT_TYPES); 380 return Context.getTUIndex(); 381 } 382 383 DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { 384 if (!Die) 385 return DWARFDie(); 386 const uint32_t Depth = Die->getDepth(); 387 // Unit DIEs always have a depth of zero and never have parents. 388 if (Depth == 0) 389 return DWARFDie(); 390 // Depth of 1 always means parent is the compile/type unit. 391 if (Depth == 1) 392 return getUnitDIE(); 393 // Look for previous DIE with a depth that is one less than the Die's depth. 394 const uint32_t ParentDepth = Depth - 1; 395 for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) { 396 if (DieArray[I].getDepth() == ParentDepth) 397 return DWARFDie(this, &DieArray[I]); 398 } 399 return DWARFDie(); 400 } 401 402 DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { 403 if (!Die) 404 return DWARFDie(); 405 uint32_t Depth = Die->getDepth(); 406 // Unit DIEs always have a depth of zero and never have siblings. 407 if (Depth == 0) 408 return DWARFDie(); 409 // NULL DIEs don't have siblings. 410 if (Die->getAbbreviationDeclarationPtr() == nullptr) 411 return DWARFDie(); 412 413 // Find the next DIE whose depth is the same as the Die's depth. 414 for (size_t I=getDIEIndex(Die)+1, EndIdx = DieArray.size(); I<EndIdx; ++I) { 415 if (DieArray[I].getDepth() == Depth) 416 return DWARFDie(this, &DieArray[I]); 417 } 418 return DWARFDie(); 419 } 420 421 } // end namespace llvm 422