github.com/nikandfor/loc@v0.5.1/unsafe.go (about) 1 package loc 2 3 import ( 4 "reflect" 5 "runtime" 6 "sync" 7 "unsafe" 8 ) 9 10 type ( 11 nfl struct { 12 name string 13 file string 14 line int 15 } 16 ) 17 18 var ( 19 locmu sync.Mutex 20 locc = map[PC]nfl{} 21 ) 22 23 //go:noescape 24 //go:linkname callers runtime.callers 25 func callers(skip int, pc []PC) int 26 27 //go:noescape 28 //go:linkname caller1 runtime.callers 29 func caller1(skip int, pc *PC, len, cap int) int //nolint:predeclared 30 31 //go:linkname callersFrames runtime.CallersFrames 32 func callersFrames(pcs PCs) *runtime.Frames 33 34 // NameFileLine returns function name, file and line number for location. 35 // 36 // This works only in the same binary where location was captured. 37 // 38 // This functions is a little bit modified version of runtime.(*Frames).Next(). 39 func (l PC) NameFileLine() (name, file string, line int) { 40 if l == 0 { 41 return 42 } 43 44 locmu.Lock() 45 c, ok := locc[l] 46 locmu.Unlock() 47 if ok { 48 return c.name, c.file, c.line 49 } 50 51 name, file, line = l.nameFileLine() 52 53 if file != "" { 54 file = cropFilename(file, name) 55 } 56 57 locmu.Lock() 58 locc[l] = nfl{ 59 name: name, 60 file: file, 61 line: line, 62 } 63 locmu.Unlock() 64 65 return 66 } 67 68 // SetCache sets name, file and line for the PC. 69 // It allows to work with PC in another binary the same as in original. 70 func SetCache(l PC, name, file string, line int) { 71 locmu.Lock() 72 if name == "" && file == "" && line == 0 { 73 delete(locc, l) 74 } else { 75 locc[l] = nfl{ 76 name: name, 77 file: file, 78 line: line, 79 } 80 } 81 locmu.Unlock() 82 } 83 84 func SetCacheBytes(l PC, name, file []byte, line int) { 85 locmu.Lock() 86 if name == nil && file == nil && line == 0 { 87 delete(locc, l) 88 } else { 89 x := locc[l] 90 91 if x.line != line || x.name != string(name) || x.file != string(file) { 92 locc[l] = nfl{ 93 name: string(name), 94 file: string(file), 95 line: line, 96 } 97 } 98 } 99 locmu.Unlock() 100 } 101 102 func Cached(l PC) (ok bool) { 103 locmu.Lock() 104 _, ok = locc[l] 105 locmu.Unlock() 106 return 107 } 108 109 func noescapeSlize(b *byte, l int) []byte { 110 return *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{ //nolint:govet 111 Data: uintptr(unsafe.Pointer(b)), 112 Len: 0, 113 Cap: l, 114 })) 115 }