void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
- /// Get inlined chain for a given address, rooted at the current DIE.
- /// Returns empty chain if address is not contained in address range
- /// of current DIE.
- void
- getInlinedChainForAddress(const uint64_t Address,
- SmallVectorImpl<DWARFDie> &InlinedChain) const;
-
class attribute_iterator;
/// Get an iterator range to all attributes in the current DIE only.
#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();
- /// getSubprogramForAddress - Returns subprogram DIE with address range
+ /// getSubroutineForAddress - 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 getSubprogramForAddress(uint64_t Address);
+ DWARFDie getSubroutineForAddress(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);
}
-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
+ // First, find the subroutine that contains the given address (the leaf
// of inlined chain).
- DWARFDie SubprogramDIE;
+ DWARFDie SubroutineDIE;
// Try to look for subprogram DIEs in the DWO file.
parseDWO();
if (DWO)
- SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
+ SubroutineDIE = DWO->getUnit()->getSubroutineForAddress(Address);
else
- SubprogramDIE = getSubprogramForAddress(Address);
+ SubroutineDIE = getSubroutineForAddress(Address);
- // Get inlined chain rooted at this subprogram DIE.
- if (SubprogramDIE)
- SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
- else
+ if (SubroutineDIE) {
+ while (SubroutineDIE) {
+ if (SubroutineDIE.isSubroutineDIE())
+ InlinedChain.push_back(SubroutineDIE);
+ SubroutineDIE = SubroutineDIE.getParent();
+ }
+ } else
InlinedChain.clear();
}
--- /dev/null
+; REQUIRES: x86_64-linux
+; Checks if symbolizer can correctly symbolize address in the padding between
+; functions.
+; RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %s
+; RUN: echo 0x5 | llvm-symbolizer -obj=%t.o | FileCheck %s --check-prefix=FOO
+; RUN: echo 0xd | llvm-symbolizer -obj=%t.o | FileCheck %s --check-prefix=PADDING
+; RUN: echo 0x10 | llvm-symbolizer -obj=%t.o | FileCheck %s --check-prefix=MAIN
+
+;FOO: foo
+;PADDING: ??
+;MAIN: main
+
+@a = global i32 1, align 4
+
+define i32 @foo() !dbg !9 {
+entry:
+ %0 = load i32, i32* @a, align 4
+ ret i32 %0
+}
+
+define i32 @main() !dbg !14 {
+entry:
+ %call = call i32 @foo(), !dbg !18
+ ret i32 %call
+}
+
+!llvm.dbg.cu = !{!0}
+!llvm.module.flags = !{!6, !7}
+
+!0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
+!1 = !DIFile(filename: "padding-x86_64.c", directory: "/tmp/")
+!2 = !{}
+!5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
+!6 = !{i32 2, !"Dwarf Version", i32 4}
+!7 = !{i32 2, !"Debug Info Version", i32 3}
+!9 = distinct !DISubprogram(name: "foo", scope: !1, file: !1, line: 2, type: !10, isLocal: false, isDefinition: true, scopeLine: 2, isOptimized: false, unit: !0, variables: !2)
+!10 = !DISubroutineType(types: !11)
+!11 = !{!5}
+!14 = distinct !DISubprogram(name: "main", scope: !1, file: !1, line: 6, type: !10, isLocal: false, isDefinition: true, scopeLine: 6, isOptimized: false, unit: !0, variables: !2)
+!18 = !DILocation(line: 7, column: 8, scope: !14)