github.com/activestate/go@v0.0.0-20170614201249-0b81c023a722/src/runtime/symtab.go (about)

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