#include <cstdint>
#include <memory>
#include <vector>
-#include <map>
namespace llvm {
uint64_t BaseAddr;
// The compile unit debug information entry items.
std::vector<DWARFDebugInfoEntry> DieArray;
-
- // Map from range's start address to end address and corresponding DIE.
- // IntervalMap does not support range removal, as a result, we use the
- // std::map::upper_bound for address range lookup.
- std::map<uint64_t, std::pair<uint64_t, DWARFDie>> AddrDieMap;
typedef iterator_range<std::vector<DWARFDebugInfoEntry>::iterator>
die_iterator_range;
AddrOffsetSectionBase = Base;
}
- // Recursively update address to Die map.
- void updateAddressDieMap(DWARFDie Die);
-
void setRangesSection(StringRef RS, uint32_t Base) {
RangeSection = RS;
RangeSectionBase = Base;
/// it was actually constructed.
bool parseDWO();
- /// getSubroutineForAddress - Returns subprogram DIE with address range
+ /// getSubprogramForAddress - Returns subprogram DIE with address range
/// encompassing the provided address. The pointer is alive as long as parsed
/// compile unit DIEs are not cleared.
- DWARFDie getSubroutineForAddress(uint64_t Address);
+ DWARFDie getSubprogramForAddress(uint64_t Address);
};
} // end namespace llvm
}
}
+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);
clearDIEs(true);
}
-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);
+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;
}
}
- // 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;
- assert(Address <= R->second.first);
- return R->second.second;
+ return DWARFDie();
}
void
DWARFUnit::getInlinedChainForAddress(uint64_t Address,
SmallVectorImpl<DWARFDie> &InlinedChain) {
- // First, find the subroutine that contains the given address (the leaf
+ // First, find a subprogram that contains the given address (the root
// of inlined chain).
- DWARFDie SubroutineDIE;
+ DWARFDie SubprogramDIE;
// Try to look for subprogram DIEs in the DWO file.
parseDWO();
if (DWO)
- SubroutineDIE = DWO->getUnit()->getSubroutineForAddress(Address);
+ SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
else
- SubroutineDIE = getSubroutineForAddress(Address);
+ SubprogramDIE = getSubprogramForAddress(Address);
- if (SubroutineDIE) {
- while (SubroutineDIE) {
- if (SubroutineDIE.isSubroutineDIE())
- InlinedChain.push_back(SubroutineDIE);
- SubroutineDIE = SubroutineDIE.getParent();
- }
- } else
+ // Get inlined chain rooted at this subprogram DIE.
+ if (SubprogramDIE)
+ SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
+ else
InlinedChain.clear();
}