LLVM API Documentation
00001 //===-- DWARFUnit.cpp -----------------------------------------------------===// 00002 // 00003 // The LLVM Compiler Infrastructure 00004 // 00005 // This file is distributed under the University of Illinois Open Source 00006 // License. See LICENSE.TXT for details. 00007 // 00008 //===----------------------------------------------------------------------===// 00009 00010 #include "DWARFUnit.h" 00011 #include "DWARFContext.h" 00012 #include "llvm/DebugInfo/DWARFFormValue.h" 00013 #include "llvm/Support/Dwarf.h" 00014 #include "llvm/Support/Path.h" 00015 #include <cstdio> 00016 00017 using namespace llvm; 00018 using namespace dwarf; 00019 00020 DWARFUnit::DWARFUnit(DWARFContext &DC, const DWARFDebugAbbrev *DA, 00021 StringRef IS, StringRef RS, StringRef SS, StringRef SOS, 00022 StringRef AOS, const RelocAddrMap *M, bool LE, 00023 const DWARFUnitSectionBase& UnitSection) 00024 : Context(DC), Abbrev(DA), InfoSection(IS), RangeSection(RS), 00025 StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), 00026 RelocMap(M), isLittleEndian(LE), UnitSection(UnitSection) { 00027 clear(); 00028 } 00029 00030 DWARFUnit::~DWARFUnit() { 00031 } 00032 00033 bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, 00034 uint64_t &Result) const { 00035 uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; 00036 if (AddrOffsetSection.size() < Offset + AddrSize) 00037 return false; 00038 DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize); 00039 Result = DA.getAddress(&Offset); 00040 return true; 00041 } 00042 00043 bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, 00044 uint32_t &Result) const { 00045 // FIXME: string offset section entries are 8-byte for DWARF64. 00046 const uint32_t ItemSize = 4; 00047 uint32_t Offset = Index * ItemSize; 00048 if (StringOffsetSection.size() < Offset + ItemSize) 00049 return false; 00050 DataExtractor DA(StringOffsetSection, isLittleEndian, 0); 00051 Result = DA.getU32(&Offset); 00052 return true; 00053 } 00054 00055 bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { 00056 Length = debug_info.getU32(offset_ptr); 00057 Version = debug_info.getU16(offset_ptr); 00058 uint64_t AbbrOffset = debug_info.getU32(offset_ptr); 00059 AddrSize = debug_info.getU8(offset_ptr); 00060 00061 bool LengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); 00062 bool VersionOK = DWARFContext::isSupportedVersion(Version); 00063 bool AddrSizeOK = AddrSize == 4 || AddrSize == 8; 00064 00065 if (!LengthOK || !VersionOK || !AddrSizeOK) 00066 return false; 00067 00068 Abbrevs = Abbrev->getAbbreviationDeclarationSet(AbbrOffset); 00069 if (Abbrevs == nullptr) 00070 return false; 00071 00072 return true; 00073 } 00074 00075 bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 00076 clear(); 00077 00078 Offset = *offset_ptr; 00079 00080 if (debug_info.isValidOffset(*offset_ptr)) { 00081 if (extractImpl(debug_info, offset_ptr)) 00082 return true; 00083 00084 // reset the offset to where we tried to parse from if anything went wrong 00085 *offset_ptr = Offset; 00086 } 00087 00088 return false; 00089 } 00090 00091 bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, 00092 DWARFDebugRangeList &RangeList) const { 00093 // Require that compile unit is extracted. 00094 assert(DieArray.size() > 0); 00095 DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); 00096 uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 00097 return RangeList.extract(RangesData, &ActualRangeListOffset); 00098 } 00099 00100 void DWARFUnit::clear() { 00101 Offset = 0; 00102 Length = 0; 00103 Version = 0; 00104 Abbrevs = nullptr; 00105 AddrSize = 0; 00106 BaseAddr = 0; 00107 RangeSectionBase = 0; 00108 AddrOffsetSectionBase = 0; 00109 clearDIEs(false); 00110 DWO.reset(); 00111 } 00112 00113 const char *DWARFUnit::getCompilationDir() { 00114 extractDIEsIfNeeded(true); 00115 if (DieArray.empty()) 00116 return nullptr; 00117 return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); 00118 } 00119 00120 uint64_t DWARFUnit::getDWOId() { 00121 extractDIEsIfNeeded(true); 00122 const uint64_t FailValue = -1ULL; 00123 if (DieArray.empty()) 00124 return FailValue; 00125 return DieArray[0] 00126 .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); 00127 } 00128 00129 void DWARFUnit::setDIERelations() { 00130 if (DieArray.size() <= 1) 00131 return; 00132 00133 std::vector<DWARFDebugInfoEntryMinimal *> ParentChain; 00134 DWARFDebugInfoEntryMinimal *SiblingChain = nullptr; 00135 for (auto &DIE : DieArray) { 00136 if (SiblingChain) { 00137 SiblingChain->setSibling(&DIE); 00138 } 00139 if (const DWARFAbbreviationDeclaration *AbbrDecl = 00140 DIE.getAbbreviationDeclarationPtr()) { 00141 // Normal DIE. 00142 if (AbbrDecl->hasChildren()) { 00143 ParentChain.push_back(&DIE); 00144 SiblingChain = nullptr; 00145 } else { 00146 SiblingChain = &DIE; 00147 } 00148 } else { 00149 // NULL entry terminates the sibling chain. 00150 SiblingChain = ParentChain.back(); 00151 ParentChain.pop_back(); 00152 } 00153 } 00154 assert(SiblingChain == nullptr || SiblingChain == &DieArray[0]); 00155 assert(ParentChain.empty()); 00156 } 00157 00158 void DWARFUnit::extractDIEsToVector( 00159 bool AppendCUDie, bool AppendNonCUDies, 00160 std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { 00161 if (!AppendCUDie && !AppendNonCUDies) 00162 return; 00163 00164 // Set the offset to that of the first DIE and calculate the start of the 00165 // next compilation unit header. 00166 uint32_t DIEOffset = Offset + getHeaderSize(); 00167 uint32_t NextCUOffset = getNextUnitOffset(); 00168 DWARFDebugInfoEntryMinimal DIE; 00169 uint32_t Depth = 0; 00170 bool IsCUDie = true; 00171 00172 while (DIEOffset < NextCUOffset && DIE.extractFast(this, &DIEOffset)) { 00173 if (IsCUDie) { 00174 if (AppendCUDie) 00175 Dies.push_back(DIE); 00176 if (!AppendNonCUDies) 00177 break; 00178 // The average bytes per DIE entry has been seen to be 00179 // around 14-20 so let's pre-reserve the needed memory for 00180 // our DIE entries accordingly. 00181 Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 00182 IsCUDie = false; 00183 } else { 00184 Dies.push_back(DIE); 00185 } 00186 00187 if (const DWARFAbbreviationDeclaration *AbbrDecl = 00188 DIE.getAbbreviationDeclarationPtr()) { 00189 // Normal DIE 00190 if (AbbrDecl->hasChildren()) 00191 ++Depth; 00192 } else { 00193 // NULL DIE. 00194 if (Depth > 0) 00195 --Depth; 00196 if (Depth == 0) 00197 break; // We are done with this compile unit! 00198 } 00199 } 00200 00201 // Give a little bit of info if we encounter corrupt DWARF (our offset 00202 // should always terminate at or before the start of the next compilation 00203 // unit header). 00204 if (DIEOffset > NextCUOffset) 00205 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 00206 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), DIEOffset); 00207 } 00208 00209 size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 00210 if ((CUDieOnly && DieArray.size() > 0) || 00211 DieArray.size() > 1) 00212 return 0; // Already parsed. 00213 00214 bool HasCUDie = DieArray.size() > 0; 00215 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 00216 00217 if (DieArray.empty()) 00218 return 0; 00219 00220 // If CU DIE was just parsed, copy several attribute values from it. 00221 if (!HasCUDie) { 00222 uint64_t BaseAddr = 00223 DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); 00224 if (BaseAddr == -1ULL) 00225 BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); 00226 setBaseAddress(BaseAddr); 00227 AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 00228 this, DW_AT_GNU_addr_base, 0); 00229 RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 00230 this, DW_AT_ranges_base, 0); 00231 // Don't fall back to DW_AT_GNU_ranges_base: it should be ignored for 00232 // skeleton CU DIE, so that DWARF users not aware of it are not broken. 00233 } 00234 00235 setDIERelations(); 00236 return DieArray.size(); 00237 } 00238 00239 DWARFUnit::DWOHolder::DWOHolder(StringRef DWOPath) 00240 : DWOFile(), DWOContext(), DWOU(nullptr) { 00241 auto Obj = object::ObjectFile::createObjectFile(DWOPath); 00242 if (!Obj) 00243 return; 00244 DWOFile = std::move(Obj.get()); 00245 DWOContext.reset( 00246 cast<DWARFContext>(DIContext::getDWARFContext(*DWOFile.getBinary()))); 00247 if (DWOContext->getNumDWOCompileUnits() > 0) 00248 DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 00249 } 00250 00251 bool DWARFUnit::parseDWO() { 00252 if (DWO.get()) 00253 return false; 00254 extractDIEsIfNeeded(true); 00255 if (DieArray.empty()) 00256 return false; 00257 const char *DWOFileName = 00258 DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, nullptr); 00259 if (!DWOFileName) 00260 return false; 00261 const char *CompilationDir = 00262 DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, nullptr); 00263 SmallString<16> AbsolutePath; 00264 if (sys::path::is_relative(DWOFileName) && CompilationDir != nullptr) { 00265 sys::path::append(AbsolutePath, CompilationDir); 00266 } 00267 sys::path::append(AbsolutePath, DWOFileName); 00268 DWO = llvm::make_unique<DWOHolder>(AbsolutePath); 00269 DWARFUnit *DWOCU = DWO->getUnit(); 00270 // Verify that compile unit in .dwo file is valid. 00271 if (!DWOCU || DWOCU->getDWOId() != getDWOId()) { 00272 DWO.reset(); 00273 return false; 00274 } 00275 // Share .debug_addr and .debug_ranges section with compile unit in .dwo 00276 DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 00277 uint32_t DWORangesBase = DieArray[0].getRangesBaseAttribute(this, 0); 00278 DWOCU->setRangesSection(RangeSection, DWORangesBase); 00279 return true; 00280 } 00281 00282 void DWARFUnit::clearDIEs(bool KeepCUDie) { 00283 if (DieArray.size() > (unsigned)KeepCUDie) { 00284 // std::vectors never get any smaller when resized to a smaller size, 00285 // or when clear() or erase() are called, the size will report that it 00286 // is smaller, but the memory allocated remains intact (call capacity() 00287 // to see this). So we need to create a temporary vector and swap the 00288 // contents which will cause just the internal pointers to be swapped 00289 // so that when temporary vector goes out of scope, it will destroy the 00290 // contents. 00291 std::vector<DWARFDebugInfoEntryMinimal> TmpArray; 00292 DieArray.swap(TmpArray); 00293 // Save at least the compile unit DIE 00294 if (KeepCUDie) 00295 DieArray.push_back(TmpArray.front()); 00296 } 00297 } 00298 00299 void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { 00300 // First, check if CU DIE describes address ranges for the unit. 00301 const auto &CUDIERanges = getCompileUnitDIE()->getAddressRanges(this); 00302 if (!CUDIERanges.empty()) { 00303 CURanges.insert(CURanges.end(), CUDIERanges.begin(), CUDIERanges.end()); 00304 return; 00305 } 00306 00307 // This function is usually called if there in no .debug_aranges section 00308 // in order to produce a compile unit level set of address ranges that 00309 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 00310 // all compile units to stay loaded when they weren't needed. So we can end 00311 // up parsing the DWARF and then throwing them all away to keep memory usage 00312 // down. 00313 const bool ClearDIEs = extractDIEsIfNeeded(false) > 1; 00314 DieArray[0].collectChildrenAddressRanges(this, CURanges); 00315 00316 // Collect address ranges from DIEs in .dwo if necessary. 00317 bool DWOCreated = parseDWO(); 00318 if (DWO.get()) 00319 DWO->getUnit()->collectAddressRanges(CURanges); 00320 if (DWOCreated) 00321 DWO.reset(); 00322 00323 // Keep memory down by clearing DIEs if this generate function 00324 // caused them to be parsed. 00325 if (ClearDIEs) 00326 clearDIEs(true); 00327 } 00328 00329 const DWARFDebugInfoEntryMinimal * 00330 DWARFUnit::getSubprogramForAddress(uint64_t Address) { 00331 extractDIEsIfNeeded(false); 00332 for (const DWARFDebugInfoEntryMinimal &DIE : DieArray) { 00333 if (DIE.isSubprogramDIE() && 00334 DIE.addressRangeContainsAddress(this, Address)) { 00335 return &DIE; 00336 } 00337 } 00338 return nullptr; 00339 } 00340 00341 DWARFDebugInfoEntryInlinedChain 00342 DWARFUnit::getInlinedChainForAddress(uint64_t Address) { 00343 // First, find a subprogram that contains the given address (the root 00344 // of inlined chain). 00345 const DWARFUnit *ChainCU = nullptr; 00346 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 00347 getSubprogramForAddress(Address); 00348 if (SubprogramDIE) { 00349 ChainCU = this; 00350 } else { 00351 // Try to look for subprogram DIEs in the DWO file. 00352 parseDWO(); 00353 if (DWO.get()) { 00354 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 00355 if (SubprogramDIE) 00356 ChainCU = DWO->getUnit(); 00357 } 00358 } 00359 00360 // Get inlined chain rooted at this subprogram DIE. 00361 if (!SubprogramDIE) 00362 return DWARFDebugInfoEntryInlinedChain(); 00363 return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); 00364 }