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

View as plain text