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  	"internal/abi"
     9  	"internal/goarch"
    10  	"internal/runtime/atomic"
    11  	"internal/runtime/sys"
    12  	"unsafe"
    13  )
    14  
    15  // Frames may be used to get function/file/line information for a
    16  // slice of PC values returned by [Callers].
    17  type Frames struct {
    18  	// callers is a slice of PCs that have not yet been expanded to frames.
    19  	callers []uintptr
    20  
    21  	// nextPC is a next PC to expand ahead of processing callers.
    22  	nextPC uintptr
    23  
    24  	// frames is a slice of Frames that have yet to be returned.
    25  	frames     []Frame
    26  	frameStore [2]Frame
    27  }
    28  
    29  // Frame is the information returned by [Frames] for each call frame.
    30  type Frame struct {
    31  	// PC is the program counter for the location in this frame.
    32  	// For a frame that calls another frame, this will be the
    33  	// program counter of a call instruction. Because of inlining,
    34  	// multiple frames may have the same PC value, but different
    35  	// symbolic information.
    36  	PC uintptr
    37  
    38  	// Func is the Func value of this call frame. This may be nil
    39  	// for non-Go code or fully inlined functions.
    40  	Func *Func
    41  
    42  	// Function is the package path-qualified function name of
    43  	// this call frame. If non-empty, this string uniquely
    44  	// identifies a single function in the program.
    45  	// This may be the empty string if not known.
    46  	// If Func is not nil then Function == Func.Name().
    47  	Function string
    48  
    49  	// File and Line are the file name and line number of the
    50  	// location in this frame. For non-leaf frames, this will be
    51  	// the location of a call. These may be the empty string and
    52  	// zero, respectively, if not known. The file name uses
    53  	// forward slashes, even on Windows.
    54  	File string
    55  	Line int
    56  
    57  	// startLine is the line number of the beginning of the function in
    58  	// this frame. Specifically, it is the line number of the func keyword
    59  	// for Go functions. Note that //line directives can change the
    60  	// filename and/or line number arbitrarily within a function, meaning
    61  	// that the Line - startLine offset is not always meaningful.
    62  	//
    63  	// This may be zero if not known.
    64  	startLine int
    65  
    66  	// Entry point program counter for the function; may be zero
    67  	// if not known. If Func is not nil then Entry ==
    68  	// Func.Entry().
    69  	Entry uintptr
    70  
    71  	// The runtime's internal view of the function. This field
    72  	// is set (funcInfo.valid() returns true) only for Go functions,
    73  	// not for C functions.
    74  	funcInfo funcInfo
    75  }
    76  
    77  // CallersFrames takes a slice of PC values returned by [Callers] and
    78  // prepares to return function/file/line information.
    79  // Do not change the slice until you are done with the [Frames].
    80  func CallersFrames(callers []uintptr) *Frames {
    81  	f := &Frames{callers: callers}
    82  	f.frames = f.frameStore[:0]
    83  	return f
    84  }
    85  
    86  // Next returns a [Frame] representing the next call frame in the slice
    87  // of PC values. If it has already returned all call frames, Next
    88  // returns a zero [Frame].
    89  //
    90  // The more result indicates whether the next call to Next will return
    91  // a valid [Frame]. It does not necessarily indicate whether this call
    92  // returned one.
    93  //
    94  // See the [Frames] example for idiomatic usage.
    95  func (ci *Frames) Next() (frame Frame, more bool) {
    96  	for len(ci.frames) < 2 {
    97  		// Find the next frame.
    98  		// We need to look for 2 frames so we know what
    99  		// to return for the "more" result.
   100  		if len(ci.callers) == 0 {
   101  			break
   102  		}
   103  		var pc uintptr
   104  		if ci.nextPC != 0 {
   105  			pc, ci.nextPC = ci.nextPC, 0
   106  		} else {
   107  			pc, ci.callers = ci.callers[0], ci.callers[1:]
   108  		}
   109  		funcInfo := findfunc(pc)
   110  		if !funcInfo.valid() {
   111  			if cgoSymbolizer != nil {
   112  				// Pre-expand cgo frames. We could do this
   113  				// incrementally, too, but there's no way to
   114  				// avoid allocation in this case anyway.
   115  				ci.frames = append(ci.frames, expandCgoFrames(pc)...)
   116  			}
   117  			continue
   118  		}
   119  		f := funcInfo._Func()
   120  		entry := f.Entry()
   121  		if pc > entry {
   122  			// We store the pc of the start of the instruction following
   123  			// the instruction in question (the call or the inline mark).
   124  			// This is done for historical reasons, and to make FuncForPC
   125  			// work correctly for entries in the result of runtime.Callers.
   126  			pc--
   127  		}
   128  		// It's important that interpret pc non-strictly as cgoTraceback may
   129  		// have added bogus PCs with a valid funcInfo but invalid PCDATA.
   130  		u, uf := newInlineUnwinder(funcInfo, pc)
   131  		sf := u.srcFunc(uf)
   132  		if u.isInlined(uf) {
   133  			// Note: entry is not modified. It always refers to a real frame, not an inlined one.
   134  			// File/line from funcline1 below are already correct.
   135  			f = nil
   136  
   137  			// When CallersFrame is invoked using the PC list returned by Callers,
   138  			// the PC list includes virtual PCs corresponding to each outer frame
   139  			// around an innermost real inlined PC.
   140  			// We also want to support code passing in a PC list extracted from a
   141  			// stack trace, and there only the real PCs are printed, not the virtual ones.
   142  			// So check to see if the implied virtual PC for this PC (obtained from the
   143  			// unwinder itself) is the next PC in ci.callers. If not, insert it.
   144  			// The +1 here correspond to the pc-- above: the output of Callers
   145  			// and therefore the input to CallersFrames is return PCs from the stack;
   146  			// The pc-- backs up into the CALL instruction (not the first byte of the CALL
   147  			// instruction, but good enough to find it nonetheless).
   148  			// There are no cycles in implied virtual PCs (some number of frames were
   149  			// inlined, but that number is finite), so this unpacking cannot cause an infinite loop.
   150  			for unext := u.next(uf); unext.valid() && len(ci.callers) > 0 && ci.callers[0] != unext.pc+1; unext = u.next(unext) {
   151  				snext := u.srcFunc(unext)
   152  				if snext.funcID == abi.FuncIDWrapper && elideWrapperCalling(sf.funcID) {
   153  					// Skip, because tracebackPCs (inside runtime.Callers) would too.
   154  					continue
   155  				}
   156  				ci.nextPC = unext.pc + 1
   157  				break
   158  			}
   159  		}
   160  		ci.frames = append(ci.frames, Frame{
   161  			PC:        pc,
   162  			Func:      f,
   163  			Function:  funcNameForPrint(sf.name()),
   164  			Entry:     entry,
   165  			startLine: int(sf.startLine),
   166  			funcInfo:  funcInfo,
   167  			// Note: File,Line set below
   168  		})
   169  	}
   170  
   171  	// Pop one frame from the frame list. Keep the rest.
   172  	// Avoid allocation in the common case, which is 1 or 2 frames.
   173  	switch len(ci.frames) {
   174  	case 0: // In the rare case when there are no frames at all, we return Frame{}.
   175  		return
   176  	case 1:
   177  		frame = ci.frames[0]
   178  		ci.frames = ci.frameStore[:0]
   179  	case 2:
   180  		frame = ci.frames[0]
   181  		ci.frameStore[0] = ci.frames[1]
   182  		ci.frames = ci.frameStore[:1]
   183  	default:
   184  		frame = ci.frames[0]
   185  		ci.frames = ci.frames[1:]
   186  	}
   187  	more = len(ci.frames) > 0
   188  	if frame.funcInfo.valid() {
   189  		// Compute file/line just before we need to return it,
   190  		// as it can be expensive. This avoids computing file/line
   191  		// for the Frame we find but don't return. See issue 32093.
   192  		file, line := funcline1(frame.funcInfo, frame.PC, false)
   193  		frame.File, frame.Line = file, int(line)
   194  	}
   195  	return
   196  }
   197  
   198  // runtime_FrameStartLine returns the start line of the function in a Frame.
   199  //
   200  // runtime_FrameStartLine should be an internal detail,
   201  // but widely used packages access it using linkname.
   202  // Notable members of the hall of shame include:
   203  //   - github.com/grafana/pyroscope-go/godeltaprof
   204  //
   205  // Do not remove or change the type signature.
   206  // See go.dev/issue/67401.
   207  //
   208  //go:linkname runtime_FrameStartLine runtime/pprof.runtime_FrameStartLine
   209  func runtime_FrameStartLine(f *Frame) int {
   210  	return f.startLine
   211  }
   212  
   213  // runtime_FrameSymbolName returns the full symbol name of the function in a Frame.
   214  // For generic functions this differs from f.Function in that this doesn't replace
   215  // the shape name to "...".
   216  //
   217  // runtime_FrameSymbolName should be an internal detail,
   218  // but widely used packages access it using linkname.
   219  // Notable members of the hall of shame include:
   220  //   - github.com/grafana/pyroscope-go/godeltaprof
   221  //
   222  // Do not remove or change the type signature.
   223  // See go.dev/issue/67401.
   224  //
   225  //go:linkname runtime_FrameSymbolName runtime/pprof.runtime_FrameSymbolName
   226  func runtime_FrameSymbolName(f *Frame) string {
   227  	if !f.funcInfo.valid() {
   228  		return f.Function
   229  	}
   230  	u, uf := newInlineUnwinder(f.funcInfo, f.PC)
   231  	sf := u.srcFunc(uf)
   232  	return sf.name()
   233  }
   234  
   235  // runtime_expandFinalInlineFrame expands the final pc in stk to include all
   236  // "callers" if pc is inline.
   237  //
   238  // runtime_expandFinalInlineFrame should be an internal detail,
   239  // but widely used packages access it using linkname.
   240  // Notable members of the hall of shame include:
   241  //   - github.com/grafana/pyroscope-go/godeltaprof
   242  //   - github.com/pyroscope-io/godeltaprof
   243  //
   244  // Do not remove or change the type signature.
   245  // See go.dev/issue/67401.
   246  //
   247  //go:linkname runtime_expandFinalInlineFrame runtime/pprof.runtime_expandFinalInlineFrame
   248  func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
   249  	// TODO: It would be more efficient to report only physical PCs to pprof and
   250  	// just expand the whole stack.
   251  	if len(stk) == 0 {
   252  		return stk
   253  	}
   254  	pc := stk[len(stk)-1]
   255  	tracepc := pc - 1
   256  
   257  	f := findfunc(tracepc)
   258  	if !f.valid() {
   259  		// Not a Go function.
   260  		return stk
   261  	}
   262  
   263  	u, uf := newInlineUnwinder(f, tracepc)
   264  	if !u.isInlined(uf) {
   265  		// Nothing inline at tracepc.
   266  		return stk
   267  	}
   268  
   269  	// Treat the previous func as normal. We haven't actually checked, but
   270  	// since this pc was included in the stack, we know it shouldn't be
   271  	// elided.
   272  	calleeID := abi.FuncIDNormal
   273  
   274  	// Remove pc from stk; we'll re-add it below.
   275  	stk = stk[:len(stk)-1]
   276  
   277  	for ; uf.valid(); uf = u.next(uf) {
   278  		funcID := u.srcFunc(uf).funcID
   279  		if funcID == abi.FuncIDWrapper && elideWrapperCalling(calleeID) {
   280  			// ignore wrappers
   281  		} else {
   282  			stk = append(stk, uf.pc+1)
   283  		}
   284  		calleeID = funcID
   285  	}
   286  
   287  	return stk
   288  }
   289  
   290  // expandCgoFrames expands frame information for pc, known to be
   291  // a non-Go function, using the cgoSymbolizer hook. expandCgoFrames
   292  // returns nil if pc could not be expanded.
   293  func expandCgoFrames(pc uintptr) []Frame {
   294  	arg := cgoSymbolizerArg{pc: pc}
   295  	callCgoSymbolizer(&arg)
   296  
   297  	if arg.file == nil && arg.funcName == nil {
   298  		// No useful information from symbolizer.
   299  		return nil
   300  	}
   301  
   302  	var frames []Frame
   303  	for {
   304  		frames = append(frames, Frame{
   305  			PC:       pc,
   306  			Func:     nil,
   307  			Function: gostring(arg.funcName),
   308  			File:     gostring(arg.file),
   309  			Line:     int(arg.lineno),
   310  			Entry:    arg.entry,
   311  			// funcInfo is zero, which implies !funcInfo.valid().
   312  			// That ensures that we use the File/Line info given here.
   313  		})
   314  		if arg.more == 0 {
   315  			break
   316  		}
   317  		callCgoSymbolizer(&arg)
   318  	}
   319  
   320  	// No more frames for this PC. Tell the symbolizer we are done.
   321  	// We don't try to maintain a single cgoSymbolizerArg for the
   322  	// whole use of Frames, because there would be no good way to tell
   323  	// the symbolizer when we are done.
   324  	arg.pc = 0
   325  	callCgoSymbolizer(&arg)
   326  
   327  	return frames
   328  }
   329  
   330  // NOTE: Func does not expose the actual unexported fields, because we return *Func
   331  // values to users, and we want to keep them from being able to overwrite the data
   332  // with (say) *f = Func{}.
   333  // All code operating on a *Func must call raw() to get the *_func
   334  // or funcInfo() to get the funcInfo instead.
   335  
   336  // A Func represents a Go function in the running binary.
   337  type Func struct {
   338  	opaque struct{} // unexported field to disallow conversions
   339  }
   340  
   341  func (f *Func) raw() *_func {
   342  	return (*_func)(unsafe.Pointer(f))
   343  }
   344  
   345  func (f *Func) funcInfo() funcInfo {
   346  	return f.raw().funcInfo()
   347  }
   348  
   349  func (f *_func) funcInfo() funcInfo {
   350  	// Find the module containing fn. fn is located in the pclntable.
   351  	// The unsafe.Pointer to uintptr conversions and arithmetic
   352  	// are safe because we are working with module addresses.
   353  	ptr := uintptr(unsafe.Pointer(f))
   354  	var mod *moduledata
   355  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   356  		if len(datap.pclntable) == 0 {
   357  			continue
   358  		}
   359  		base := uintptr(unsafe.Pointer(&datap.pclntable[0]))
   360  		if base <= ptr && ptr < base+uintptr(len(datap.pclntable)) {
   361  			mod = datap
   362  			break
   363  		}
   364  	}
   365  	return funcInfo{f, mod}
   366  }
   367  
   368  // pcHeader holds data used by the pclntab lookups.
   369  type pcHeader struct {
   370  	magic          uint32  // 0xFFFFFFF1
   371  	pad1, pad2     uint8   // 0,0
   372  	minLC          uint8   // min instruction size
   373  	ptrSize        uint8   // size of a ptr in bytes
   374  	nfunc          int     // number of functions in the module
   375  	nfiles         uint    // number of entries in the file tab
   376  	textStart      uintptr // base for function entry PC offsets in this module, equal to moduledata.text
   377  	funcnameOffset uintptr // offset to the funcnametab variable from pcHeader
   378  	cuOffset       uintptr // offset to the cutab variable from pcHeader
   379  	filetabOffset  uintptr // offset to the filetab variable from pcHeader
   380  	pctabOffset    uintptr // offset to the pctab variable from pcHeader
   381  	pclnOffset     uintptr // offset to the pclntab variable from pcHeader
   382  }
   383  
   384  // moduledata records information about the layout of the executable
   385  // image. It is written by the linker. Any changes here must be
   386  // matched changes to the code in cmd/link/internal/ld/symtab.go:symtab.
   387  // moduledata is stored in statically allocated non-pointer memory;
   388  // none of the pointers here are visible to the garbage collector.
   389  type moduledata struct {
   390  	sys.NotInHeap // Only in static data
   391  
   392  	pcHeader     *pcHeader
   393  	funcnametab  []byte
   394  	cutab        []uint32
   395  	filetab      []byte
   396  	pctab        []byte
   397  	pclntable    []byte
   398  	ftab         []functab
   399  	findfunctab  uintptr
   400  	minpc, maxpc uintptr
   401  
   402  	text, etext           uintptr
   403  	noptrdata, enoptrdata uintptr
   404  	data, edata           uintptr
   405  	bss, ebss             uintptr
   406  	noptrbss, enoptrbss   uintptr
   407  	covctrs, ecovctrs     uintptr
   408  	end, gcdata, gcbss    uintptr
   409  	types, etypes         uintptr
   410  	rodata                uintptr
   411  	gofunc                uintptr // go.func.*
   412  
   413  	textsectmap []textsect
   414  	typelinks   []int32 // offsets from types
   415  	itablinks   []*itab
   416  
   417  	ptab []ptabEntry
   418  
   419  	pluginpath string
   420  	pkghashes  []modulehash
   421  
   422  	// This slice records the initializing tasks that need to be
   423  	// done to start up the program. It is built by the linker.
   424  	inittasks []*initTask
   425  
   426  	modulename   string
   427  	modulehashes []modulehash
   428  
   429  	hasmain uint8 // 1 if module contains the main function, 0 otherwise
   430  	bad     bool  // module failed to load and should be ignored
   431  
   432  	gcdatamask, gcbssmask bitvector
   433  
   434  	typemap map[typeOff]*_type // offset to *_rtype in previous module
   435  
   436  	next *moduledata
   437  }
   438  
   439  // A modulehash is used to compare the ABI of a new module or a
   440  // package in a new module with the loaded program.
   441  //
   442  // For each shared library a module links against, the linker creates an entry in the
   443  // moduledata.modulehashes slice containing the name of the module, the abi hash seen
   444  // at link time and a pointer to the runtime abi hash. These are checked in
   445  // moduledataverify1 below.
   446  //
   447  // For each loaded plugin, the pkghashes slice has a modulehash of the
   448  // newly loaded package that can be used to check the plugin's version of
   449  // a package against any previously loaded version of the package.
   450  // This is done in plugin.lastmoduleinit.
   451  type modulehash struct {
   452  	modulename   string
   453  	linktimehash string
   454  	runtimehash  *string
   455  }
   456  
   457  // pinnedTypemaps are the map[typeOff]*_type from the moduledata objects.
   458  //
   459  // These typemap objects are allocated at run time on the heap, but the
   460  // only direct reference to them is in the moduledata, created by the
   461  // linker and marked SNOPTRDATA so it is ignored by the GC.
   462  //
   463  // To make sure the map isn't collected, we keep a second reference here.
   464  var pinnedTypemaps []map[typeOff]*_type
   465  
   466  var firstmoduledata moduledata  // linker symbol
   467  var lastmoduledatap *moduledata // linker symbol
   468  
   469  var modulesSlice *[]*moduledata // see activeModules
   470  
   471  // activeModules returns a slice of active modules.
   472  //
   473  // A module is active once its gcdatamask and gcbssmask have been
   474  // assembled and it is usable by the GC.
   475  //
   476  // This is nosplit/nowritebarrier because it is called by the
   477  // cgo pointer checking code.
   478  //
   479  //go:nosplit
   480  //go:nowritebarrier
   481  func activeModules() []*moduledata {
   482  	p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
   483  	if p == nil {
   484  		return nil
   485  	}
   486  	return *p
   487  }
   488  
   489  // modulesinit creates the active modules slice out of all loaded modules.
   490  //
   491  // When a module is first loaded by the dynamic linker, an .init_array
   492  // function (written by cmd/link) is invoked to call addmoduledata,
   493  // appending to the module to the linked list that starts with
   494  // firstmoduledata.
   495  //
   496  // There are two times this can happen in the lifecycle of a Go
   497  // program. First, if compiled with -linkshared, a number of modules
   498  // built with -buildmode=shared can be loaded at program initialization.
   499  // Second, a Go program can load a module while running that was built
   500  // with -buildmode=plugin.
   501  //
   502  // After loading, this function is called which initializes the
   503  // moduledata so it is usable by the GC and creates a new activeModules
   504  // list.
   505  //
   506  // Only one goroutine may call modulesinit at a time.
   507  func modulesinit() {
   508  	modules := new([]*moduledata)
   509  	for md := &firstmoduledata; md != nil; md = md.next {
   510  		if md.bad {
   511  			continue
   512  		}
   513  		*modules = append(*modules, md)
   514  		if md.gcdatamask == (bitvector{}) {
   515  			scanDataSize := md.edata - md.data
   516  			md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), scanDataSize)
   517  			scanBSSSize := md.ebss - md.bss
   518  			md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), scanBSSSize)
   519  			gcController.addGlobals(int64(scanDataSize + scanBSSSize))
   520  		}
   521  	}
   522  
   523  	// Modules appear in the moduledata linked list in the order they are
   524  	// loaded by the dynamic loader, with one exception: the
   525  	// firstmoduledata itself the module that contains the runtime. This
   526  	// is not always the first module (when using -buildmode=shared, it
   527  	// is typically libstd.so, the second module). The order matters for
   528  	// typelinksinit, so we swap the first module with whatever module
   529  	// contains the main function.
   530  	//
   531  	// See Issue #18729.
   532  	for i, md := range *modules {
   533  		if md.hasmain != 0 {
   534  			(*modules)[0] = md
   535  			(*modules)[i] = &firstmoduledata
   536  			break
   537  		}
   538  	}
   539  
   540  	atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules))
   541  }
   542  
   543  type functab struct {
   544  	entryoff uint32 // relative to runtime.text
   545  	funcoff  uint32
   546  }
   547  
   548  // Mapping information for secondary text sections
   549  
   550  type textsect struct {
   551  	vaddr    uintptr // prelinked section vaddr
   552  	end      uintptr // vaddr + section length
   553  	baseaddr uintptr // relocated section address
   554  }
   555  
   556  // findfuncbucket is an array of these structures.
   557  // Each bucket represents 4096 bytes of the text segment.
   558  // Each subbucket represents 256 bytes of the text segment.
   559  // To find a function given a pc, locate the bucket and subbucket for
   560  // that pc. Add together the idx and subbucket value to obtain a
   561  // function index. Then scan the functab array starting at that
   562  // index to find the target function.
   563  // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead.
   564  type findfuncbucket struct {
   565  	idx        uint32
   566  	subbuckets [16]byte
   567  }
   568  
   569  func moduledataverify() {
   570  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   571  		moduledataverify1(datap)
   572  	}
   573  }
   574  
   575  const debugPcln = false
   576  
   577  func moduledataverify1(datap *moduledata) {
   578  	// Check that the pclntab's format is valid.
   579  	hdr := datap.pcHeader
   580  	if hdr.magic != 0xfffffff1 || hdr.pad1 != 0 || hdr.pad2 != 0 ||
   581  		hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize || hdr.textStart != datap.text {
   582  		println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2,
   583  			"minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pcHeader.textStart=", hex(hdr.textStart),
   584  			"text=", hex(datap.text), "pluginpath=", datap.pluginpath)
   585  		throw("invalid function symbol table")
   586  	}
   587  
   588  	// ftab is lookup table for function by program counter.
   589  	nftab := len(datap.ftab) - 1
   590  	for i := 0; i < nftab; i++ {
   591  		// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
   592  		if datap.ftab[i].entryoff > datap.ftab[i+1].entryoff {
   593  			f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap}
   594  			f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap}
   595  			f2name := "end"
   596  			if i+1 < nftab {
   597  				f2name = funcname(f2)
   598  			}
   599  			println("function symbol table not sorted by PC offset:", hex(datap.ftab[i].entryoff), funcname(f1), ">", hex(datap.ftab[i+1].entryoff), f2name, ", plugin:", datap.pluginpath)
   600  			for j := 0; j <= i; j++ {
   601  				println("\t", hex(datap.ftab[j].entryoff), funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}))
   602  			}
   603  			if GOOS == "aix" && isarchive {
   604  				println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive")
   605  			}
   606  			throw("invalid runtime symbol table")
   607  		}
   608  	}
   609  
   610  	min := datap.textAddr(datap.ftab[0].entryoff)
   611  	max := datap.textAddr(datap.ftab[nftab].entryoff)
   612  	if datap.minpc != min || datap.maxpc != max {
   613  		println("minpc=", hex(datap.minpc), "min=", hex(min), "maxpc=", hex(datap.maxpc), "max=", hex(max))
   614  		throw("minpc or maxpc invalid")
   615  	}
   616  
   617  	for _, modulehash := range datap.modulehashes {
   618  		if modulehash.linktimehash != *modulehash.runtimehash {
   619  			println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename)
   620  			throw("abi mismatch")
   621  		}
   622  	}
   623  }
   624  
   625  // textAddr returns md.text + off, with special handling for multiple text sections.
   626  // off is a (virtual) offset computed at internal linking time,
   627  // before the external linker adjusts the sections' base addresses.
   628  //
   629  // The text, or instruction stream is generated as one large buffer.
   630  // The off (offset) for a function is its offset within this buffer.
   631  // If the total text size gets too large, there can be issues on platforms like ppc64
   632  // if the target of calls are too far for the call instruction.
   633  // To resolve the large text issue, the text is split into multiple text sections
   634  // to allow the linker to generate long calls when necessary.
   635  // When this happens, the vaddr for each text section is set to its offset within the text.
   636  // Each function's offset is compared against the section vaddrs and ends to determine the containing section.
   637  // Then the section relative offset is added to the section's
   638  // relocated baseaddr to compute the function address.
   639  //
   640  // It is nosplit because it is part of the findfunc implementation.
   641  //
   642  //go:nosplit
   643  func (md *moduledata) textAddr(off32 uint32) uintptr {
   644  	off := uintptr(off32)
   645  	res := md.text + off
   646  	if len(md.textsectmap) > 1 {
   647  		for i, sect := range md.textsectmap {
   648  			// For the last section, include the end address (etext), as it is included in the functab.
   649  			if off >= sect.vaddr && off < sect.end || (i == len(md.textsectmap)-1 && off == sect.end) {
   650  				res = sect.baseaddr + off - sect.vaddr
   651  				break
   652  			}
   653  		}
   654  		if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory
   655  			println("runtime: textAddr", hex(res), "out of range", hex(md.text), "-", hex(md.etext))
   656  			throw("runtime: text offset out of range")
   657  		}
   658  	}
   659  	return res
   660  }
   661  
   662  // textOff is the opposite of textAddr. It converts a PC to a (virtual) offset
   663  // to md.text, and returns if the PC is in any Go text section.
   664  //
   665  // It is nosplit because it is part of the findfunc implementation.
   666  //
   667  //go:nosplit
   668  func (md *moduledata) textOff(pc uintptr) (uint32, bool) {
   669  	res := uint32(pc - md.text)
   670  	if len(md.textsectmap) > 1 {
   671  		for i, sect := range md.textsectmap {
   672  			if sect.baseaddr > pc {
   673  				// pc is not in any section.
   674  				return 0, false
   675  			}
   676  			end := sect.baseaddr + (sect.end - sect.vaddr)
   677  			// For the last section, include the end address (etext), as it is included in the functab.
   678  			if i == len(md.textsectmap)-1 {
   679  				end++
   680  			}
   681  			if pc < end {
   682  				res = uint32(pc - sect.baseaddr + sect.vaddr)
   683  				break
   684  			}
   685  		}
   686  	}
   687  	return res, true
   688  }
   689  
   690  // funcName returns the string at nameOff in the function name table.
   691  func (md *moduledata) funcName(nameOff int32) string {
   692  	if nameOff == 0 {
   693  		return ""
   694  	}
   695  	return gostringnocopy(&md.funcnametab[nameOff])
   696  }
   697  
   698  // FuncForPC returns a *[Func] describing the function that contains the
   699  // given program counter address, or else nil.
   700  //
   701  // If pc represents multiple functions because of inlining, it returns
   702  // the *Func describing the innermost function, but with an entry of
   703  // the outermost function.
   704  //
   705  // For completely unclear reasons, even though they can import runtime,
   706  // some widely used packages access this using linkname.
   707  // Notable members of the hall of shame include:
   708  //   - gitee.com/quant1x/gox
   709  //
   710  // Do not remove or change the type signature.
   711  // See go.dev/issue/67401.
   712  //
   713  //go:linkname FuncForPC
   714  func FuncForPC(pc uintptr) *Func {
   715  	f := findfunc(pc)
   716  	if !f.valid() {
   717  		return nil
   718  	}
   719  	// This must interpret PC non-strictly so bad PCs (those between functions) don't crash the runtime.
   720  	// We just report the preceding function in that situation. See issue 29735.
   721  	// TODO: Perhaps we should report no function at all in that case.
   722  	// The runtime currently doesn't have function end info, alas.
   723  	u, uf := newInlineUnwinder(f, pc)
   724  	if !u.isInlined(uf) {
   725  		return f._Func()
   726  	}
   727  	sf := u.srcFunc(uf)
   728  	file, line := u.fileLine(uf)
   729  	fi := &funcinl{
   730  		ones:      ^uint32(0),
   731  		entry:     f.entry(), // entry of the real (the outermost) function.
   732  		name:      sf.name(),
   733  		file:      file,
   734  		line:      int32(line),
   735  		startLine: sf.startLine,
   736  	}
   737  	return (*Func)(unsafe.Pointer(fi))
   738  }
   739  
   740  // Name returns the name of the function.
   741  func (f *Func) Name() string {
   742  	if f == nil {
   743  		return ""
   744  	}
   745  	fn := f.raw()
   746  	if fn.isInlined() { // inlined version
   747  		fi := (*funcinl)(unsafe.Pointer(fn))
   748  		return funcNameForPrint(fi.name)
   749  	}
   750  	return funcNameForPrint(funcname(f.funcInfo()))
   751  }
   752  
   753  // Entry returns the entry address of the function.
   754  func (f *Func) Entry() uintptr {
   755  	fn := f.raw()
   756  	if fn.isInlined() { // inlined version
   757  		fi := (*funcinl)(unsafe.Pointer(fn))
   758  		return fi.entry
   759  	}
   760  	return fn.funcInfo().entry()
   761  }
   762  
   763  // FileLine returns the file name and line number of the
   764  // source code corresponding to the program counter pc.
   765  // The result will not be accurate if pc is not a program
   766  // counter within f.
   767  func (f *Func) FileLine(pc uintptr) (file string, line int) {
   768  	fn := f.raw()
   769  	if fn.isInlined() { // inlined version
   770  		fi := (*funcinl)(unsafe.Pointer(fn))
   771  		return fi.file, int(fi.line)
   772  	}
   773  	// Pass strict=false here, because anyone can call this function,
   774  	// and they might just be wrong about targetpc belonging to f.
   775  	file, line32 := funcline1(f.funcInfo(), pc, false)
   776  	return file, int(line32)
   777  }
   778  
   779  // startLine returns the starting line number of the function. i.e., the line
   780  // number of the func keyword.
   781  func (f *Func) startLine() int32 {
   782  	fn := f.raw()
   783  	if fn.isInlined() { // inlined version
   784  		fi := (*funcinl)(unsafe.Pointer(fn))
   785  		return fi.startLine
   786  	}
   787  	return fn.funcInfo().startLine
   788  }
   789  
   790  // findmoduledatap looks up the moduledata for a PC.
   791  //
   792  // It is nosplit because it's part of the isgoexception
   793  // implementation.
   794  //
   795  //go:nosplit
   796  func findmoduledatap(pc uintptr) *moduledata {
   797  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   798  		if datap.minpc <= pc && pc < datap.maxpc {
   799  			return datap
   800  		}
   801  	}
   802  	return nil
   803  }
   804  
   805  type funcInfo struct {
   806  	*_func
   807  	datap *moduledata
   808  }
   809  
   810  func (f funcInfo) valid() bool {
   811  	return f._func != nil
   812  }
   813  
   814  func (f funcInfo) _Func() *Func {
   815  	return (*Func)(unsafe.Pointer(f._func))
   816  }
   817  
   818  // isInlined reports whether f should be re-interpreted as a *funcinl.
   819  func (f *_func) isInlined() bool {
   820  	return f.entryOff == ^uint32(0) // see comment for funcinl.ones
   821  }
   822  
   823  // entry returns the entry PC for f.
   824  //
   825  // entry should be an internal detail,
   826  // but widely used packages access it using linkname.
   827  // Notable members of the hall of shame include:
   828  //   - github.com/phuslu/log
   829  //
   830  // Do not remove or change the type signature.
   831  // See go.dev/issue/67401.
   832  func (f funcInfo) entry() uintptr {
   833  	return f.datap.textAddr(f.entryOff)
   834  }
   835  
   836  //go:linkname badFuncInfoEntry runtime.funcInfo.entry
   837  func badFuncInfoEntry(funcInfo) uintptr
   838  
   839  // findfunc looks up function metadata for a PC.
   840  //
   841  // It is nosplit because it's part of the isgoexception
   842  // implementation.
   843  //
   844  // findfunc should be an internal detail,
   845  // but widely used packages access it using linkname.
   846  // Notable members of the hall of shame include:
   847  //   - github.com/phuslu/log
   848  //
   849  // Do not remove or change the type signature.
   850  // See go.dev/issue/67401.
   851  //
   852  //go:nosplit
   853  //go:linkname findfunc
   854  func findfunc(pc uintptr) funcInfo {
   855  	datap := findmoduledatap(pc)
   856  	if datap == nil {
   857  		return funcInfo{}
   858  	}
   859  	const nsub = uintptr(len(findfuncbucket{}.subbuckets))
   860  
   861  	pcOff, ok := datap.textOff(pc)
   862  	if !ok {
   863  		return funcInfo{}
   864  	}
   865  
   866  	x := uintptr(pcOff) + datap.text - datap.minpc // TODO: are datap.text and datap.minpc always equal?
   867  	b := x / abi.FuncTabBucketSize
   868  	i := x % abi.FuncTabBucketSize / (abi.FuncTabBucketSize / nsub)
   869  
   870  	ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
   871  	idx := ffb.idx + uint32(ffb.subbuckets[i])
   872  
   873  	// Find the ftab entry.
   874  	for datap.ftab[idx+1].entryoff <= pcOff {
   875  		idx++
   876  	}
   877  
   878  	funcoff := datap.ftab[idx].funcoff
   879  	return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[funcoff])), datap}
   880  }
   881  
   882  // A srcFunc represents a logical function in the source code. This may
   883  // correspond to an actual symbol in the binary text, or it may correspond to a
   884  // source function that has been inlined.
   885  type srcFunc struct {
   886  	datap     *moduledata
   887  	nameOff   int32
   888  	startLine int32
   889  	funcID    abi.FuncID
   890  }
   891  
   892  func (f funcInfo) srcFunc() srcFunc {
   893  	if !f.valid() {
   894  		return srcFunc{}
   895  	}
   896  	return srcFunc{f.datap, f.nameOff, f.startLine, f.funcID}
   897  }
   898  
   899  // name should be an internal detail,
   900  // but widely used packages access it using linkname.
   901  // Notable members of the hall of shame include:
   902  //   - github.com/phuslu/log
   903  //
   904  // Do not remove or change the type signature.
   905  // See go.dev/issue/67401.
   906  func (s srcFunc) name() string {
   907  	if s.datap == nil {
   908  		return ""
   909  	}
   910  	return s.datap.funcName(s.nameOff)
   911  }
   912  
   913  //go:linkname badSrcFuncName runtime.srcFunc.name
   914  func badSrcFuncName(srcFunc) string
   915  
   916  type pcvalueCache struct {
   917  	entries [2][8]pcvalueCacheEnt
   918  	inUse   int
   919  }
   920  
   921  type pcvalueCacheEnt struct {
   922  	// targetpc and off together are the key of this cache entry.
   923  	targetpc uintptr
   924  	off      uint32
   925  
   926  	val   int32   // The value of this entry.
   927  	valPC uintptr // The PC at which val starts
   928  }
   929  
   930  // pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc.
   931  // It must be very cheap to calculate.
   932  // For now, align to goarch.PtrSize and reduce mod the number of entries.
   933  // In practice, this appears to be fairly randomly and evenly distributed.
   934  func pcvalueCacheKey(targetpc uintptr) uintptr {
   935  	return (targetpc / goarch.PtrSize) % uintptr(len(pcvalueCache{}.entries))
   936  }
   937  
   938  // Returns the PCData value, and the PC where this value starts.
   939  func pcvalue(f funcInfo, off uint32, targetpc uintptr, strict bool) (int32, uintptr) {
   940  	// If true, when we get a cache hit, still look up the data and make sure it
   941  	// matches the cached contents.
   942  	const debugCheckCache = false
   943  
   944  	if off == 0 {
   945  		return -1, 0
   946  	}
   947  
   948  	// Check the cache. This speeds up walks of deep stacks, which
   949  	// tend to have the same recursive functions over and over,
   950  	// or repetitive stacks between goroutines.
   951  	var checkVal int32
   952  	var checkPC uintptr
   953  	ck := pcvalueCacheKey(targetpc)
   954  	{
   955  		mp := acquirem()
   956  		cache := &mp.pcvalueCache
   957  		// The cache can be used by the signal handler on this M. Avoid
   958  		// re-entrant use of the cache. The signal handler can also write inUse,
   959  		// but will always restore its value, so we can use a regular increment
   960  		// even if we get signaled in the middle of it.
   961  		cache.inUse++
   962  		if cache.inUse == 1 {
   963  			for i := range cache.entries[ck] {
   964  				// We check off first because we're more
   965  				// likely to have multiple entries with
   966  				// different offsets for the same targetpc
   967  				// than the other way around, so we'll usually
   968  				// fail in the first clause.
   969  				ent := &cache.entries[ck][i]
   970  				if ent.off == off && ent.targetpc == targetpc {
   971  					val, pc := ent.val, ent.valPC
   972  					if debugCheckCache {
   973  						checkVal, checkPC = ent.val, ent.valPC
   974  						break
   975  					} else {
   976  						cache.inUse--
   977  						releasem(mp)
   978  						return val, pc
   979  					}
   980  				}
   981  			}
   982  		} else if debugCheckCache && (cache.inUse < 1 || cache.inUse > 2) {
   983  			// Catch accounting errors or deeply reentrant use. In principle
   984  			// "inUse" should never exceed 2.
   985  			throw("cache.inUse out of range")
   986  		}
   987  		cache.inUse--
   988  		releasem(mp)
   989  	}
   990  
   991  	if !f.valid() {
   992  		if strict && panicking.Load() == 0 {
   993  			println("runtime: no module data for", hex(f.entry()))
   994  			throw("no module data")
   995  		}
   996  		return -1, 0
   997  	}
   998  	datap := f.datap
   999  	p := datap.pctab[off:]
  1000  	pc := f.entry()
  1001  	prevpc := pc
  1002  	val := int32(-1)
  1003  	for {
  1004  		var ok bool
  1005  		p, ok = step(p, &pc, &val, pc == f.entry())
  1006  		if !ok {
  1007  			break
  1008  		}
  1009  		if targetpc < pc {
  1010  			// Replace a random entry in the cache. Random
  1011  			// replacement prevents a performance cliff if
  1012  			// a recursive stack's cycle is slightly
  1013  			// larger than the cache.
  1014  			// Put the new element at the beginning,
  1015  			// since it is the most likely to be newly used.
  1016  			if debugCheckCache && checkPC != 0 {
  1017  				if checkVal != val || checkPC != prevpc {
  1018  					print("runtime: table value ", val, "@", prevpc, " != cache value ", checkVal, "@", checkPC, " at PC ", targetpc, " off ", off, "\n")
  1019  					throw("bad pcvalue cache")
  1020  				}
  1021  			} else {
  1022  				mp := acquirem()
  1023  				cache := &mp.pcvalueCache
  1024  				cache.inUse++
  1025  				if cache.inUse == 1 {
  1026  					e := &cache.entries[ck]
  1027  					ci := cheaprandn(uint32(len(cache.entries[ck])))
  1028  					e[ci] = e[0]
  1029  					e[0] = pcvalueCacheEnt{
  1030  						targetpc: targetpc,
  1031  						off:      off,
  1032  						val:      val,
  1033  						valPC:    prevpc,
  1034  					}
  1035  				}
  1036  				cache.inUse--
  1037  				releasem(mp)
  1038  			}
  1039  
  1040  			return val, prevpc
  1041  		}
  1042  		prevpc = pc
  1043  	}
  1044  
  1045  	// If there was a table, it should have covered all program counters.
  1046  	// If not, something is wrong.
  1047  	if panicking.Load() != 0 || !strict {
  1048  		return -1, 0
  1049  	}
  1050  
  1051  	print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
  1052  
  1053  	p = datap.pctab[off:]
  1054  	pc = f.entry()
  1055  	val = -1
  1056  	for {
  1057  		var ok bool
  1058  		p, ok = step(p, &pc, &val, pc == f.entry())
  1059  		if !ok {
  1060  			break
  1061  		}
  1062  		print("\tvalue=", val, " until pc=", hex(pc), "\n")
  1063  	}
  1064  
  1065  	throw("invalid runtime symbol table")
  1066  	return -1, 0
  1067  }
  1068  
  1069  func funcname(f funcInfo) string {
  1070  	if !f.valid() {
  1071  		return ""
  1072  	}
  1073  	return f.datap.funcName(f.nameOff)
  1074  }
  1075  
  1076  func funcpkgpath(f funcInfo) string {
  1077  	name := funcNameForPrint(funcname(f))
  1078  	i := len(name) - 1
  1079  	for ; i > 0; i-- {
  1080  		if name[i] == '/' {
  1081  			break
  1082  		}
  1083  	}
  1084  	for ; i < len(name); i++ {
  1085  		if name[i] == '.' {
  1086  			break
  1087  		}
  1088  	}
  1089  	return name[:i]
  1090  }
  1091  
  1092  func funcfile(f funcInfo, fileno int32) string {
  1093  	datap := f.datap
  1094  	if !f.valid() {
  1095  		return "?"
  1096  	}
  1097  	// Make sure the cu index and file offset are valid
  1098  	if fileoff := datap.cutab[f.cuOffset+uint32(fileno)]; fileoff != ^uint32(0) {
  1099  		return gostringnocopy(&datap.filetab[fileoff])
  1100  	}
  1101  	// pcln section is corrupt.
  1102  	return "?"
  1103  }
  1104  
  1105  // funcline1 should be an internal detail,
  1106  // but widely used packages access it using linkname.
  1107  // Notable members of the hall of shame include:
  1108  //   - github.com/phuslu/log
  1109  //
  1110  // Do not remove or change the type signature.
  1111  // See go.dev/issue/67401.
  1112  //
  1113  //go:linkname funcline1
  1114  func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) {
  1115  	datap := f.datap
  1116  	if !f.valid() {
  1117  		return "?", 0
  1118  	}
  1119  	fileno, _ := pcvalue(f, f.pcfile, targetpc, strict)
  1120  	line, _ = pcvalue(f, f.pcln, targetpc, strict)
  1121  	if fileno == -1 || line == -1 || int(fileno) >= len(datap.filetab) {
  1122  		// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
  1123  		return "?", 0
  1124  	}
  1125  	file = funcfile(f, fileno)
  1126  	return
  1127  }
  1128  
  1129  func funcline(f funcInfo, targetpc uintptr) (file string, line int32) {
  1130  	return funcline1(f, targetpc, true)
  1131  }
  1132  
  1133  func funcspdelta(f funcInfo, targetpc uintptr) int32 {
  1134  	x, _ := pcvalue(f, f.pcsp, targetpc, true)
  1135  	if debugPcln && x&(goarch.PtrSize-1) != 0 {
  1136  		print("invalid spdelta ", funcname(f), " ", hex(f.entry()), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
  1137  		throw("bad spdelta")
  1138  	}
  1139  	return x
  1140  }
  1141  
  1142  // funcMaxSPDelta returns the maximum spdelta at any point in f.
  1143  func funcMaxSPDelta(f funcInfo) int32 {
  1144  	datap := f.datap
  1145  	p := datap.pctab[f.pcsp:]
  1146  	pc := f.entry()
  1147  	val := int32(-1)
  1148  	most := int32(0)
  1149  	for {
  1150  		var ok bool
  1151  		p, ok = step(p, &pc, &val, pc == f.entry())
  1152  		if !ok {
  1153  			return most
  1154  		}
  1155  		most = max(most, val)
  1156  	}
  1157  }
  1158  
  1159  func pcdatastart(f funcInfo, table uint32) uint32 {
  1160  	return *(*uint32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
  1161  }
  1162  
  1163  func pcdatavalue(f funcInfo, table uint32, targetpc uintptr) int32 {
  1164  	if table >= f.npcdata {
  1165  		return -1
  1166  	}
  1167  	r, _ := pcvalue(f, pcdatastart(f, table), targetpc, true)
  1168  	return r
  1169  }
  1170  
  1171  func pcdatavalue1(f funcInfo, table uint32, targetpc uintptr, strict bool) int32 {
  1172  	if table >= f.npcdata {
  1173  		return -1
  1174  	}
  1175  	r, _ := pcvalue(f, pcdatastart(f, table), targetpc, strict)
  1176  	return r
  1177  }
  1178  
  1179  // Like pcdatavalue, but also return the start PC of this PCData value.
  1180  func pcdatavalue2(f funcInfo, table uint32, targetpc uintptr) (int32, uintptr) {
  1181  	if table >= f.npcdata {
  1182  		return -1, 0
  1183  	}
  1184  	return pcvalue(f, pcdatastart(f, table), targetpc, true)
  1185  }
  1186  
  1187  // funcdata returns a pointer to the ith funcdata for f.
  1188  // funcdata should be kept in sync with cmd/link:writeFuncs.
  1189  func funcdata(f funcInfo, i uint8) unsafe.Pointer {
  1190  	if i < 0 || i >= f.nfuncdata {
  1191  		return nil
  1192  	}
  1193  	base := f.datap.gofunc // load gofunc address early so that we calculate during cache misses
  1194  	p := uintptr(unsafe.Pointer(&f.nfuncdata)) + unsafe.Sizeof(f.nfuncdata) + uintptr(f.npcdata)*4 + uintptr(i)*4
  1195  	off := *(*uint32)(unsafe.Pointer(p))
  1196  	// Return off == ^uint32(0) ? 0 : f.datap.gofunc + uintptr(off), but without branches.
  1197  	// The compiler calculates mask on most architectures using conditional assignment.
  1198  	var mask uintptr
  1199  	if off == ^uint32(0) {
  1200  		mask = 1
  1201  	}
  1202  	mask--
  1203  	raw := base + uintptr(off)
  1204  	return unsafe.Pointer(raw & mask)
  1205  }
  1206  
  1207  // step advances to the next pc, value pair in the encoded table.
  1208  func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
  1209  	// For both uvdelta and pcdelta, the common case (~70%)
  1210  	// is that they are a single byte. If so, avoid calling readvarint.
  1211  	uvdelta := uint32(p[0])
  1212  	if uvdelta == 0 && !first {
  1213  		return nil, false
  1214  	}
  1215  	n := uint32(1)
  1216  	if uvdelta&0x80 != 0 {
  1217  		n, uvdelta = readvarint(p)
  1218  	}
  1219  	*val += int32(-(uvdelta & 1) ^ (uvdelta >> 1))
  1220  	p = p[n:]
  1221  
  1222  	pcdelta := uint32(p[0])
  1223  	n = 1
  1224  	if pcdelta&0x80 != 0 {
  1225  		n, pcdelta = readvarint(p)
  1226  	}
  1227  	p = p[n:]
  1228  	*pc += uintptr(pcdelta * sys.PCQuantum)
  1229  	return p, true
  1230  }
  1231  
  1232  // readvarint reads a varint from p.
  1233  func readvarint(p []byte) (read uint32, val uint32) {
  1234  	var v, shift, n uint32
  1235  	for {
  1236  		b := p[n]
  1237  		n++
  1238  		v |= uint32(b&0x7F) << (shift & 31)
  1239  		if b&0x80 == 0 {
  1240  			break
  1241  		}
  1242  		shift += 7
  1243  	}
  1244  	return n, v
  1245  }
  1246  
  1247  type stackmap struct {
  1248  	n        int32   // number of bitmaps
  1249  	nbit     int32   // number of bits in each bitmap
  1250  	bytedata [1]byte // bitmaps, each starting on a byte boundary
  1251  }
  1252  
  1253  //go:nowritebarrier
  1254  func stackmapdata(stkmap *stackmap, n int32) bitvector {
  1255  	// Check this invariant only when stackDebug is on at all.
  1256  	// The invariant is already checked by many of stackmapdata's callers,
  1257  	// and disabling it by default allows stackmapdata to be inlined.
  1258  	if stackDebug > 0 && (n < 0 || n >= stkmap.n) {
  1259  		throw("stackmapdata: index out of range")
  1260  	}
  1261  	return bitvector{stkmap.nbit, addb(&stkmap.bytedata[0], uintptr(n*((stkmap.nbit+7)>>3)))}
  1262  }
  1263  

View as plain text