@@ -32,12 +32,17 @@ type InlineInfo struct {
32
32
33
33
// DWARFInfo implements the liner interface
34
34
type DWARFInfo struct {
35
- debugData * dwarf.Data
36
- lineEntries map [dwarf.Offset ][]dwarf.LineEntry
37
- subprograms map [dwarf.Offset ][]* godwarf.Tree
38
- abstractSubprograms map [dwarf.Offset ]* dwarf.Entry
39
- addressMap map [uint64 ]* FunctionInfo // Quick address lookups
40
- functionMap map [string ]* FunctionRange // Function name lookups
35
+ debugData * dwarf.Data
36
+ lineEntries map [dwarf.Offset ][]dwarf.LineEntry
37
+ subprograms map [dwarf.Offset ][]* godwarf.Tree
38
+ abstractSubprograms map [dwarf.Offset ]* dwarf.Entry
39
+ addressMap map [uint64 ]* FunctionInfo // Quick address lookups
40
+ functionMap map [string ]* FunctionRange // Function name lookups
41
+ lineEntriesSorted map [dwarf.Offset ]bool
42
+ scannedAbstractSubprograms bool
43
+ lastRangeInfo * FunctionInfo
44
+ lastRangeStart uint64
45
+ lastRangeEnd uint64
41
46
}
42
47
43
48
// NewDWARFInfo creates a new liner using DWARF debug info
@@ -49,6 +54,7 @@ func NewDWARFInfo(debugData *dwarf.Data) *DWARFInfo {
49
54
abstractSubprograms : make (map [dwarf.Offset ]* dwarf.Entry ),
50
55
addressMap : make (map [uint64 ]* FunctionInfo ),
51
56
functionMap : make (map [string ]* FunctionRange ),
57
+ lineEntriesSorted : make (map [dwarf.Offset ]bool ),
52
58
}
53
59
}
54
60
@@ -94,7 +100,7 @@ func (d *DWARFInfo) ResolveAddress(_ context.Context, addr uint64) ([]SymbolLoca
94
100
declLine = 0
95
101
}
96
102
97
- file , line := d .findLineInfo (d .lineEntries [cu .Offset ], targetTree .Ranges )
103
+ file , line := d .findLineInfo (d .lineEntries [cu .Offset ], targetTree .Ranges , cu . Offset )
98
104
lines = append (lines , SymbolLocation {
99
105
Function : & pprof.Function {
100
106
Name : functionName ,
@@ -247,12 +253,16 @@ func (d *DWARFInfo) processSubprogramEntries(cu *dwarf.Entry) error {
247
253
return nil
248
254
}
249
255
250
- func (d * DWARFInfo ) findLineInfo (entries []dwarf.LineEntry , ranges [][2 ]uint64 ) (string , int64 ) {
251
- sort .Slice (entries , func (i , j int ) bool {
252
- return entries [i ].Address < entries [j ].Address
253
- })
256
+ func (d * DWARFInfo ) findLineInfo (entries []dwarf.LineEntry , ranges [][2 ]uint64 , cuOffset dwarf.Offset ) (string , int64 ) {
257
+ // Sort only once per compilation unit
258
+ if ! d .lineEntriesSorted [cuOffset ] {
259
+ sort .Slice (entries , func (i , j int ) bool {
260
+ return entries [i ].Address < entries [j ].Address
261
+ })
262
+ d .lineEntriesSorted [cuOffset ] = true
263
+ }
254
264
255
- // Try to find an entry that contains our target address
265
+ // Try to find an entry that contains the target address
256
266
targetAddr := ranges [0 ][0 ]
257
267
for _ , entry := range entries {
258
268
if entry .Address >= targetAddr && entry .Address < ranges [0 ][1 ] {
@@ -279,30 +289,48 @@ func (d *DWARFInfo) findLineInfo(entries []dwarf.LineEntry, ranges [][2]uint64)
279
289
}
280
290
281
291
func (d * DWARFInfo ) scanAbstractSubprograms () error {
292
+ if d .scannedAbstractSubprograms {
293
+ return nil
294
+ }
295
+
282
296
reader := d .debugData .Reader ()
283
- // Scan from the start, don't stop at first CU
284
297
for {
285
298
entry , err := reader .Next ()
286
299
if err != nil || entry == nil {
287
300
break
288
301
}
289
-
290
302
if entry .Tag == dwarf .TagSubprogram {
291
303
// Store ALL subprograms, not just inline ones
292
304
d .abstractSubprograms [entry .Offset ] = entry
293
305
}
294
306
}
307
+
308
+ d .scannedAbstractSubprograms = true
295
309
return nil
296
310
}
297
311
298
312
func (d * DWARFInfo ) resolveFromOptimizedMaps (addr uint64 ) ([]SymbolLocation , bool ) {
313
+ if info , found := d .addressMap [addr ]; found {
314
+ return info .Locations , true
315
+ }
316
+
317
+ // Use a simple caching mechanism for the last successful range lookup
318
+ if d .lastRangeInfo != nil &&
319
+ addr >= d .lastRangeStart && addr < d .lastRangeEnd {
320
+ return d .lastRangeInfo .Locations , true
321
+ }
322
+
299
323
for _ , info := range d .addressMap {
300
324
for _ , rang := range info .Ranges {
301
325
if addr >= rang .StartAddr && addr < rang .EndAddr {
326
+ d .lastRangeInfo = info
327
+ d .lastRangeStart = rang .StartAddr
328
+ d .lastRangeEnd = rang .EndAddr
302
329
return info .Locations , true
303
330
}
304
331
}
305
332
}
333
+
306
334
return nil , false
307
335
}
308
336
@@ -317,7 +345,7 @@ func (d *DWARFInfo) buildOptimizedMaps(cuOffset dwarf.Offset) error {
317
345
continue
318
346
}
319
347
320
- filename , line := d .findLineInfo (d .lineEntries [cuOffset ], tree .Ranges )
348
+ filename , line := d .findLineInfo (d .lineEntries [cuOffset ], tree .Ranges , cuOffset )
321
349
322
350
// Build locations once
323
351
locations := []SymbolLocation {{
@@ -375,7 +403,7 @@ func (d *DWARFInfo) processInlineFunctions(tree *godwarf.Tree, addr uint64, cuOf
375
403
continue
376
404
}
377
405
378
- filename , line := d .findLineInfo (d .lineEntries [cuOffset ], inline .Ranges )
406
+ filename , line := d .findLineInfo (d .lineEntries [cuOffset ], inline .Ranges , cuOffset )
379
407
inlines = append (inlines , InlineInfo {
380
408
Name : inlineName ,
381
409
File : filename ,
0 commit comments