diff options
Diffstat (limited to 'lib/DebugInfo/DWARF')
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFContext.cpp | 6 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFDie.cpp | 30 | ||||
-rw-r--r-- | lib/DebugInfo/DWARF/DWARFUnit.cpp | 70 |
3 files changed, 55 insertions, 51 deletions
diff --git a/lib/DebugInfo/DWARF/DWARFContext.cpp b/lib/DebugInfo/DWARF/DWARFContext.cpp index cbce2dc89debe..bbb19b5e998da 100644 --- a/lib/DebugInfo/DWARF/DWARFContext.cpp +++ b/lib/DebugInfo/DWARF/DWARFContext.cpp @@ -579,7 +579,7 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address, return InliningInfo; } - uint32_t CallFile = 0, CallLine = 0, CallColumn = 0; + uint32_t CallFile = 0, CallLine = 0, CallColumn = 0, CallDiscriminator = 0; for (uint32_t i = 0, n = InlinedChain.size(); i != n; i++) { DWARFDie &FunctionDIE = InlinedChain[i]; DILineInfo Frame; @@ -605,10 +605,12 @@ DWARFContext::getInliningInfoForAddress(uint64_t Address, Spec.FLIKind, Frame.FileName); Frame.Line = CallLine; Frame.Column = CallColumn; + Frame.Discriminator = CallDiscriminator; } // Get call file/line/column of a current DIE. if (i + 1 < n) { - FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn); + FunctionDIE.getCallerFrame(CallFile, CallLine, CallColumn, + CallDiscriminator); } } InliningInfo.addFrame(Frame); diff --git a/lib/DebugInfo/DWARF/DWARFDie.cpp b/lib/DebugInfo/DWARF/DWARFDie.cpp index 4308cc2e26396..24039eb35209a 100644 --- a/lib/DebugInfo/DWARF/DWARFDie.cpp +++ b/lib/DebugInfo/DWARF/DWARFDie.cpp @@ -290,10 +290,12 @@ uint64_t DWARFDie::getDeclLine() const { } void DWARFDie::getCallerFrame(uint32_t &CallFile, uint32_t &CallLine, - uint32_t &CallColumn) const { + uint32_t &CallColumn, + uint32_t &CallDiscriminator) const { CallFile = toUnsigned(find(DW_AT_call_file), 0); CallLine = toUnsigned(find(DW_AT_call_line), 0); CallColumn = toUnsigned(find(DW_AT_call_column), 0); + CallDiscriminator = toUnsigned(find(DW_AT_GNU_discriminator), 0); } void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, @@ -350,32 +352,6 @@ void DWARFDie::dump(raw_ostream &OS, unsigned RecurseDepth, } } -void DWARFDie::getInlinedChainForAddress( - const uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) const { - if (isNULL()) - return; - DWARFDie DIE(*this); - while (DIE) { - // Append current DIE to inlined chain only if it has correct tag - // (e.g. it is not a lexical block). - if (DIE.isSubroutineDIE()) - InlinedChain.push_back(DIE); - - // Try to get child which also contains provided address. - DWARFDie Child = DIE.getFirstChild(); - while (Child) { - if (Child.addressRangeContainsAddress(Address)) { - // Assume there is only one such child. - break; - } - Child = Child.getSibling(); - } - DIE = Child; - } - // Reverse the obtained chain to make the root of inlined chain last. - std::reverse(InlinedChain.begin(), InlinedChain.end()); -} - DWARFDie DWARFDie::getParent() const { if (isValid()) return U->getParent(Die); diff --git a/lib/DebugInfo/DWARF/DWARFUnit.cpp b/lib/DebugInfo/DWARF/DWARFUnit.cpp index 4ee8e8f46d2eb..c3f467745402f 100644 --- a/lib/DebugInfo/DWARF/DWARFUnit.cpp +++ b/lib/DebugInfo/DWARF/DWARFUnit.cpp @@ -343,37 +343,63 @@ void DWARFUnit::collectAddressRanges(DWARFAddressRangesVector &CURanges) { clearDIEs(true); } -DWARFDie -DWARFUnit::getSubprogramForAddress(uint64_t Address) { - extractDIEsIfNeeded(false); - for (const DWARFDebugInfoEntry &D : DieArray) { - DWARFDie DIE(this, &D); - if (DIE.isSubprogramDIE() && - DIE.addressRangeContainsAddress(Address)) { - return DIE; +void DWARFUnit::updateAddressDieMap(DWARFDie Die) { + if (Die.isSubroutineDIE()) { + for (const auto &R : Die.getAddressRanges()) { + // Ignore 0-sized ranges. + if (R.first == R.second) + continue; + auto B = AddrDieMap.upper_bound(R.first); + if (B != AddrDieMap.begin() && R.first < (--B)->second.first) { + // The range is a sub-range of existing ranges, we need to split the + // existing range. + if (R.second < B->second.first) + AddrDieMap[R.second] = B->second; + if (R.first > B->first) + AddrDieMap[B->first].first = R.first; + } + AddrDieMap[R.first] = std::make_pair(R.second, Die); } } - return DWARFDie(); + // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to + // simplify the logic to update AddrDieMap. The child's range will always + // be equal or smaller than the parent's range. With this assumption, when + // adding one range into the map, it will at most split a range into 3 + // sub-ranges. + for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling()) + updateAddressDieMap(Child); +} + +DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) { + extractDIEsIfNeeded(false); + if (AddrDieMap.empty()) + updateAddressDieMap(getUnitDIE()); + auto R = AddrDieMap.upper_bound(Address); + if (R == AddrDieMap.begin()) + return DWARFDie(); + // upper_bound's previous item contains Address. + --R; + if (Address >= R->second.first) + return DWARFDie(); + return R->second.second; } void DWARFUnit::getInlinedChainForAddress(uint64_t Address, SmallVectorImpl<DWARFDie> &InlinedChain) { - // First, find a subprogram that contains the given address (the root - // of inlined chain). - DWARFDie SubprogramDIE; + assert(InlinedChain.empty()); // Try to look for subprogram DIEs in the DWO file. parseDWO(); - if (DWO) - SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address); - else - SubprogramDIE = getSubprogramForAddress(Address); - - // Get inlined chain rooted at this subprogram DIE. - if (SubprogramDIE) - SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain); - else - InlinedChain.clear(); + // First, find the subroutine that contains the given address (the leaf + // of inlined chain). + DWARFDie SubroutineDIE = + (DWO ? DWO->getUnit() : this)->getSubroutineForAddress(Address); + + while (SubroutineDIE) { + if (SubroutineDIE.isSubroutineDIE()) + InlinedChain.push_back(SubroutineDIE); + SubroutineDIE = SubroutineDIE.getParent(); + } } const DWARFUnitIndex &llvm::getDWARFUnitIndex(DWARFContext &Context, |