github.com/nikandfor/loc@v0.5.1/name_file_line_go1.16.go (about) 1 //go:build nikandfor_loc_unsafe && go1.16 && !go1.17 2 // +build nikandfor_loc_unsafe,go1.16,!go1.17 3 4 package loc 5 6 import "unsafe" 7 8 func (l PC) nameFileLine() (name, file string, line int) { 9 if l == 0 { 10 return 11 } 12 13 funcInfo := findfunc(l) 14 if funcInfo.entry == nil { 15 return 16 } 17 18 if uintptr(l) > *funcInfo.entry { 19 // We store the pc of the start of the instruction following 20 // the instruction in question (the call or the inline mark). 21 // This is done for historical reasons, and to make FuncForPC 22 // work correctly for entries in the result of runtime.Callers. 23 l-- 24 } 25 26 name = funcname(funcInfo) 27 if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil { 28 ix := pcdatavalue1(funcInfo, _PCDATA_InlTreeIndex, l, nil, false) 29 if ix >= 0 { 30 inltree := (*[1 << 20]inlinedCall)(inldata) 31 // Note: entry is not modified. It always refers to a real frame, not an inlined one. 32 name = funcnameFromNameoff(funcInfo, inltree[ix].func_) 33 // File/line is already correct. 34 // TODO: remove file/line from InlinedCall? 35 } 36 } 37 38 file, line32 := funcline1(funcInfo, l, false) 39 line = int(line32) 40 41 return 42 } 43 44 //go:linkname findfunc runtime.findfunc 45 func findfunc(pc PC) funcInfo 46 47 //go:linkname funcline1 runtime.funcline1 48 func funcline1(f funcInfo, targetpc PC, strict bool) (file string, line int32) 49 50 //go:linkname funcname runtime.funcname 51 func funcname(f funcInfo) string 52 53 //go:linkname funcdata runtime.funcdata 54 func funcdata(f funcInfo, i uint8) unsafe.Pointer 55 56 //go:linkname pcdatavalue1 runtime.pcdatavalue1 57 func pcdatavalue1(f funcInfo, table int32, targetpc PC, cache unsafe.Pointer, strict bool) int32 58 59 //go:linkname funcnameFromNameoff runtime.funcnameFromNameoff 60 func funcnameFromNameoff(f funcInfo, nameoff int32) string