llvm.org GIT mirror llvm / fd134f7
Using address range map to speedup finding inline stack for address. Summary: In the current implementation, to find inline stack for an address incurs expensive linear search in 2 places: * linear search for the top-level DIE * recursive linear traverse the DIE tree to find the path to the leaf DIE In this patch, a map is built from address to its corresponding leaf DIE. The inline stack is built by traversing from the leaf DIE up to the root DIE. This speeds up batch symbolization by ~10X without noticible memory overhead. Reviewers: dblaikie Reviewed By: dblaikie Subscribers: llvm-commits Differential Revision: https://reviews.llvm.org/D32177 git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@300742 91177308-0d34-0410-b5e6-96231b3b80d8 Dehao Chen 2 years ago
5 changed file(s) with 101 addition(s) and 54 deletion(s). Raw diff Collapse all Expand all
251251 void getCallerFrame(uint32_t &CallFile, uint32_t &CallLine,
252252 uint32_t &CallColumn, uint32_t &CallDiscriminator) const;
253253
254 /// Get inlined chain for a given address, rooted at the current DIE.
255 /// Returns empty chain if address is not contained in address range
256 /// of current DIE.
257 void
258 getInlinedChainForAddress(const uint64_t Address,
259 SmallVectorImpl &InlinedChain) const;
260
261254 class attribute_iterator;
262255
263256 /// Get an iterator range to all attributes in the current DIE only.
3030 #include
3131 #include
3232 #include
33 #include
3334
3435 namespace llvm {
3536
133134 uint64_t BaseAddr;
134135 // The compile unit debug information entry items.
135136 std::vector DieArray;
137
138 // Map from range's start address to end address and corresponding DIE.
139 // IntervalMap does not support range removal, as a result, we use the
140 // std::map::upper_bound for address range lookup.
141 std::map> AddrDieMap;
136142 typedef iterator_range::iterator>
137143 die_iterator_range;
138144
181187 AddrOffsetSection = AOS;
182188 AddrOffsetSectionBase = Base;
183189 }
190
191 // Recursively update address to Die map.
192 void updateAddressDieMap(DWARFDie Die);
184193
185194 void setRangesSection(StringRef RS, uint32_t Base) {
186195 RangeSection = RS;
338347 /// it was actually constructed.
339348 bool parseDWO();
340349
341 /// getSubprogramForAddress - Returns subprogram DIE with address range
350 /// getSubroutineForAddress - Returns subprogram DIE with address range
342351 /// encompassing the provided address. The pointer is alive as long as parsed
343352 /// compile unit DIEs are not cleared.
344 DWARFDie getSubprogramForAddress(uint64_t Address);
353 DWARFDie getSubroutineForAddress(uint64_t Address);
345354 };
346355
347356 } // end namespace llvm
351351 }
352352 }
353353
354 void DWARFDie::getInlinedChainForAddress(
355 const uint64_t Address, SmallVectorImpl &InlinedChain) const {
356 if (isNULL())
357 return;
358 DWARFDie DIE(*this);
359 while (DIE) {
360 // Append current DIE to inlined chain only if it has correct tag
361 // (e.g. it is not a lexical block).
362 if (DIE.isSubroutineDIE())
363 InlinedChain.push_back(DIE);
364
365 // Try to get child which also contains provided address.
366 DWARFDie Child = DIE.getFirstChild();
367 while (Child) {
368 if (Child.addressRangeContainsAddress(Address)) {
369 // Assume there is only one such child.
370 break;
371 }
372 Child = Child.getSibling();
373 }
374 DIE = Child;
375 }
376 // Reverse the obtained chain to make the root of inlined chain last.
377 std::reverse(InlinedChain.begin(), InlinedChain.end());
378 }
379
380354 DWARFDie DWARFDie::getParent() const {
381355 if (isValid())
382356 return U->getParent(Die);
342342 clearDIEs(true);
343343 }
344344
345 DWARFDie
346 DWARFUnit::getSubprogramForAddress(uint64_t Address) {
345 void DWARFUnit::updateAddressDieMap(DWARFDie Die) {
346 if (Die.isSubroutineDIE()) {
347 for (const auto &R : Die.getAddressRanges()) {
348 // Ignore 0-sized ranges.
349 if (R.first == R.second)
350 continue;
351 auto B = AddrDieMap.upper_bound(R.first);
352 if (B != AddrDieMap.begin() && R.first < (--B)->second.first) {
353 // The range is a sub-range of existing ranges, we need to split the
354 // existing range.
355 if (R.second < B->second.first)
356 AddrDieMap[R.second] = B->second;
357 if (R.first > B->first)
358 AddrDieMap[B->first].first = R.first;
359 }
360 AddrDieMap[R.first] = std::make_pair(R.second, Die);
361 }
362 }
363 // Parent DIEs are added to the AddrDieMap prior to the Children DIEs to
364 // simplify the logic to update AddrDieMap. The child's range will always
365 // be equal or smaller than the parent's range. With this assumption, when
366 // adding one range into the map, it will at most split a range into 3
367 // sub-ranges.
368 for (DWARFDie Child = Die.getFirstChild(); Child; Child = Child.getSibling())
369 updateAddressDieMap(Child);
370 }
371
372 DWARFDie DWARFUnit::getSubroutineForAddress(uint64_t Address) {
347373 extractDIEsIfNeeded(false);
348 for (const DWARFDebugInfoEntry &D : DieArray) {
349 DWARFDie DIE(this, &D);
350 if (DIE.isSubprogramDIE() &&
351 DIE.addressRangeContainsAddress(Address)) {
352 return DIE;
353 }
354 }
355 return DWARFDie();
374 if (AddrDieMap.empty())
375 updateAddressDieMap(getUnitDIE());
376 auto R = AddrDieMap.upper_bound(Address);
377 if (R == AddrDieMap.begin())
378 return DWARFDie();
379 // upper_bound's previous item contains Address.
380 --R;
381 if (Address >= R->second.first)
382 return DWARFDie();
383 return R->second.second;
356384 }
357385
358386 void
359387 DWARFUnit::getInlinedChainForAddress(uint64_t Address,
360388 SmallVectorImpl &InlinedChain) {
361 // First, find a subprogram that contains the given address (the root
389 // First, find the subroutine that contains the given address (the leaf
362390 // of inlined chain).
363 DWARFDie SubprogramDIE;
391 DWARFDie SubroutineDIE;
364392 // Try to look for subprogram DIEs in the DWO file.
365393 parseDWO();
366394 if (DWO)
367 SubprogramDIE = DWO->getUnit()->getSubprogramForAddress(Address);
395 SubroutineDIE = DWO->getUnit()->getSubroutineForAddress(Address);
368396 else
369 SubprogramDIE = getSubprogramForAddress(Address);
370
371 // Get inlined chain rooted at this subprogram DIE.
372 if (SubprogramDIE)
373 SubprogramDIE.getInlinedChainForAddress(Address, InlinedChain);
374 else
397 SubroutineDIE = getSubroutineForAddress(Address);
398
399 if (SubroutineDIE) {
400 while (SubroutineDIE) {
401 if (SubroutineDIE.isSubroutineDIE())
402 InlinedChain.push_back(SubroutineDIE);
403 SubroutineDIE = SubroutineDIE.getParent();
404 }
405 } else
375406 InlinedChain.clear();
376407 }
377408
0 ; REQUIRES: x86_64-linux
1 ; Checks if symbolizer can correctly symbolize address in the padding between
2 ; functions.
3 ; RUN: llc -o %t.o -filetype=obj -mtriple=x86_64-pc-linux %s
4 ; RUN: echo 0x5 | llvm-symbolizer -obj=%t.o | FileCheck %s --check-prefix=FOO
5 ; RUN: echo 0xd | llvm-symbolizer -obj=%t.o | FileCheck %s --check-prefix=PADDING
6 ; RUN: echo 0x10 | llvm-symbolizer -obj=%t.o | FileCheck %s --check-prefix=MAIN
7
8 ;FOO: foo
9 ;PADDING: ??
10 ;MAIN: main
11
12 @a = global i32 1, align 4
13
14 define i32 @foo() !dbg !9 {
15 entry:
16 %0 = load i32, i32* @a, align 4
17 ret i32 %0
18 }
19
20 define i32 @main() !dbg !14 {
21 entry:
22 %call = call i32 @foo(), !dbg !18
23 ret i32 %call
24 }
25
26 !llvm.dbg.cu = !{!0}
27 !llvm.module.flags = !{!6, !7}
28
29 !0 = distinct !DICompileUnit(language: DW_LANG_C99, file: !1, producer: "clang", isOptimized: false, runtimeVersion: 0, emissionKind: FullDebug, enums: !2)
30 !1 = !DIFile(filename: "padding-x86_64.c", directory: "/tmp/")
31 !2 = !{}
32 !5 = !DIBasicType(name: "int", size: 32, align: 32, encoding: DW_ATE_signed)
33 !6 = !{i32 2, !"Dwarf Version", i32 4}
34 !7 = !{i32 2, !"Debug Info Version", i32 3}
35 !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)
36 !10 = !DISubroutineType(types: !11)
37 !11 = !{!5}
38 !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)
39 !18 = !DILocation(line: 7, column: 8, scope: !14)