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 = 234 UnitDie.getAttributeValueAsSectionOffset(DW_AT_GNU_addr_base) 235 .getValueOr(0); 236 RangeSectionBase = 237 UnitDie.getAttributeValueAsSectionOffset(DW_AT_rnglists_base) 238 .getValueOr(0); 239 // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 240 // skeleton CU DIE, so that DWARF users not aware of it are not broken. 241 } 242 243 return DieArray.size(); 244 } 245 246 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) 247 : DWOU(nullptr) { 248 auto Obj = object::ObjectFile::createObjectFile(DWOPath); 249 if (!Obj) { 250 // TODO: Actually report errors helpfully. 251 consumeError(Obj.takeError()); 252 return; 253 } 254 DWOFile = std::move(Obj.get()); 255 DWOContext.reset( 256 cast<DWARFContext>(new DWARFContextInMemory(*DWOFile.getBinary()))); 257 if (DWOContext->getNumDWOCompileUnits() > 0) 258 DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 259 } 260 261 bool DWARFUnit::parseDWO() { 262 if (isDWO) 263 return false; 264 if (DWO.get()) 265 return false; 266 DWARFDie UnitDie = getUnitDIE(); 267 if (!UnitDie) 268 return false; 269 const char *DWOFileName = 270 UnitDie.getAttributeValueAsString(DW_AT_GNU_dwo_name, nullptr); 271 if (!DWOFileName) 272 return false; 273 const char *CompilationDir = 274 UnitDie.getAttributeValueAsString(DW_AT_comp_dir, nullptr); 275 SmallString<16> AbsolutePath; 276 if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { 277 sys::path::append(AbsolutePath, CompilationDir); 278 } 279 sys::path::append(AbsolutePath, DWOFileName); 280 DWO = llvm::make_unique<DWOHolder>(AbsolutePath); 281 DWARFUnit *DWOCU = DWO->getUnit(); 282 // Verify that compile unit in .dwo file is valid. 283 if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { 284 DWO.reset(); 285 return false; 286 } 287 // Share .debug_addr and .debug_ranges section with compile unit in .dwo 288 DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 289 auto DWORangesBase = UnitDie.getRangesBaseAttribute(); 290 DWOCU->setRangesSection(RangeSection, DWORangesBase ? *DWORangesBase : 0); 291 return true; 292 } 293 294 void DWARFUnit::clearDIEs(bool KeepCUDie) { 295 if (DieArray.size() > (unsigned)KeepCUDie) { 296 // std::vectors never get any smaller when resized to a smaller size, 297 // or when clear() or erase() are called, the size will report that it 298 // is smaller, but the memory allocated remains intact (call capacity() 299 // to see this). So we need to create a temporary vector and swap the 300 // contents which will cause just the internal pointers to be swapped 301 // so that when temporary vector goes out of scope, it will destroy the 302 // contents. 303 std::vector<DWARFDebugInfoEntry> TmpArray; 304 DieArray.swap(TmpArray); 305 // Save at least the compile unit DIE 306 if (KeepCUDie) 307 DieArray.push_back(TmpArray.front()); 308 } 309 } 310 311 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { 312 DWARFDie UnitDie = getUnitDIE(); 313 if (!UnitDie) 314 return; 315 // First, check if unit DIE describes address ranges for the whole unit. 316 const auto &CUDIERanges = UnitDie.getAddressRanges(); 317 if (!CUDIERanges.empty()) { 318 CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); 319 return; 320 } 321 322 // This function is usually called if there in no .debug_aranges section 323 // in order to produce a compile unit level set of address ranges that 324 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 325 // all compile units to stay loaded when they weren't needed. So we can end 326 // up parsing the DWARF and then throwing them all away to keep memory usage 327 // down. 328 const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; 329 getUnitDIE().collectChildrenAddressRanges(CURanges); 330 331 // Collect address ranges from DIEs in .dwo if necessary. 332 bool DWOCreated = parseDWO(); 333 if (DWO.get()) 334 DWO->getUnit()->collectAddressRanges(CURanges); 335 if (DWOCreated) 336 DWO.reset(); 337 338 // Keep memory down by clearing DIEs if this generate function 339 // caused them to be parsed. 340 if (ClearDIEs) 341 clearDIEs(true); 342 } 343 344 DWARFDie 345 DWARFUnit::getSubprogramForAddress(uint64_t Address) { 346 extractDIEsIfNeeded(false); 347 for (const DWARFDebugInfoEntry &D : DieArray) { 348 DWARFDie DIE(this, &D); 349 if (DIE.isSubprogramDIE() && 350 DIE.addressRangeContainsAddress(Address)) { 351 return DIE; 352 } 353 } 354 return DWARFDie(); 355 } 356 357 void 358 DWARFUnit::getInlinedChainForAddress(uint64_t Address, 359 SmallVectorImpl<DWARFDie> &InlinedChain) { 360 // First, find a subprogram that contains the given address (the root 361 // of inlined chain). 362 DWARFDie SubprogramDIE; 363 // Try to look for subprogram DIEs in the DWO file. 364 parseDWO(); 365 if (DWO) 366 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 367 else 368 SubprogramDIE = getSubprogramForAddress(Address); 369 370 // Get inlined chain rooted at this subprogram DIE. 371 if (SubprogramDIE) 372 SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain); 373 else 374 InlinedChain.clear(); 375 } 376 377 const DWARFUnitIndex &getDWARFUnitIndex(DWARFContext &Context, 378 DWARFSectionKind Kind) { 379 if (Kind == DW_SECT_INFO) 380 return Context.getCUIndex(); 381 assert(Kind == DW_SECT_TYPES); 382 return Context.getTUIndex(); 383 } 384 385 DWARFDie DWARFUnit::getParent(const DWARFDebugInfoEntry *Die) { 386 if (!Die) 387 return DWARFDie(); 388 const uint32_t Depth = Die->getDepth(); 389 // Unit DIEs always have a depth of zero and never have parents. 390 if (Depth == 0) 391 return DWARFDie(); 392 // Depth of 1 always means parent is the compile/type unit. 393 if (Depth == 1) 394 return getUnitDIE(); 395 // Look for previous DIE with a depth that is one less than the Die's depth. 396 const uint32_t ParentDepth = Depth - 1; 397 for (uint32_t I = getDIEIndex(Die) - 1; I > 0; --I) { 398 if (DieArray[I].getDepth() == ParentDepth) 399 return DWARFDie(this, &DieArray[I]); 400 } 401 return DWARFDie(); 402 } 403 404 DWARFDie DWARFUnit::getSibling(const DWARFDebugInfoEntry *Die) { 405 if (!Die) 406 return DWARFDie(); 407 uint32_t Depth = Die->getDepth(); 408 // Unit DIEs always have a depth of zero and never have siblings. 409 if (Depth == 0) 410 return DWARFDie(); 411 // NULL DIEs don't have siblings. 412 if (Die->getAbbreviationDeclarationPtr() == nullptr) 413 return DWARFDie(); 414 415 // Find the next DIE whose depth is the same as the Die's depth. 416 for (size_t I=getDIEIndex(Die)+1, EndIdx = DieArray.size(); I<EndIdx; ++I) { 417 if (DieArray[I].getDepth() == Depth) 418 return DWARFDie(this, &DieArray[I]); 419 } 420 return DWARFDie(); 421 } 422 423 } // end namespace llvm 424