1259698Sdim//===-- DWARFUnit.cpp -----------------------------------------------------===// 2259698Sdim// 3259698Sdim// The LLVM Compiler Infrastructure 4259698Sdim// 5259698Sdim// This file is distributed under the University of Illinois Open Source 6259698Sdim// License. See LICENSE.TXT for details. 7259698Sdim// 8259698Sdim//===----------------------------------------------------------------------===// 9259698Sdim 10259698Sdim#include "DWARFUnit.h" 11259698Sdim#include "DWARFContext.h" 12259698Sdim#include "llvm/DebugInfo/DWARFFormValue.h" 13259698Sdim#include "llvm/Support/Dwarf.h" 14259698Sdim#include "llvm/Support/Path.h" 15259698Sdim#include <cstdio> 16259698Sdim 17259698Sdimusing namespace llvm; 18259698Sdimusing namespace dwarf; 19259698Sdim 20259698SdimDWARFUnit::DWARFUnit(const DWARFDebugAbbrev *DA, StringRef IS, StringRef AS, 21259698Sdim StringRef RS, StringRef SS, StringRef SOS, StringRef AOS, 22259698Sdim const RelocAddrMap *M, bool LE) 23259698Sdim : Abbrev(DA), InfoSection(IS), AbbrevSection(AS), RangeSection(RS), 24259698Sdim StringSection(SS), StringOffsetSection(SOS), AddrOffsetSection(AOS), 25259698Sdim RelocMap(M), isLittleEndian(LE) { 26259698Sdim clear(); 27259698Sdim} 28259698Sdim 29259698SdimDWARFUnit::~DWARFUnit() { 30259698Sdim} 31259698Sdim 32259698Sdimbool DWARFUnit::getAddrOffsetSectionItem(uint32_t Index, 33259698Sdim uint64_t &Result) const { 34259698Sdim uint32_t Offset = AddrOffsetSectionBase + Index * AddrSize; 35259698Sdim if (AddrOffsetSection.size() < Offset + AddrSize) 36259698Sdim return false; 37259698Sdim DataExtractor DA(AddrOffsetSection, isLittleEndian, AddrSize); 38259698Sdim Result = DA.getAddress(&Offset); 39259698Sdim return true; 40259698Sdim} 41259698Sdim 42259698Sdimbool DWARFUnit::getStringOffsetSectionItem(uint32_t Index, 43259698Sdim uint32_t &Result) const { 44259698Sdim // FIXME: string offset section entries are 8-byte for DWARF64. 45259698Sdim const uint32_t ItemSize = 4; 46259698Sdim uint32_t Offset = Index * ItemSize; 47259698Sdim if (StringOffsetSection.size() < Offset + ItemSize) 48259698Sdim return false; 49259698Sdim DataExtractor DA(StringOffsetSection, isLittleEndian, 0); 50259698Sdim Result = DA.getU32(&Offset); 51259698Sdim return true; 52259698Sdim} 53259698Sdim 54259698Sdimbool DWARFUnit::extractImpl(DataExtractor debug_info, uint32_t *offset_ptr) { 55259698Sdim Length = debug_info.getU32(offset_ptr); 56259698Sdim Version = debug_info.getU16(offset_ptr); 57259698Sdim uint64_t abbrOffset = debug_info.getU32(offset_ptr); 58259698Sdim AddrSize = debug_info.getU8(offset_ptr); 59259698Sdim 60259698Sdim bool lengthOK = debug_info.isValidOffset(getNextUnitOffset() - 1); 61259698Sdim bool versionOK = DWARFContext::isSupportedVersion(Version); 62259698Sdim bool abbrOffsetOK = AbbrevSection.size() > abbrOffset; 63259698Sdim bool addrSizeOK = AddrSize == 4 || AddrSize == 8; 64259698Sdim 65259698Sdim if (!lengthOK || !versionOK || !addrSizeOK || !abbrOffsetOK) 66259698Sdim return false; 67259698Sdim 68259698Sdim Abbrevs = Abbrev->getAbbreviationDeclarationSet(abbrOffset); 69259698Sdim return true; 70259698Sdim} 71259698Sdim 72259698Sdimbool DWARFUnit::extract(DataExtractor debug_info, uint32_t *offset_ptr) { 73259698Sdim clear(); 74259698Sdim 75259698Sdim Offset = *offset_ptr; 76259698Sdim 77259698Sdim if (debug_info.isValidOffset(*offset_ptr)) { 78259698Sdim if (extractImpl(debug_info, offset_ptr)) 79259698Sdim return true; 80259698Sdim 81259698Sdim // reset the offset to where we tried to parse from if anything went wrong 82259698Sdim *offset_ptr = Offset; 83259698Sdim } 84259698Sdim 85259698Sdim return false; 86259698Sdim} 87259698Sdim 88259698Sdimbool DWARFUnit::extractRangeList(uint32_t RangeListOffset, 89259698Sdim DWARFDebugRangeList &RangeList) const { 90259698Sdim // Require that compile unit is extracted. 91259698Sdim assert(DieArray.size() > 0); 92259698Sdim DataExtractor RangesData(RangeSection, isLittleEndian, AddrSize); 93259698Sdim uint32_t ActualRangeListOffset = RangeSectionBase + RangeListOffset; 94259698Sdim return RangeList.extract(RangesData, &ActualRangeListOffset); 95259698Sdim} 96259698Sdim 97259698Sdimvoid DWARFUnit::clear() { 98259698Sdim Offset = 0; 99259698Sdim Length = 0; 100259698Sdim Version = 0; 101259698Sdim Abbrevs = 0; 102259698Sdim AddrSize = 0; 103259698Sdim BaseAddr = 0; 104259698Sdim RangeSectionBase = 0; 105259698Sdim AddrOffsetSectionBase = 0; 106259698Sdim clearDIEs(false); 107259698Sdim DWO.reset(); 108259698Sdim} 109259698Sdim 110259698Sdimconst char *DWARFUnit::getCompilationDir() { 111259698Sdim extractDIEsIfNeeded(true); 112259698Sdim if (DieArray.empty()) 113259698Sdim return 0; 114259698Sdim return DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); 115259698Sdim} 116259698Sdim 117259698Sdimuint64_t DWARFUnit::getDWOId() { 118259698Sdim extractDIEsIfNeeded(true); 119259698Sdim const uint64_t FailValue = -1ULL; 120259698Sdim if (DieArray.empty()) 121259698Sdim return FailValue; 122259698Sdim return DieArray[0] 123259698Sdim .getAttributeValueAsUnsignedConstant(this, DW_AT_GNU_dwo_id, FailValue); 124259698Sdim} 125259698Sdim 126259698Sdimvoid DWARFUnit::setDIERelations() { 127259698Sdim if (DieArray.empty()) 128259698Sdim return; 129259698Sdim DWARFDebugInfoEntryMinimal *die_array_begin = &DieArray.front(); 130259698Sdim DWARFDebugInfoEntryMinimal *die_array_end = &DieArray.back(); 131259698Sdim DWARFDebugInfoEntryMinimal *curr_die; 132259698Sdim // We purposely are skipping the last element in the array in the loop below 133259698Sdim // so that we can always have a valid next item 134259698Sdim for (curr_die = die_array_begin; curr_die < die_array_end; ++curr_die) { 135259698Sdim // Since our loop doesn't include the last element, we can always 136259698Sdim // safely access the next die in the array. 137259698Sdim DWARFDebugInfoEntryMinimal *next_die = curr_die + 1; 138259698Sdim 139259698Sdim const DWARFAbbreviationDeclaration *curr_die_abbrev = 140259698Sdim curr_die->getAbbreviationDeclarationPtr(); 141259698Sdim 142259698Sdim if (curr_die_abbrev) { 143259698Sdim // Normal DIE 144259698Sdim if (curr_die_abbrev->hasChildren()) 145259698Sdim next_die->setParent(curr_die); 146259698Sdim else 147259698Sdim curr_die->setSibling(next_die); 148259698Sdim } else { 149259698Sdim // NULL DIE that terminates a sibling chain 150259698Sdim DWARFDebugInfoEntryMinimal *parent = curr_die->getParent(); 151259698Sdim if (parent) 152259698Sdim parent->setSibling(next_die); 153259698Sdim } 154259698Sdim } 155259698Sdim 156259698Sdim // Since we skipped the last element, we need to fix it up! 157259698Sdim if (die_array_begin < die_array_end) 158259698Sdim curr_die->setParent(die_array_begin); 159259698Sdim} 160259698Sdim 161259698Sdimvoid DWARFUnit::extractDIEsToVector( 162259698Sdim bool AppendCUDie, bool AppendNonCUDies, 163259698Sdim std::vector<DWARFDebugInfoEntryMinimal> &Dies) const { 164259698Sdim if (!AppendCUDie && !AppendNonCUDies) 165259698Sdim return; 166259698Sdim 167259698Sdim // Set the offset to that of the first DIE and calculate the start of the 168259698Sdim // next compilation unit header. 169259698Sdim uint32_t Offset = getFirstDIEOffset(); 170259698Sdim uint32_t NextCUOffset = getNextUnitOffset(); 171259698Sdim DWARFDebugInfoEntryMinimal DIE; 172259698Sdim uint32_t Depth = 0; 173259698Sdim bool IsCUDie = true; 174259698Sdim 175259698Sdim while (Offset < NextCUOffset && DIE.extractFast(this, &Offset)) { 176259698Sdim if (IsCUDie) { 177259698Sdim if (AppendCUDie) 178259698Sdim Dies.push_back(DIE); 179259698Sdim if (!AppendNonCUDies) 180259698Sdim break; 181259698Sdim // The average bytes per DIE entry has been seen to be 182259698Sdim // around 14-20 so let's pre-reserve the needed memory for 183259698Sdim // our DIE entries accordingly. 184259698Sdim Dies.reserve(Dies.size() + getDebugInfoSize() / 14); 185259698Sdim IsCUDie = false; 186259698Sdim } else { 187259698Sdim Dies.push_back(DIE); 188259698Sdim } 189259698Sdim 190259698Sdim const DWARFAbbreviationDeclaration *AbbrDecl = 191259698Sdim DIE.getAbbreviationDeclarationPtr(); 192259698Sdim if (AbbrDecl) { 193259698Sdim // Normal DIE 194259698Sdim if (AbbrDecl->hasChildren()) 195259698Sdim ++Depth; 196259698Sdim } else { 197259698Sdim // NULL DIE. 198259698Sdim if (Depth > 0) 199259698Sdim --Depth; 200259698Sdim if (Depth == 0) 201259698Sdim break; // We are done with this compile unit! 202259698Sdim } 203259698Sdim } 204259698Sdim 205259698Sdim // Give a little bit of info if we encounter corrupt DWARF (our offset 206259698Sdim // should always terminate at or before the start of the next compilation 207259698Sdim // unit header). 208259698Sdim if (Offset > NextCUOffset) 209259698Sdim fprintf(stderr, "warning: DWARF compile unit extends beyond its " 210259698Sdim "bounds cu 0x%8.8x at 0x%8.8x'\n", getOffset(), Offset); 211259698Sdim} 212259698Sdim 213259698Sdimsize_t DWARFUnit::extractDIEsIfNeeded(bool CUDieOnly) { 214259698Sdim if ((CUDieOnly && DieArray.size() > 0) || 215259698Sdim DieArray.size() > 1) 216259698Sdim return 0; // Already parsed. 217259698Sdim 218259698Sdim bool HasCUDie = DieArray.size() > 0; 219259698Sdim extractDIEsToVector(!HasCUDie, !CUDieOnly, DieArray); 220259698Sdim 221259698Sdim if (DieArray.empty()) 222259698Sdim return 0; 223259698Sdim 224259698Sdim // If CU DIE was just parsed, copy several attribute values from it. 225259698Sdim if (!HasCUDie) { 226259698Sdim uint64_t BaseAddr = 227259698Sdim DieArray[0].getAttributeValueAsAddress(this, DW_AT_low_pc, -1ULL); 228259698Sdim if (BaseAddr == -1ULL) 229259698Sdim BaseAddr = DieArray[0].getAttributeValueAsAddress(this, DW_AT_entry_pc, 0); 230259698Sdim setBaseAddress(BaseAddr); 231259698Sdim AddrOffsetSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 232259698Sdim this, DW_AT_GNU_addr_base, 0); 233259698Sdim RangeSectionBase = DieArray[0].getAttributeValueAsSectionOffset( 234259698Sdim this, DW_AT_GNU_ranges_base, 0); 235259698Sdim } 236259698Sdim 237259698Sdim setDIERelations(); 238259698Sdim return DieArray.size(); 239259698Sdim} 240259698Sdim 241259698SdimDWARFUnit::DWOHolder::DWOHolder(object::ObjectFile *DWOFile) 242259698Sdim : DWOFile(DWOFile), 243259698Sdim DWOContext(cast<DWARFContext>(DIContext::getDWARFContext(DWOFile))), 244259698Sdim DWOU(0) { 245259698Sdim if (DWOContext->getNumDWOCompileUnits() > 0) 246259698Sdim DWOU = DWOContext->getDWOCompileUnitAtIndex(0); 247259698Sdim} 248259698Sdim 249259698Sdimbool DWARFUnit::parseDWO() { 250259698Sdim if (DWO.get() != 0) 251259698Sdim return false; 252259698Sdim extractDIEsIfNeeded(true); 253259698Sdim if (DieArray.empty()) 254259698Sdim return false; 255259698Sdim const char *DWOFileName = 256259698Sdim DieArray[0].getAttributeValueAsString(this, DW_AT_GNU_dwo_name, 0); 257259698Sdim if (DWOFileName == 0) 258259698Sdim return false; 259259698Sdim const char *CompilationDir = 260259698Sdim DieArray[0].getAttributeValueAsString(this, DW_AT_comp_dir, 0); 261259698Sdim SmallString<16> AbsolutePath; 262259698Sdim if (sys::path::is_relative(DWOFileName) && CompilationDir != 0) { 263259698Sdim sys::path::append(AbsolutePath, CompilationDir); 264259698Sdim } 265259698Sdim sys::path::append(AbsolutePath, DWOFileName); 266259698Sdim object::ObjectFile *DWOFile = 267259698Sdim object::ObjectFile::createObjectFile(AbsolutePath); 268259698Sdim if (!DWOFile) 269259698Sdim return false; 270259698Sdim // Reset DWOHolder. 271259698Sdim DWO.reset(new DWOHolder(DWOFile)); 272259698Sdim DWARFUnit *DWOCU = DWO->getUnit(); 273259698Sdim // Verify that compile unit in .dwo file is valid. 274259698Sdim if (DWOCU == 0 || DWOCU->getDWOId() != getDWOId()) { 275259698Sdim DWO.reset(); 276259698Sdim return false; 277259698Sdim } 278259698Sdim // Share .debug_addr and .debug_ranges section with compile unit in .dwo 279259698Sdim DWOCU->setAddrOffsetSection(AddrOffsetSection, AddrOffsetSectionBase); 280259698Sdim DWOCU->setRangesSection(RangeSection, RangeSectionBase); 281259698Sdim return true; 282259698Sdim} 283259698Sdim 284259698Sdimvoid DWARFUnit::clearDIEs(bool KeepCUDie) { 285259698Sdim if (DieArray.size() > (unsigned)KeepCUDie) { 286259698Sdim // std::vectors never get any smaller when resized to a smaller size, 287259698Sdim // or when clear() or erase() are called, the size will report that it 288259698Sdim // is smaller, but the memory allocated remains intact (call capacity() 289259698Sdim // to see this). So we need to create a temporary vector and swap the 290259698Sdim // contents which will cause just the internal pointers to be swapped 291259698Sdim // so that when temporary vector goes out of scope, it will destroy the 292259698Sdim // contents. 293259698Sdim std::vector<DWARFDebugInfoEntryMinimal> TmpArray; 294259698Sdim DieArray.swap(TmpArray); 295259698Sdim // Save at least the compile unit DIE 296259698Sdim if (KeepCUDie) 297259698Sdim DieArray.push_back(TmpArray.front()); 298259698Sdim } 299259698Sdim} 300259698Sdim 301259698Sdimvoid 302259698SdimDWARFUnit::buildAddressRangeTable(DWARFDebugAranges *debug_aranges, 303259698Sdim bool clear_dies_if_already_not_parsed, 304259698Sdim uint32_t CUOffsetInAranges) { 305259698Sdim // This function is usually called if there in no .debug_aranges section 306259698Sdim // in order to produce a compile unit level set of address ranges that 307259698Sdim // is accurate. If the DIEs weren't parsed, then we don't want all dies for 308259698Sdim // all compile units to stay loaded when they weren't needed. So we can end 309259698Sdim // up parsing the DWARF and then throwing them all away to keep memory usage 310259698Sdim // down. 311259698Sdim const bool clear_dies = extractDIEsIfNeeded(false) > 1 && 312259698Sdim clear_dies_if_already_not_parsed; 313259698Sdim DieArray[0].buildAddressRangeTable(this, debug_aranges, CUOffsetInAranges); 314259698Sdim bool DWOCreated = parseDWO(); 315259698Sdim if (DWO.get()) { 316259698Sdim // If there is a .dwo file for this compile unit, then skeleton CU DIE 317259698Sdim // doesn't have children, and we should instead build address range table 318259698Sdim // from DIEs in the .debug_info.dwo section of .dwo file. 319259698Sdim DWO->getUnit()->buildAddressRangeTable( 320259698Sdim debug_aranges, clear_dies_if_already_not_parsed, CUOffsetInAranges); 321259698Sdim } 322259698Sdim if (DWOCreated && clear_dies_if_already_not_parsed) 323259698Sdim DWO.reset(); 324259698Sdim 325259698Sdim // Keep memory down by clearing DIEs if this generate function 326259698Sdim // caused them to be parsed. 327259698Sdim if (clear_dies) 328259698Sdim clearDIEs(true); 329259698Sdim} 330259698Sdim 331259698Sdimconst DWARFDebugInfoEntryMinimal * 332259698SdimDWARFUnit::getSubprogramForAddress(uint64_t Address) { 333259698Sdim extractDIEsIfNeeded(false); 334259698Sdim for (size_t i = 0, n = DieArray.size(); i != n; i++) 335259698Sdim if (DieArray[i].isSubprogramDIE() && 336259698Sdim DieArray[i].addressRangeContainsAddress(this, Address)) { 337259698Sdim return &DieArray[i]; 338259698Sdim } 339259698Sdim return 0; 340259698Sdim} 341259698Sdim 342259698SdimDWARFDebugInfoEntryInlinedChain 343259698SdimDWARFUnit::getInlinedChainForAddress(uint64_t Address) { 344259698Sdim // First, find a subprogram that contains the given address (the root 345259698Sdim // of inlined chain). 346259698Sdim const DWARFUnit *ChainCU = 0; 347259698Sdim const DWARFDebugInfoEntryMinimal *SubprogramDIE = 348259698Sdim getSubprogramForAddress(Address); 349259698Sdim if (SubprogramDIE) { 350259698Sdim ChainCU = this; 351259698Sdim } else { 352259698Sdim // Try to look for subprogram DIEs in the DWO file. 353259698Sdim parseDWO(); 354259698Sdim if (DWO.get()) { 355259698Sdim SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); 356259698Sdim if (SubprogramDIE) 357259698Sdim ChainCU = DWO->getUnit(); 358259698Sdim } 359259698Sdim } 360259698Sdim 361259698Sdim // Get inlined chain rooted at this subprogram DIE. 362259698Sdim if (!SubprogramDIE) 363259698Sdim return DWARFDebugInfoEntryInlinedChain(); 364259698Sdim return SubprogramDIE->getInlinedChainForAddress(ChainCU, Address); 365259698Sdim} 366