DWARFUnit.cpp revision 6948897e478cbd66626159776a8017b3c18579b9
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 return Abbrevs != nullptr; 83} 84 85bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 86 clear(); 87 88 Offset = *offset_ptr; 89 90 if (debug_info.isValidOffset(*offset_ptr)) { 91 if (extractImpl(debug_info, offset_ptr)) 92 return true; 93 94 // reset the offset to where we tried to parse from if anything went wrong 95 *offset_ptr = Offset; 96 } 97 98 return false; 99} 100 101bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, 102 DWARFDebugRangeList &RangeList) const { 103 // Require that compile unit is extracted. 104 assert(DieArray.size() > 0); 105 DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); 106 uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 107 return RangeList.extract(RangesData, &ActualRangeListOffset); 108} 109 110void DWARFUnit::clear() { 111 Offset = 0; 112 Length = 0; 113 Version = 0; 114 Abbrevs = nullptr; 115 AddrSize = 0; 116 BaseAddr = 0; 117 RangeSectionBase = 0; 118 AddrOffsetSectionBase = 0; 119 clearDIEs(false); 120 DWO.reset(); 121} 122 123const char *DWARFUnit::getCompilationDir() { 124 extractDIEsIfNeeded(true); 125 if (DieArray.empty()) 126 return nullptr; 127 return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); 128} 129 130uint64_t DWARFUnit::getDWOId() { 131 extractDIEsIfNeeded(true); 132 const uint64_t FailValue = -1ULL; 133 if (DieArray.empty()) 134 return FailValue; 135 return DieArray[0] 136 .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); 137} 138 139void DWARFUnit::setDIERelations() { 140 if (DieArray.size() <= 1) 141 return; 142 143 std::vector<DWARFDebugInfoEntryMinimal *> ParentChain; 144 DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; 145 for (auto &DIE : DieArray) { 146 if (SiblingChain) { 147 SiblingChain->setSibling(&DIE); 148 } 149 if (const DWARFAbbreviationDeclaration *AbbrDecl = 150 DIE.getAbbreviationDeclarationPtr()) { 151 // Normal DIE. 152 if (AbbrDecl->hasChildren()) { 153 ParentChain.push_back(&DIE); 154 SiblingChain = nullptr; 155 } else { 156 SiblingChain = &DIE; 157 } 158 } else { 159 // NULL entry terminates the sibling chain. 160 SiblingChain = ParentChain.back(); 161 ParentChain.pop_back(); 162 } 163 } 164 assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); 165 assert(ParentChain.empty()); 166} 167 168void DWARFUnit::extractDIEsToVector( 169 bool AppendCUDie, bool AppendNonCUDies, 170 std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { 171 if (!AppendCUDie && !AppendNonCUDies) 172 return; 173 174 // Set the offset to that of the first DIE and calculate the start of the 175 // next compilation unit header. 176 uint32_t DIEOffset = Offset + getHeaderSize(); 177 uint32_t NextCUOffset = getNextUnitOffset(); 178 DWARFDebugInfoEntryMinimal DIE; 179 uint32_t Depth = 0; 180 bool IsCUDie = true; 181 182 while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { 183 if (IsCUDie) { 184 if (AppendCUDie) 185 Dies.push_back(DIE); 186 if (!AppendNonCUDies) 187 break; 188 // The average bytes per DIE entry has been seen to be 189 // around 14-20 so let's pre-reserve the needed memory for 190 // our DIE entries accordingly. 191 Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 192 IsCUDie = false; 193 } else { 194 Dies.push_back(DIE); 195 } 196 197 if (const DWARFAbbreviationDeclaration *AbbrDecl = 198 DIE.getAbbreviationDeclarationPtr()) { 199 // Normal DIE 200 if (AbbrDecl->hasChildren()) 201 ++Depth; 202 } else { 203 // NULL DIE. 204 if (Depth > 0) 205 --Depth; 206 if (Depth == 0) 207 break; // We are done with this compile unit! 208 } 209 } 210 211 // Give a little bit of info if we encounter corrupt DWARF (our offset 212 // should always terminate at or before the start of the next compilation 213 // unit header). 214 if (DIEOffset > NextCUOffset) 215 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 216 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); 217} 218 219size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 220 if ((CUDieOnly && DieArray.size() > 0) || 221 DieArray.size() > 1) 222 return 0; // Already parsed. 223 224 bool HasCUDie = DieArray.size() > 0; 225 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 226 227 if (DieArray.empty()) 228 return 0; 229 230 // If CU DIE was just parsed, copy several attribute values from it. 231 if (!HasCUDie) { 232 uint64_t BaseAddr = 233 DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); 234 if (BaseAddr == -1ULL) 235 BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); 236 setBaseAddress(BaseAddr); 237 AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 238 this, DW_AT_GNU_addr_base, 0); 239 RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 240 this, DW_AT_ranges_base, 0); 241 // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 242 // skeleton CU DIE, so that DWARF users not aware of it are not broken. 243 } 244 245 setDIERelations(); 246 return DieArray.size(); 247} 248 249DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) 250 : DWOFile(), DWOContext(), DWOU(nullptr) { 251 auto Obj = object::ObjectFile::createObjectFile(DWOPath); 252 if (!Obj) 253 return; 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 261bool DWARFUnit::parseDWO() { 262 if (DWO.get()) 263 return false; 264 extractDIEsIfNeeded(true); 265 if (DieArray.empty()) 266 return false; 267 const char *DWOFileName = 268 DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); 269 if (!DWOFileName) 270 return false; 271 const char *CompilationDir = 272 DieArray[0].getAttributeValueAsString(this, 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 uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); 288 DWOCU->setRangesSection(RangeSection, DWORangesBase); 289 return true; 290} 291 292void 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<DWARFDebugInfoEntryMinimal> 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 309void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { 310 const auto *U = getUnitDIE(); 311 if (U == nullptr) 312 return; 313 // First, check if unit DIE describes address ranges for the whole unit. 314 const auto &CUDIERanges = U->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