...

Source file src/runtime/symtab.go

     1	// Copyright 2014 The Go Authors. All rights reserved.
     2	// Use of this source code is governed by a BSD-style
     3	// license that can be found in the LICENSE file.
     4	
     5	package runtime
     6	
     7	import (
     8		"runtime/internal/atomic"
     9		"runtime/internal/sys"
    10		"unsafe"
    11	)
    12	
    13	// Frames may be used to get function/file/line information for a
    14	// slice of PC values returned by Callers.
    15	type Frames struct {
    16		// callers is a slice of PCs that have not yet been expanded to frames.
    17		callers []uintptr
    18	
    19		// frames is a slice of Frames that have yet to be returned.
    20		frames     []Frame
    21		frameStore [2]Frame
    22	}
    23	
    24	// Frame is the information returned by Frames for each call frame.
    25	type Frame struct {
    26		// PC is the program counter for the location in this frame.
    27		// For a frame that calls another frame, this will be the
    28		// program counter of a call instruction. Because of inlining,
    29		// multiple frames may have the same PC value, but different
    30		// symbolic information.
    31		PC uintptr
    32	
    33		// Func is the Func value of this call frame. This may be nil
    34		// for non-Go code or fully inlined functions.
    35		Func *Func
    36	
    37		// Function is the package path-qualified function name of
    38		// this call frame. If non-empty, this string uniquely
    39		// identifies a single function in the program.
    40		// This may be the empty string if not known.
    41		// If Func is not nil then Function == Func.Name().
    42		Function string
    43	
    44		// File and Line are the file name and line number of the
    45		// location in this frame. For non-leaf frames, this will be
    46		// the location of a call. These may be the empty string and
    47		// zero, respectively, if not known.
    48		File string
    49		Line int
    50	
    51		// Entry point program counter for the function; may be zero
    52		// if not known. If Func is not nil then Entry ==
    53		// Func.Entry().
    54		Entry uintptr
    55	
    56		// The runtime's internal view of the function. This field
    57		// is set (funcInfo.valid() returns true) only for Go functions,
    58		// not for C functions.
    59		funcInfo funcInfo
    60	}
    61	
    62	// CallersFrames takes a slice of PC values returned by Callers and
    63	// prepares to return function/file/line information.
    64	// Do not change the slice until you are done with the Frames.
    65	func CallersFrames(callers []uintptr) *Frames {
    66		f := &Frames{callers: callers}
    67		f.frames = f.frameStore[:0]
    68		return f
    69	}
    70	
    71	// Next returns frame information for the next caller.
    72	// If more is false, there are no more callers (the Frame value is valid).
    73	func (ci *Frames) Next() (frame Frame, more bool) {
    74		for len(ci.frames) < 2 {
    75			// Find the next frame.
    76			// We need to look for 2 frames so we know what
    77			// to return for the "more" result.
    78			if len(ci.callers) == 0 {
    79				break
    80			}
    81			pc := ci.callers[0]
    82			ci.callers = ci.callers[1:]
    83			funcInfo := findfunc(pc)
    84			if !funcInfo.valid() {
    85				if cgoSymbolizer != nil {
    86					// Pre-expand cgo frames. We could do this
    87					// incrementally, too, but there's no way to
    88					// avoid allocation in this case anyway.
    89					ci.frames = append(ci.frames, expandCgoFrames(pc)...)
    90				}
    91				continue
    92			}
    93			f := funcInfo._Func()
    94			entry := f.Entry()
    95			if pc > entry {
    96				// We store the pc of the start of the instruction following
    97				// the instruction in question (the call or the inline mark).
    98				// This is done for historical reasons, and to make FuncForPC
    99				// work correctly for entries in the result of runtime.Callers.
   100				pc--
   101			}
   102			name := funcname(funcInfo)
   103			if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil {
   104				inltree := (*[1 << 20]inlinedCall)(inldata)
   105				ix := pcdatavalue(funcInfo, _PCDATA_InlTreeIndex, pc, nil)
   106				if ix >= 0 {
   107					// Note: entry is not modified. It always refers to a real frame, not an inlined one.
   108					f = nil
   109					name = funcnameFromNameoff(funcInfo, inltree[ix].func_)
   110					// File/line is already correct.
   111					// TODO: remove file/line from InlinedCall?
   112				}
   113			}
   114			ci.frames = append(ci.frames, Frame{
   115				PC:       pc,
   116				Func:     f,
   117				Function: name,
   118				Entry:    entry,
   119				funcInfo: funcInfo,
   120				// Note: File,Line set below
   121			})
   122		}
   123	
   124		// Pop one frame from the frame list. Keep the rest.
   125		// Avoid allocation in the common case, which is 1 or 2 frames.
   126		switch len(ci.frames) {
   127		case 0: // In the rare case when there are no frames at all, we return Frame{}.
   128			return
   129		case 1:
   130			frame = ci.frames[0]
   131			ci.frames = ci.frameStore[:0]
   132		case 2:
   133			frame = ci.frames[0]
   134			ci.frameStore[0] = ci.frames[1]
   135			ci.frames = ci.frameStore[:1]
   136		default:
   137			frame = ci.frames[0]
   138			ci.frames = ci.frames[1:]
   139		}
   140		more = len(ci.frames) > 0
   141		if frame.funcInfo.valid() {
   142			// Compute file/line just before we need to return it,
   143			// as it can be expensive. This avoids computing file/line
   144			// for the Frame we find but don't return. See issue 32093.
   145			file, line := funcline1(frame.funcInfo, frame.PC, false)
   146			frame.File, frame.Line = file, int(line)
   147		}
   148		return
   149	}
   150	
   151	// expandCgoFrames expands frame information for pc, known to be
   152	// a non-Go function, using the cgoSymbolizer hook. expandCgoFrames
   153	// returns nil if pc could not be expanded.
   154	func expandCgoFrames(pc uintptr) []Frame {
   155		arg := cgoSymbolizerArg{pc: pc}
   156		callCgoSymbolizer(&arg)
   157	
   158		if arg.file == nil && arg.funcName == nil {
   159			// No useful information from symbolizer.
   160			return nil
   161		}
   162	
   163		var frames []Frame
   164		for {
   165			frames = append(frames, Frame{
   166				PC:       pc,
   167				Func:     nil,
   168				Function: gostring(arg.funcName),
   169				File:     gostring(arg.file),
   170				Line:     int(arg.lineno),
   171				Entry:    arg.entry,
   172				// funcInfo is zero, which implies !funcInfo.valid().
   173				// That ensures that we use the File/Line info given here.
   174			})
   175			if arg.more == 0 {
   176				break
   177			}
   178			callCgoSymbolizer(&arg)
   179		}
   180	
   181		// No more frames for this PC. Tell the symbolizer we are done.
   182		// We don't try to maintain a single cgoSymbolizerArg for the
   183		// whole use of Frames, because there would be no good way to tell
   184		// the symbolizer when we are done.
   185		arg.pc = 0
   186		callCgoSymbolizer(&arg)
   187	
   188		return frames
   189	}
   190	
   191	// NOTE: Func does not expose the actual unexported fields, because we return *Func
   192	// values to users, and we want to keep them from being able to overwrite the data
   193	// with (say) *f = Func{}.
   194	// All code operating on a *Func must call raw() to get the *_func
   195	// or funcInfo() to get the funcInfo instead.
   196	
   197	// A Func represents a Go function in the running binary.
   198	type Func struct {
   199		opaque struct{} // unexported field to disallow conversions
   200	}
   201	
   202	func (f *Func) raw() *_func {
   203		return (*_func)(unsafe.Pointer(f))
   204	}
   205	
   206	func (f *Func) funcInfo() funcInfo {
   207		fn := f.raw()
   208		return funcInfo{fn, findmoduledatap(fn.entry)}
   209	}
   210	
   211	// PCDATA and FUNCDATA table indexes.
   212	//
   213	// See funcdata.h and ../cmd/internal/objabi/funcdata.go.
   214	const (
   215		_PCDATA_RegMapIndex   = 0
   216		_PCDATA_StackMapIndex = 1
   217		_PCDATA_InlTreeIndex  = 2
   218	
   219		_FUNCDATA_ArgsPointerMaps   = 0
   220		_FUNCDATA_LocalsPointerMaps = 1
   221		_FUNCDATA_RegPointerMaps    = 2
   222		_FUNCDATA_StackObjects      = 3
   223		_FUNCDATA_InlTree           = 4
   224	
   225		_ArgsSizeUnknown = -0x80000000
   226	)
   227	
   228	// A FuncID identifies particular functions that need to be treated
   229	// specially by the runtime.
   230	// Note that in some situations involving plugins, there may be multiple
   231	// copies of a particular special runtime function.
   232	// Note: this list must match the list in cmd/internal/objabi/funcid.go.
   233	type funcID uint8
   234	
   235	const (
   236		funcID_normal funcID = iota // not a special function
   237		funcID_runtime_main
   238		funcID_goexit
   239		funcID_jmpdefer
   240		funcID_mcall
   241		funcID_morestack
   242		funcID_mstart
   243		funcID_rt0_go
   244		funcID_asmcgocall
   245		funcID_sigpanic
   246		funcID_runfinq
   247		funcID_gcBgMarkWorker
   248		funcID_systemstack_switch
   249		funcID_systemstack
   250		funcID_cgocallback_gofunc
   251		funcID_gogo
   252		funcID_externalthreadhandler
   253		funcID_debugCallV1
   254		funcID_gopanic
   255		funcID_panicwrap
   256		funcID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
   257	)
   258	
   259	// moduledata records information about the layout of the executable
   260	// image. It is written by the linker. Any changes here must be
   261	// matched changes to the code in cmd/internal/ld/symtab.go:symtab.
   262	// moduledata is stored in statically allocated non-pointer memory;
   263	// none of the pointers here are visible to the garbage collector.
   264	type moduledata struct {
   265		pclntable    []byte
   266		ftab         []functab
   267		filetab      []uint32
   268		findfunctab  uintptr
   269		minpc, maxpc uintptr
   270	
   271		text, etext           uintptr
   272		noptrdata, enoptrdata uintptr
   273		data, edata           uintptr
   274		bss, ebss             uintptr
   275		noptrbss, enoptrbss   uintptr
   276		end, gcdata, gcbss    uintptr
   277		types, etypes         uintptr
   278	
   279		textsectmap []textsect
   280		typelinks   []int32 // offsets from types
   281		itablinks   []*itab
   282	
   283		ptab []ptabEntry
   284	
   285		pluginpath string
   286		pkghashes  []modulehash
   287	
   288		modulename   string
   289		modulehashes []modulehash
   290	
   291		hasmain uint8 // 1 if module contains the main function, 0 otherwise
   292	
   293		gcdatamask, gcbssmask bitvector
   294	
   295		typemap map[typeOff]*_type // offset to *_rtype in previous module
   296	
   297		bad bool // module failed to load and should be ignored
   298	
   299		next *moduledata
   300	}
   301	
   302	// A modulehash is used to compare the ABI of a new module or a
   303	// package in a new module with the loaded program.
   304	//
   305	// For each shared library a module links against, the linker creates an entry in the
   306	// moduledata.modulehashes slice containing the name of the module, the abi hash seen
   307	// at link time and a pointer to the runtime abi hash. These are checked in
   308	// moduledataverify1 below.
   309	//
   310	// For each loaded plugin, the pkghashes slice has a modulehash of the
   311	// newly loaded package that can be used to check the plugin's version of
   312	// a package against any previously loaded version of the package.
   313	// This is done in plugin.lastmoduleinit.
   314	type modulehash struct {
   315		modulename   string
   316		linktimehash string
   317		runtimehash  *string
   318	}
   319	
   320	// pinnedTypemaps are the map[typeOff]*_type from the moduledata objects.
   321	//
   322	// These typemap objects are allocated at run time on the heap, but the
   323	// only direct reference to them is in the moduledata, created by the
   324	// linker and marked SNOPTRDATA so it is ignored by the GC.
   325	//
   326	// To make sure the map isn't collected, we keep a second reference here.
   327	var pinnedTypemaps []map[typeOff]*_type
   328	
   329	var firstmoduledata moduledata  // linker symbol
   330	var lastmoduledatap *moduledata // linker symbol
   331	var modulesSlice *[]*moduledata // see activeModules
   332	
   333	// activeModules returns a slice of active modules.
   334	//
   335	// A module is active once its gcdatamask and gcbssmask have been
   336	// assembled and it is usable by the GC.
   337	//
   338	// This is nosplit/nowritebarrier because it is called by the
   339	// cgo pointer checking code.
   340	//go:nosplit
   341	//go:nowritebarrier
   342	func activeModules() []*moduledata {
   343		p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
   344		if p == nil {
   345			return nil
   346		}
   347		return *p
   348	}
   349	
   350	// modulesinit creates the active modules slice out of all loaded modules.
   351	//
   352	// When a module is first loaded by the dynamic linker, an .init_array
   353	// function (written by cmd/link) is invoked to call addmoduledata,
   354	// appending to the module to the linked list that starts with
   355	// firstmoduledata.
   356	//
   357	// There are two times this can happen in the lifecycle of a Go
   358	// program. First, if compiled with -linkshared, a number of modules
   359	// built with -buildmode=shared can be loaded at program initialization.
   360	// Second, a Go program can load a module while running that was built
   361	// with -buildmode=plugin.
   362	//
   363	// After loading, this function is called which initializes the
   364	// moduledata so it is usable by the GC and creates a new activeModules
   365	// list.
   366	//
   367	// Only one goroutine may call modulesinit at a time.
   368	func modulesinit() {
   369		modules := new([]*moduledata)
   370		for md := &firstmoduledata; md != nil; md = md.next {
   371			if md.bad {
   372				continue
   373			}
   374			*modules = append(*modules, md)
   375			if md.gcdatamask == (bitvector{}) {
   376				md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data)
   377				md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss)
   378			}
   379		}
   380	
   381		// Modules appear in the moduledata linked list in the order they are
   382		// loaded by the dynamic loader, with one exception: the
   383		// firstmoduledata itself the module that contains the runtime. This
   384		// is not always the first module (when using -buildmode=shared, it
   385		// is typically libstd.so, the second module). The order matters for
   386		// typelinksinit, so we swap the first module with whatever module
   387		// contains the main function.
   388		//
   389		// See Issue #18729.
   390		for i, md := range *modules {
   391			if md.hasmain != 0 {
   392				(*modules)[0] = md
   393				(*modules)[i] = &firstmoduledata
   394				break
   395			}
   396		}
   397	
   398		atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules))
   399	}
   400	
   401	type functab struct {
   402		entry   uintptr
   403		funcoff uintptr
   404	}
   405	
   406	// Mapping information for secondary text sections
   407	
   408	type textsect struct {
   409		vaddr    uintptr // prelinked section vaddr
   410		length   uintptr // section length
   411		baseaddr uintptr // relocated section address
   412	}
   413	
   414	const minfunc = 16                 // minimum function size
   415	const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table
   416	
   417	// findfunctab is an array of these structures.
   418	// Each bucket represents 4096 bytes of the text segment.
   419	// Each subbucket represents 256 bytes of the text segment.
   420	// To find a function given a pc, locate the bucket and subbucket for
   421	// that pc. Add together the idx and subbucket value to obtain a
   422	// function index. Then scan the functab array starting at that
   423	// index to find the target function.
   424	// This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead.
   425	type findfuncbucket struct {
   426		idx        uint32
   427		subbuckets [16]byte
   428	}
   429	
   430	func moduledataverify() {
   431		for datap := &firstmoduledata; datap != nil; datap = datap.next {
   432			moduledataverify1(datap)
   433		}
   434	}
   435	
   436	const debugPcln = false
   437	
   438	func moduledataverify1(datap *moduledata) {
   439		// See golang.org/s/go12symtab for header: 0xfffffffb,
   440		// two zero bytes, a byte giving the PC quantum,
   441		// and a byte giving the pointer width in bytes.
   442		pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable))
   443		pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable))
   444		if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize {
   445			println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
   446			throw("invalid function symbol table\n")
   447		}
   448	
   449		// ftab is lookup table for function by program counter.
   450		nftab := len(datap.ftab) - 1
   451		for i := 0; i < nftab; i++ {
   452			// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
   453			if datap.ftab[i].entry > datap.ftab[i+1].entry {
   454				f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap}
   455				f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap}
   456				f2name := "end"
   457				if i+1 < nftab {
   458					f2name = funcname(f2)
   459				}
   460				println("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name)
   461				for j := 0; j <= i; j++ {
   462					print("\t", hex(datap.ftab[j].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}), "\n")
   463				}
   464				if GOOS == "aix" && isarchive {
   465					println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive")
   466				}
   467				throw("invalid runtime symbol table")
   468			}
   469		}
   470	
   471		if datap.minpc != datap.ftab[0].entry ||
   472			datap.maxpc != datap.ftab[nftab].entry {
   473			throw("minpc or maxpc invalid")
   474		}
   475	
   476		for _, modulehash := range datap.modulehashes {
   477			if modulehash.linktimehash != *modulehash.runtimehash {
   478				println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename)
   479				throw("abi mismatch")
   480			}
   481		}
   482	}
   483	
   484	// FuncForPC returns a *Func describing the function that contains the
   485	// given program counter address, or else nil.
   486	//
   487	// If pc represents multiple functions because of inlining, it returns
   488	// the a *Func describing the innermost function, but with an entry
   489	// of the outermost function.
   490	func FuncForPC(pc uintptr) *Func {
   491		f := findfunc(pc)
   492		if !f.valid() {
   493			return nil
   494		}
   495		if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil {
   496			// Note: strict=false so bad PCs (those between functions) don't crash the runtime.
   497			// We just report the preceding function in that situation. See issue 29735.
   498			// TODO: Perhaps we should report no function at all in that case.
   499			// The runtime currently doesn't have function end info, alas.
   500			if ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, pc, nil, false); ix >= 0 {
   501				inltree := (*[1 << 20]inlinedCall)(inldata)
   502				name := funcnameFromNameoff(f, inltree[ix].func_)
   503				file, line := funcline(f, pc)
   504				fi := &funcinl{
   505					entry: f.entry, // entry of the real (the outermost) function.
   506					name:  name,
   507					file:  file,
   508					line:  int(line),
   509				}
   510				return (*Func)(unsafe.Pointer(fi))
   511			}
   512		}
   513		return f._Func()
   514	}
   515	
   516	// Name returns the name of the function.
   517	func (f *Func) Name() string {
   518		if f == nil {
   519			return ""
   520		}
   521		fn := f.raw()
   522		if fn.entry == 0 { // inlined version
   523			fi := (*funcinl)(unsafe.Pointer(fn))
   524			return fi.name
   525		}
   526		return funcname(f.funcInfo())
   527	}
   528	
   529	// Entry returns the entry address of the function.
   530	func (f *Func) Entry() uintptr {
   531		fn := f.raw()
   532		if fn.entry == 0 { // inlined version
   533			fi := (*funcinl)(unsafe.Pointer(fn))
   534			return fi.entry
   535		}
   536		return fn.entry
   537	}
   538	
   539	// FileLine returns the file name and line number of the
   540	// source code corresponding to the program counter pc.
   541	// The result will not be accurate if pc is not a program
   542	// counter within f.
   543	func (f *Func) FileLine(pc uintptr) (file string, line int) {
   544		fn := f.raw()
   545		if fn.entry == 0 { // inlined version
   546			fi := (*funcinl)(unsafe.Pointer(fn))
   547			return fi.file, fi.line
   548		}
   549		// Pass strict=false here, because anyone can call this function,
   550		// and they might just be wrong about targetpc belonging to f.
   551		file, line32 := funcline1(f.funcInfo(), pc, false)
   552		return file, int(line32)
   553	}
   554	
   555	func findmoduledatap(pc uintptr) *moduledata {
   556		for datap := &firstmoduledata; datap != nil; datap = datap.next {
   557			if datap.minpc <= pc && pc < datap.maxpc {
   558				return datap
   559			}
   560		}
   561		return nil
   562	}
   563	
   564	type funcInfo struct {
   565		*_func
   566		datap *moduledata
   567	}
   568	
   569	func (f funcInfo) valid() bool {
   570		return f._func != nil
   571	}
   572	
   573	func (f funcInfo) _Func() *Func {
   574		return (*Func)(unsafe.Pointer(f._func))
   575	}
   576	
   577	func findfunc(pc uintptr) funcInfo {
   578		datap := findmoduledatap(pc)
   579		if datap == nil {
   580			return funcInfo{}
   581		}
   582		const nsub = uintptr(len(findfuncbucket{}.subbuckets))
   583	
   584		x := pc - datap.minpc
   585		b := x / pcbucketsize
   586		i := x % pcbucketsize / (pcbucketsize / nsub)
   587	
   588		ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
   589		idx := ffb.idx + uint32(ffb.subbuckets[i])
   590	
   591		// If the idx is beyond the end of the ftab, set it to the end of the table and search backward.
   592		// This situation can occur if multiple text sections are generated to handle large text sections
   593		// and the linker has inserted jump tables between them.
   594	
   595		if idx >= uint32(len(datap.ftab)) {
   596			idx = uint32(len(datap.ftab) - 1)
   597		}
   598		if pc < datap.ftab[idx].entry {
   599			// With multiple text sections, the idx might reference a function address that
   600			// is higher than the pc being searched, so search backward until the matching address is found.
   601	
   602			for datap.ftab[idx].entry > pc && idx > 0 {
   603				idx--
   604			}
   605			if idx == 0 {
   606				throw("findfunc: bad findfunctab entry idx")
   607			}
   608		} else {
   609			// linear search to find func with pc >= entry.
   610			for datap.ftab[idx+1].entry <= pc {
   611				idx++
   612			}
   613		}
   614		return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff])), datap}
   615	}
   616	
   617	type pcvalueCache struct {
   618		entries [2][8]pcvalueCacheEnt
   619	}
   620	
   621	type pcvalueCacheEnt struct {
   622		// targetpc and off together are the key of this cache entry.
   623		targetpc uintptr
   624		off      int32
   625		// val is the value of this cached pcvalue entry.
   626		val int32
   627	}
   628	
   629	// pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc.
   630	// It must be very cheap to calculate.
   631	// For now, align to sys.PtrSize and reduce mod the number of entries.
   632	// In practice, this appears to be fairly randomly and evenly distributed.
   633	func pcvalueCacheKey(targetpc uintptr) uintptr {
   634		return (targetpc / sys.PtrSize) % uintptr(len(pcvalueCache{}.entries))
   635	}
   636	
   637	func pcvalue(f funcInfo, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
   638		if off == 0 {
   639			return -1
   640		}
   641	
   642		// Check the cache. This speeds up walks of deep stacks, which
   643		// tend to have the same recursive functions over and over.
   644		//
   645		// This cache is small enough that full associativity is
   646		// cheaper than doing the hashing for a less associative
   647		// cache.
   648		if cache != nil {
   649			x := pcvalueCacheKey(targetpc)
   650			for i := range cache.entries[x] {
   651				// We check off first because we're more
   652				// likely to have multiple entries with
   653				// different offsets for the same targetpc
   654				// than the other way around, so we'll usually
   655				// fail in the first clause.
   656				ent := &cache.entries[x][i]
   657				if ent.off == off && ent.targetpc == targetpc {
   658					return ent.val
   659				}
   660			}
   661		}
   662	
   663		if !f.valid() {
   664			if strict && panicking == 0 {
   665				print("runtime: no module data for ", hex(f.entry), "\n")
   666				throw("no module data")
   667			}
   668			return -1
   669		}
   670		datap := f.datap
   671		p := datap.pclntable[off:]
   672		pc := f.entry
   673		val := int32(-1)
   674		for {
   675			var ok bool
   676			p, ok = step(p, &pc, &val, pc == f.entry)
   677			if !ok {
   678				break
   679			}
   680			if targetpc < pc {
   681				// Replace a random entry in the cache. Random
   682				// replacement prevents a performance cliff if
   683				// a recursive stack's cycle is slightly
   684				// larger than the cache.
   685				// Put the new element at the beginning,
   686				// since it is the most likely to be newly used.
   687				if cache != nil {
   688					x := pcvalueCacheKey(targetpc)
   689					e := &cache.entries[x]
   690					ci := fastrand() % uint32(len(cache.entries[x]))
   691					e[ci] = e[0]
   692					e[0] = pcvalueCacheEnt{
   693						targetpc: targetpc,
   694						off:      off,
   695						val:      val,
   696					}
   697				}
   698	
   699				return val
   700			}
   701		}
   702	
   703		// If there was a table, it should have covered all program counters.
   704		// If not, something is wrong.
   705		if panicking != 0 || !strict {
   706			return -1
   707		}
   708	
   709		print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
   710	
   711		p = datap.pclntable[off:]
   712		pc = f.entry
   713		val = -1
   714		for {
   715			var ok bool
   716			p, ok = step(p, &pc, &val, pc == f.entry)
   717			if !ok {
   718				break
   719			}
   720			print("\tvalue=", val, " until pc=", hex(pc), "\n")
   721		}
   722	
   723		throw("invalid runtime symbol table")
   724		return -1
   725	}
   726	
   727	func cfuncname(f funcInfo) *byte {
   728		if !f.valid() || f.nameoff == 0 {
   729			return nil
   730		}
   731		return &f.datap.pclntable[f.nameoff]
   732	}
   733	
   734	func funcname(f funcInfo) string {
   735		return gostringnocopy(cfuncname(f))
   736	}
   737	
   738	func funcnameFromNameoff(f funcInfo, nameoff int32) string {
   739		datap := f.datap
   740		if !f.valid() {
   741			return ""
   742		}
   743		cstr := &datap.pclntable[nameoff]
   744		return gostringnocopy(cstr)
   745	}
   746	
   747	func funcfile(f funcInfo, fileno int32) string {
   748		datap := f.datap
   749		if !f.valid() {
   750			return "?"
   751		}
   752		return gostringnocopy(&datap.pclntable[datap.filetab[fileno]])
   753	}
   754	
   755	func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) {
   756		datap := f.datap
   757		if !f.valid() {
   758			return "?", 0
   759		}
   760		fileno := int(pcvalue(f, f.pcfile, targetpc, nil, strict))
   761		line = pcvalue(f, f.pcln, targetpc, nil, strict)
   762		if fileno == -1 || line == -1 || fileno >= len(datap.filetab) {
   763			// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
   764			return "?", 0
   765		}
   766		file = gostringnocopy(&datap.pclntable[datap.filetab[fileno]])
   767		return
   768	}
   769	
   770	func funcline(f funcInfo, targetpc uintptr) (file string, line int32) {
   771		return funcline1(f, targetpc, true)
   772	}
   773	
   774	func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 {
   775		x := pcvalue(f, f.pcsp, targetpc, cache, true)
   776		if x&(sys.PtrSize-1) != 0 {
   777			print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
   778		}
   779		return x
   780	}
   781	
   782	func pcdatastart(f funcInfo, table int32) int32 {
   783		return *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
   784	}
   785	
   786	func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache) int32 {
   787		if table < 0 || table >= f.npcdata {
   788			return -1
   789		}
   790		return pcvalue(f, pcdatastart(f, table), targetpc, cache, true)
   791	}
   792	
   793	func pcdatavalue1(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
   794		if table < 0 || table >= f.npcdata {
   795			return -1
   796		}
   797		return pcvalue(f, pcdatastart(f, table), targetpc, cache, strict)
   798	}
   799	
   800	func funcdata(f funcInfo, i uint8) unsafe.Pointer {
   801		if i < 0 || i >= f.nfuncdata {
   802			return nil
   803		}
   804		p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
   805		if sys.PtrSize == 8 && uintptr(p)&4 != 0 {
   806			if uintptr(unsafe.Pointer(f._func))&4 != 0 {
   807				println("runtime: misaligned func", f._func)
   808			}
   809			p = add(p, 4)
   810		}
   811		return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize))
   812	}
   813	
   814	// step advances to the next pc, value pair in the encoded table.
   815	func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
   816		// For both uvdelta and pcdelta, the common case (~70%)
   817		// is that they are a single byte. If so, avoid calling readvarint.
   818		uvdelta := uint32(p[0])
   819		if uvdelta == 0 && !first {
   820			return nil, false
   821		}
   822		n := uint32(1)
   823		if uvdelta&0x80 != 0 {
   824			n, uvdelta = readvarint(p)
   825		}
   826		*val += int32(-(uvdelta & 1) ^ (uvdelta >> 1))
   827		p = p[n:]
   828	
   829		pcdelta := uint32(p[0])
   830		n = 1
   831		if pcdelta&0x80 != 0 {
   832			n, pcdelta = readvarint(p)
   833		}
   834		p = p[n:]
   835		*pc += uintptr(pcdelta * sys.PCQuantum)
   836		return p, true
   837	}
   838	
   839	// readvarint reads a varint from p.
   840	func readvarint(p []byte) (read uint32, val uint32) {
   841		var v, shift, n uint32
   842		for {
   843			b := p[n]
   844			n++
   845			v |= uint32(b&0x7F) << (shift & 31)
   846			if b&0x80 == 0 {
   847				break
   848			}
   849			shift += 7
   850		}
   851		return n, v
   852	}
   853	
   854	type stackmap struct {
   855		n        int32   // number of bitmaps
   856		nbit     int32   // number of bits in each bitmap
   857		bytedata [1]byte // bitmaps, each starting on a byte boundary
   858	}
   859	
   860	//go:nowritebarrier
   861	func stackmapdata(stkmap *stackmap, n int32) bitvector {
   862		// Check this invariant only when stackDebug is on at all.
   863		// The invariant is already checked by many of stackmapdata's callers,
   864		// and disabling it by default allows stackmapdata to be inlined.
   865		if stackDebug > 0 && (n < 0 || n >= stkmap.n) {
   866			throw("stackmapdata: index out of range")
   867		}
   868		return bitvector{stkmap.nbit, addb(&stkmap.bytedata[0], uintptr(n*((stkmap.nbit+7)>>3)))}
   869	}
   870	
   871	// inlinedCall is the encoding of entries in the FUNCDATA_InlTree table.
   872	type inlinedCall struct {
   873		parent   int16  // index of parent in the inltree, or < 0
   874		funcID   funcID // type of the called function
   875		_        byte
   876		file     int32 // fileno index into filetab
   877		line     int32 // line number of the call site
   878		func_    int32 // offset into pclntab for name of called function
   879		parentPc int32 // position of an instruction whose source position is the call site (offset from entry)
   880	}
   881	

View as plain text