DWARFUnit.cpp revision 263509
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 "DWARFUnit.h" 11#include "DWARFContext.h" 12#include "llvm/DebugInfo/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 20DWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, 21 StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, 22 const RelocAddrMap *M, bool LE) 23 : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS), 24 StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), 25 RelocMap(M), isLittleEndian(LE) { 26 clear(); 27} 28 29DWARFUnit::~DWARFUnit() { 30} 31 32bool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, 33 uint64_t &Result) const { 34 uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; 35 if (AddrOffsetSection.size() < Offset + AddrSize) 36 return false; 37 DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize); 38 Result = DA.getAddress(&Offset); 39 return true; 40} 41 42bool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, 43 uint32_t &Result) const { 44 // FIXME: string offset section entries are 8-byte for DWARF64. 45 const uint32_t ItemSize = 4; 46 uint32_t Offset = Index * ItemSize; 47 if (StringOffsetSection.size() < Offset + ItemSize) 48 return false; 49 DataExtractor DA(StringOffsetSection, isLittleEndian, 0); 50 Result = DA.getU32(&Offset); 51 return true; 52} 53 54bool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { 55 Length = debug_info.getU32(offset_ptr); 56 Version = debug_info.getU16(offset_ptr); 57 uint64_t abbrOffset = debug_info.getU32(offset_ptr); 58 AddrSize = debug_info.getU8(offset_ptr); 59 60 bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); 61 bool versionOK = DWARFContext::isSupportedVersion(Version); 62 bool abbrOffsetOK = AbbrevSection.size() > abbrOffset; 63 bool addrSizeOK = AddrSize == 4 || AddrSize == 8; 64 65 if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK) 66 return false; 67 68 Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset); 69 return true; 70} 71 72bool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 73 clear(); 74 75 Offset = *offset_ptr; 76 77 if (debug_info.isValidOffset(*offset_ptr)) { 78 if (extractImpl(debug_info, offset_ptr)) 79 return true; 80 81 // reset the offset to where we tried to parse from if anything went wrong 82 *offset_ptr = Offset; 83 } 84 85 return false; 86} 87 88bool DWARFUnit::extractRangeList(uint32_t RangeListOffset, 89 DWARFDebugRangeList &RangeList) const { 90 // Require that compile unit is extracted. 91 assert(DieArray.size() > 0); 92 DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); 93 uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 94 return RangeList.extract(RangesData, &ActualRangeListOffset); 95} 96 97void DWARFUnit::clear() { 98 Offset = 0; 99 Length = 0; 100 Version = 0; 101 Abbrevs = 0; 102 AddrSize = 0; 103 BaseAddr = 0; 104 RangeSectionBase = 0; 105 AddrOffsetSectionBase = 0; 106 clearDIEs(false); 107 DWO.reset(); 108} 109 110const char *DWARFUnit::getCompilationDir() { 111 extractDIEsIfNeeded(true); 112 if (DieArray.empty()) 113 return 0; 114 return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); 115} 116 117uint64_t DWARFUnit::getDWOId() { 118 extractDIEsIfNeeded(true); 119 const uint64_t FailValue = -1ULL; 120 if (DieArray.empty()) 121 return FailValue; 122 return DieArray[0] 123 .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); 124} 125 126void DWARFUnit::setDIERelations() { 127 if (DieArray.empty()) 128 return; 129 DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); 130 DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); 131 DWARFDebugInfoEntryMinimal *curr_die; 132 // We purposely are skipping the last element in the array in the loop below 133 // so that we can always have a valid next item 134 for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { 135 // Since our loop doesn't include the last element, we can always 136 // safely access the next die in the array. 137 DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; 138 139 const DWARFAbbreviationDeclaration *curr_die_abbrev = 140 curr_die->getAbbreviationDeclarationPtr(); 141 142 if (curr_die_abbrev) { 143 // Normal DIE 144 if (curr_die_abbrev->hasChildren()) 145 next_die->setParent(curr_die); 146 else 147 curr_die->setSibling(next_die); 148 } else { 149 // NULL DIE that terminates a sibling chain 150 DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); 151 if (parent) 152 parent->setSibling(next_die); 153 } 154 } 155 156 // Since we skipped the last element, we need to fix it up! 157 if (die_array_begin < die_array_end) 158 curr_die->setParent(die_array_begin); 159} 160 161void DWARFUnit::extractDIEsToVector( 162 bool AppendCUDie, bool AppendNonCUDies, 163 std::vector<DWARFDebugInfoEntryMinimal> &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 Offset = getFirstDIEOffset(); 170 uint32_t NextCUOffset = getNextUnitOffset(); 171 DWARFDebugInfoEntryMinimal DIE; 172 uint32_t Depth = 0; 173 bool IsCUDie = true; 174 175 while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) { 176 if (IsCUDie) { 177 if (AppendCUDie) 178 Dies.push_back(DIE); 179 if (!AppendNonCUDies) 180 break; 181 // The average bytes per DIE entry has been seen to be 182 // around 14-20 so let's pre-reserve the needed memory for 183 // our DIE entries accordingly. 184 Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 185 IsCUDie = false; 186 } else { 187 Dies.push_back(DIE); 188 } 189 190 const DWARFAbbreviationDeclaration *AbbrDecl = 191 DIE.getAbbreviationDeclarationPtr(); 192 if (AbbrDecl) { 193 // Normal DIE 194 if (AbbrDecl->hasChildren()) 195 ++Depth; 196 } else { 197 // NULL DIE. 198 if (Depth > 0) 199 --Depth; 200 if (Depth == 0) 201 break; // We are done with this compile unit! 202 } 203 } 204 205 // Give a little bit of info if we encounter corrupt DWARF (our offset 206 // should always terminate at or before the start of the next compilation 207 // unit header). 208 if (Offset > NextCUOffset) 209 fprintf(stderr, "warning: DWARF compile unit extends beyond its " 210 "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset); 211} 212 213size_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 214 if ((CUDieOnly && DieArray.size() > 0) || 215 DieArray.size() > 1) 216 return 0; // Already parsed. 217 218 bool HasCUDie = DieArray.size() > 0; 219 extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 220 221 if (DieArray.empty()) 222 return 0; 223 224 // If CU DIE was just parsed, copy several attribute values from it. 225 if (!HasCUDie) { 226 uint64_t BaseAddr = 227 DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); 228 if (BaseAddr == -1ULL) 229 BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); 230 setBaseAddress(BaseAddr); 231 AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 232 this, DW_AT_GNU_addr_base, 0); 233 RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 234 this, DW_AT_GNU_ranges_base, 0); 235 } 236 237 setDIERelations(); 238 return DieArray.size(); 239} 240 241DWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile) 242 : DWOFile(DWOFile), 243 DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))), 244 DWOU(0) { 245 if (DWOContext->getNumDWOCompileUnits() > 0) 246 DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 247} 248 249bool DWARFUnit::parseDWO() { 250 if (DWO.get() != 0) 251 return false; 252 extractDIEsIfNeeded(true); 253 if (DieArray.empty()) 254 return false; 255 const char *DWOFileName = 256 DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0); 257 if (DWOFileName == 0) 258 return false; 259 const char *CompilationDir = 260 DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); 261 SmallString<16> AbsolutePath; 262 if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) { 263 sys::path::append(AbsolutePath, CompilationDir); 264 } 265 sys::path::append(AbsolutePath, DWOFileName); 266 object::ObjectFile *DWOFile = 267 object::ObjectFile::createObjectFile(AbsolutePath); 268 if (!DWOFile) 269 return false; 270 // Reset DWOHolder. 271 DWO.reset(new DWOHolder(DWOFile)); 272 DWARFUnit *DWOCU = DWO->getUnit(); 273 // Verify that compile unit in .dwo file is valid. 274 if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) { 275 DWO.reset(); 276 return false; 277 } 278 // Share .debug_addr and .debug_ranges section with compile unit in .dwo 279 DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 280 DWOCU->setRangesSection(RangeSection, RangeSectionBase); 281 return true; 282} 283 284void DWARFUnit::clearDIEs(bool KeepCUDie) { 285 if (DieArray.size() > (unsigned)KeepCUDie) { 286 // std::vectors never get any smaller when resized to a smaller size, 287 // or when clear() or erase() are called, the size will report that it 288 // is smaller, but the memory allocated remains intact (call capacity() 289 // to see this). So we need to create a temporary vector and swap the 290 // contents which will cause just the internal pointers to be swapped 291 // so that when temporary vector goes out of scope, it will destroy the 292 // contents. 293 std::vector<DWARFDebugInfoEntryMinimal> TmpArray; 294 DieArray.swap(TmpArray); 295 // Save at least the compile unit DIE 296 if (KeepCUDie) 297 DieArray.push_back(TmpArray.front()); 298 } 299} 300 301void 302DWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, 303 bool clear_dies_if_already_not_parsed, 304 uint32_t CUOffsetInAranges) { 305 // This function is usually called if there in no .debug_aranges section 306 // in order to produce a compile unit level set of address ranges that 307 // is accurate. If the DIEs weren't parsed, then we don't want all dies for 308 // all compile units to stay loaded when they weren't needed. So we can end 309 // up parsing the DWARF and then throwing them all away to keep memory usage 310 // down. 311 const bool clear_dies = extractDIEsIfNeeded(false) > 1 && 312 clear_dies_if_already_not_parsed; 313 DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges); 314 bool DWOCreated = parseDWO(); 315 if (DWO.get()) { 316 // If there is a .dwo file for this compile unit, then skeleton CU DIE 317 // doesn't have children, and we should instead build address range table 318 // from DIEs in the .debug_info.dwo section of .dwo file. 319 DWO->getUnit()->buildAddressRangeTable( 320 debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges); 321 } 322 if (DWOCreated && clear_dies_if_already_not_parsed) 323 DWO.reset(); 324 325 // Keep memory down by clearing DIEs if this generate function 326 // caused them to be parsed. 327 if (clear_dies) 328 clearDIEs(true); 329} 330 331const DWARFDebugInfoEntryMinimal * 332DWARFUnit::getSubprogramForAddress(uint64_t Address) { 333 extractDIEsIfNeeded(false); 334 for (size_t i = 0, n = DieArray.size(); i != n; i++) 335 if (DieArray[i].isSubprogramDIE() && 336 DieArray[i].addressRangeContainsAddress(this, Address)) { 337 return &DieArray[i]; 338 } 339 return 0; 340} 341 342DWARFDebugInfoEntryInlinedChain 343DWARFUnit::getInlinedChainForAddress(uint64_t Address) { 344 // First, find a subprogram that contains the given address (the root 345 // of inlined chain). 346 const DWARFUnit *ChainCU = 0; 347 const DWARFDebugInfoEntryMinimal *SubprogramDIE = 348 getSubprogramForAddress(Address); 349 if (SubprogramDIE) { 350 ChainCU = this; 351 } else { 352 // Try to look for subprogram DIEs in the DWO file. 353 parseDWO(); 354 if (DWO.get()) { 355 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 356 if (SubprogramDIE) 357 ChainCU = DWO->getUnit(); 358 } 359 } 360 361 // Get inlined chain rooted at this subprogram DIE. 362 if (!SubprogramDIE) 363 return DWARFDebugInfoEntryInlinedChain(); 364 return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); 365} 366