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