github.com/pyroscope-io/pyroscope@v0.37.3-0.20230725203016-5f6947968bd0/pkg/agent/ebpfspy/symbols_linux.go (about) 1 //go:build ebpfspy 2 // +build ebpfspy 3 4 // Package ebpfspy provides integration with Linux eBPF. It is a rough copy of profile.py from BCC tools: 5 // 6 // https://github.com/iovisor/bcc/blob/master/tools/profile.py 7 package ebpfspy 8 9 import "C" 10 import ( 11 "fmt" 12 "github.com/pyroscope-io/pyroscope/pkg/agent/ebpfspy/symtab" 13 "github.com/pyroscope-io/pyroscope/pkg/util/genericlru" 14 "sync" 15 ) 16 17 type symbolCacheEntry struct { 18 symbolTable symtab.SymbolTable 19 roundNumber int 20 } 21 type pidKey uint32 22 23 type symbolCache struct { 24 pid2Cache *genericlru.GenericLRU[pidKey, symbolCacheEntry] 25 mutex sync.Mutex 26 } 27 28 func newSymbolCache(cacheSize int) (*symbolCache, error) { 29 pid2Cache, err := genericlru.NewGenericLRU[pidKey, symbolCacheEntry](cacheSize, func(pid pidKey, e *symbolCacheEntry) { 30 e.symbolTable.Close() 31 }) 32 if err != nil { 33 return nil, err 34 } 35 return &symbolCache{ 36 pid2Cache: pid2Cache, 37 }, nil 38 } 39 40 func (sc *symbolCache) bccResolve(pid uint32, addr uint64, roundNumber int) symtab.Symbol { 41 e := sc.getOrCreateCacheEntry(pidKey(pid)) 42 staleCheck := false 43 if roundNumber != e.roundNumber { 44 e.roundNumber = roundNumber 45 staleCheck = true 46 } 47 return e.symbolTable.Resolve(addr, staleCheck) 48 } 49 50 func (sc *symbolCache) getOrCreateCacheEntry(pid pidKey) *symbolCacheEntry { 51 sc.mutex.Lock() 52 defer sc.mutex.Unlock() 53 if cache, ok := sc.pid2Cache.Get(pid); ok { 54 return cache 55 } 56 var symbolTable symtab.SymbolTable 57 exe := fmt.Sprintf("/proc/%d/exe", pid) 58 bcc := func() symtab.SymbolTable { 59 return symtab.NewBCCSymbolTable(int(pid)) 60 } 61 symbolTable, err := symtab.NewGoSymbolTable(exe, &bcc) 62 if err != nil || symbolTable == nil { 63 symbolTable = bcc() 64 } 65 e := &symbolCacheEntry{symbolTable: symbolTable} 66 sc.pid2Cache.Add(pid, e) 67 return e 68 } 69 70 func (sc *symbolCache) clear() { 71 sc.mutex.Lock() 72 defer sc.mutex.Unlock() 73 for _, pid := range sc.pid2Cache.Keys() { 74 sc.pid2Cache.Remove(pid) 75 } 76 }