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, etypes         uintptr
   423  	rodata                uintptr
   424  	gofunc                uintptr // go.func.*
   425  	epclntab              uintptr
   426  
   427  	textsectmap []textsect
   428  	typelinks   []int32 // offsets from types
   429  	itablinks   []*itab
   430  
   431  	ptab []ptabEntry
   432  
   433  	pluginpath string
   434  	pkghashes  []modulehash
   435  
   436  	// This slice records the initializing tasks that need to be
   437  	// done to start up the program. It is built by the linker.
   438  	inittasks []*initTask
   439  
   440  	modulename   string
   441  	modulehashes []modulehash
   442  
   443  	hasmain uint8 // 1 if module contains the main function, 0 otherwise
   444  	bad     bool  // module failed to load and should be ignored
   445  
   446  	gcdatamask, gcbssmask bitvector
   447  
   448  	typemap map[typeOff]*_type // offset to *_rtype in previous module
   449  
   450  	next *moduledata
   451  }
   452  
   453  // A modulehash is used to compare the ABI of a new module or a
   454  // package in a new module with the loaded program.
   455  //
   456  // For each shared library a module links against, the linker creates an entry in the
   457  // moduledata.modulehashes slice containing the name of the module, the abi hash seen
   458  // at link time and a pointer to the runtime abi hash. These are checked in
   459  // moduledataverify1 below.
   460  //
   461  // For each loaded plugin, the pkghashes slice has a modulehash of the
   462  // newly loaded package that can be used to check the plugin's version of
   463  // a package against any previously loaded version of the package.
   464  // This is done in plugin.lastmoduleinit.
   465  type modulehash struct {
   466  	modulename   string
   467  	linktimehash string
   468  	runtimehash  *string
   469  }
   470  
   471  // pinnedTypemaps are the map[typeOff]*_type from the moduledata objects.
   472  //
   473  // These typemap objects are allocated at run time on the heap, but the
   474  // only direct reference to them is in the moduledata, created by the
   475  // linker and marked SNOPTRDATA so it is ignored by the GC.
   476  //
   477  // To make sure the map isn't collected, we keep a second reference here.
   478  var pinnedTypemaps []map[typeOff]*_type
   479  
   480  // aixStaticDataBase (used only on AIX) holds the unrelocated address
   481  // of the data section, set by the linker.
   482  //
   483  // On AIX, an R_ADDR relocation from an RODATA symbol to a DATA symbol
   484  // does not work, as the dynamic loader can change the address of the
   485  // data section, and it is not possible to apply a dynamic relocation
   486  // to RODATA. In order to get the correct address, we need to apply
   487  // the delta between unrelocated and relocated data section addresses.
   488  // aixStaticDataBase is the unrelocated address, and moduledata.data is
   489  // the relocated one.
   490  var aixStaticDataBase uintptr // linker symbol
   491  
   492  var firstmoduledata moduledata // linker symbol
   493  
   494  // lastmoduledatap should be an internal detail,
   495  // but widely used packages access it using linkname.
   496  // Notable members of the hall of shame include:
   497  //   - github.com/bytedance/sonic
   498  //
   499  // Do not remove or change the type signature.
   500  // See go.dev/issues/67401.
   501  // See go.dev/issues/71672.
   502  //
   503  //go:linkname lastmoduledatap
   504  var lastmoduledatap *moduledata // linker symbol
   505  
   506  var modulesSlice *[]*moduledata // see activeModules
   507  
   508  // activeModules returns a slice of active modules.
   509  //
   510  // A module is active once its gcdatamask and gcbssmask have been
   511  // assembled and it is usable by the GC.
   512  //
   513  // This is nosplit/nowritebarrier because it is called by the
   514  // cgo pointer checking code.
   515  //
   516  //go:nosplit
   517  //go:nowritebarrier
   518  func activeModules() []*moduledata {
   519  	p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
   520  	if p == nil {
   521  		return nil
   522  	}
   523  	return *p
   524  }
   525  
   526  // modulesinit creates the active modules slice out of all loaded modules.
   527  //
   528  // When a module is first loaded by the dynamic linker, an .init_array
   529  // function (written by cmd/link) is invoked to call addmoduledata,
   530  // appending to the module to the linked list that starts with
   531  // firstmoduledata.
   532  //
   533  // There are two times this can happen in the lifecycle of a Go
   534  // program. First, if compiled with -linkshared, a number of modules
   535  // built with -buildmode=shared can be loaded at program initialization.
   536  // Second, a Go program can load a module while running that was built
   537  // with -buildmode=plugin.
   538  //
   539  // After loading, this function is called which initializes the
   540  // moduledata so it is usable by the GC and creates a new activeModules
   541  // list.
   542  //
   543  // Only one goroutine may call modulesinit at a time.
   544  func modulesinit() {
   545  	modules := new([]*moduledata)
   546  	for md := &firstmoduledata; md != nil; md = md.next {
   547  		if md.bad {
   548  			continue
   549  		}
   550  		*modules = append(*modules, md)
   551  		if md.gcdatamask == (bitvector{}) {
   552  			scanDataSize := md.edata - md.data
   553  			md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), scanDataSize)
   554  			scanBSSSize := md.ebss - md.bss
   555  			md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), scanBSSSize)
   556  			gcController.addGlobals(int64(scanDataSize + scanBSSSize))
   557  		}
   558  	}
   559  
   560  	// Modules appear in the moduledata linked list in the order they are
   561  	// loaded by the dynamic loader, with one exception: the
   562  	// firstmoduledata itself the module that contains the runtime. This
   563  	// is not always the first module (when using -buildmode=shared, it
   564  	// is typically libstd.so, the second module). The order matters for
   565  	// typelinksinit, so we swap the first module with whatever module
   566  	// contains the main function.
   567  	//
   568  	// See Issue #18729.
   569  	for i, md := range *modules {
   570  		if md.hasmain != 0 {
   571  			(*modules)[0] = md
   572  			(*modules)[i] = &firstmoduledata
   573  			break
   574  		}
   575  	}
   576  
   577  	atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules))
   578  }
   579  
   580  type functab struct {
   581  	entryoff uint32 // relative to runtime.text
   582  	funcoff  uint32
   583  }
   584  
   585  // Mapping information for secondary text sections
   586  
   587  type textsect struct {
   588  	vaddr    uintptr // prelinked section vaddr
   589  	end      uintptr // vaddr + section length
   590  	baseaddr uintptr // relocated section address
   591  }
   592  
   593  // findfuncbucket is an array of these structures.
   594  // Each bucket represents 4096 bytes of the text segment.
   595  // Each subbucket represents 256 bytes of the text segment.
   596  // To find a function given a pc, locate the bucket and subbucket for
   597  // that pc. Add together the idx and subbucket value to obtain a
   598  // function index. Then scan the functab array starting at that
   599  // index to find the target function.
   600  // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead.
   601  type findfuncbucket struct {
   602  	idx        uint32
   603  	subbuckets [16]byte
   604  }
   605  
   606  func moduledataverify() {
   607  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   608  		moduledataverify1(datap)
   609  	}
   610  }
   611  
   612  const debugPcln = false
   613  
   614  // moduledataverify1 should be an internal detail,
   615  // but widely used packages access it using linkname.
   616  // Notable members of the hall of shame include:
   617  //   - github.com/bytedance/sonic
   618  //
   619  // Do not remove or change the type signature.
   620  // See go.dev/issues/67401.
   621  // See go.dev/issues/71672.
   622  //
   623  //go:linkname moduledataverify1
   624  func moduledataverify1(datap *moduledata) {
   625  	// Check that the pclntab's format is valid.
   626  	hdr := datap.pcHeader
   627  	if hdr.magic != abi.CurrentPCLnTabMagic || hdr.pad1 != 0 || hdr.pad2 != 0 ||
   628  		hdr.minLC != sys.PCQuantum || hdr.ptrSize != goarch.PtrSize {
   629  		println("runtime: pcHeader: magic=", hex(hdr.magic), "pad1=", hdr.pad1, "pad2=", hdr.pad2,
   630  			"minLC=", hdr.minLC, "ptrSize=", hdr.ptrSize, "pluginpath=", datap.pluginpath)
   631  		throw("invalid function symbol table")
   632  	}
   633  
   634  	// ftab is lookup table for function by program counter.
   635  	nftab := len(datap.ftab) - 1
   636  	for i := 0; i < nftab; i++ {
   637  		// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
   638  		if datap.ftab[i].entryoff > datap.ftab[i+1].entryoff {
   639  			f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap}
   640  			f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap}
   641  			f2name := "end"
   642  			if i+1 < nftab {
   643  				f2name = funcname(f2)
   644  			}
   645  			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)
   646  			for j := 0; j <= i; j++ {
   647  				println("\t", hex(datap.ftab[j].entryoff), funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}))
   648  			}
   649  			if GOOS == "aix" && isarchive {
   650  				println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive")
   651  			}
   652  			throw("invalid runtime symbol table")
   653  		}
   654  	}
   655  
   656  	min := datap.textAddr(datap.ftab[0].entryoff)
   657  	max := datap.textAddr(datap.ftab[nftab].entryoff)
   658  	minpc := datap.minpc
   659  	maxpc := datap.maxpc
   660  	if GOARCH == "wasm" {
   661  		// On Wasm, the func table contains the function index, whereas
   662  		// the "PC" is function index << 16 + block index.
   663  		maxpc = alignUp(maxpc, 1<<16) // round up for end PC
   664  	}
   665  	if minpc != min || maxpc != max {
   666  		println("minpc=", hex(minpc), "min=", hex(min), "maxpc=", hex(maxpc), "max=", hex(max))
   667  		throw("minpc or maxpc invalid")
   668  	}
   669  
   670  	for _, modulehash := range datap.modulehashes {
   671  		if modulehash.linktimehash != *modulehash.runtimehash {
   672  			println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename)
   673  			throw("abi mismatch")
   674  		}
   675  	}
   676  }
   677  
   678  // textAddr returns md.text + off, with special handling for multiple text sections.
   679  // off is a (virtual) offset computed at internal linking time,
   680  // before the external linker adjusts the sections' base addresses.
   681  //
   682  // The text, or instruction stream is generated as one large buffer.
   683  // The off (offset) for a function is its offset within this buffer.
   684  // If the total text size gets too large, there can be issues on platforms like ppc64
   685  // if the target of calls are too far for the call instruction.
   686  // To resolve the large text issue, the text is split into multiple text sections
   687  // to allow the linker to generate long calls when necessary.
   688  // When this happens, the vaddr for each text section is set to its offset within the text.
   689  // Each function's offset is compared against the section vaddrs and ends to determine the containing section.
   690  // Then the section relative offset is added to the section's
   691  // relocated baseaddr to compute the function address.
   692  //
   693  // It is nosplit because it is part of the findfunc implementation.
   694  //
   695  //go:nosplit
   696  func (md *moduledata) textAddr(off32 uint32) uintptr {
   697  	off := uintptr(off32)
   698  	res := md.text + off
   699  	if len(md.textsectmap) > 1 {
   700  		for i, sect := range md.textsectmap {
   701  			// For the last section, include the end address (etext), as it is included in the functab.
   702  			if off >= sect.vaddr && off < sect.end || (i == len(md.textsectmap)-1 && off == sect.end) {
   703  				res = sect.baseaddr + off - sect.vaddr
   704  				break
   705  			}
   706  		}
   707  		if res > md.etext && GOARCH != "wasm" { // on wasm, functions do not live in the same address space as the linear memory
   708  			println("runtime: textAddr", hex(res), "out of range", hex(md.text), "-", hex(md.etext))
   709  			throw("runtime: text offset out of range")
   710  		}
   711  	}
   712  	if GOARCH == "wasm" {
   713  		// On Wasm, a text offset (e.g. in the method table) is function index, whereas
   714  		// the "PC" is function index << 16 + block index.
   715  		res <<= 16
   716  	}
   717  	return res
   718  }
   719  
   720  // textOff is the opposite of textAddr. It converts a PC to a (virtual) offset
   721  // to md.text, and returns if the PC is in any Go text section.
   722  //
   723  // It is nosplit because it is part of the findfunc implementation.
   724  //
   725  //go:nosplit
   726  func (md *moduledata) textOff(pc uintptr) (uint32, bool) {
   727  	off := pc - md.text
   728  	if GOARCH == "wasm" {
   729  		// On Wasm, the func table contains the function index, whereas
   730  		// the "PC" is function index << 16 + block index.
   731  		off >>= 16
   732  	}
   733  	res := uint32(off)
   734  	if len(md.textsectmap) > 1 {
   735  		if GOARCH == "wasm" {
   736  			fatal("unexpected multiple text sections on Wasm")
   737  		}
   738  		for i, sect := range md.textsectmap {
   739  			if sect.baseaddr > pc {
   740  				// pc is not in any section.
   741  				return 0, false
   742  			}
   743  			end := sect.baseaddr + (sect.end - sect.vaddr)
   744  			// For the last section, include the end address (etext), as it is included in the functab.
   745  			if i == len(md.textsectmap)-1 {
   746  				end++
   747  			}
   748  			if pc < end {
   749  				res = uint32(pc - sect.baseaddr + sect.vaddr)
   750  				break
   751  			}
   752  		}
   753  	}
   754  	return res, true
   755  }
   756  
   757  // funcName returns the string at nameOff in the function name table.
   758  func (md *moduledata) funcName(nameOff int32) string {
   759  	if nameOff == 0 {
   760  		return ""
   761  	}
   762  	return gostringnocopy(&md.funcnametab[nameOff])
   763  }
   764  
   765  // Despite being an exported symbol,
   766  // FuncForPC is linknamed by widely used packages.
   767  // Notable members of the hall of shame include:
   768  //   - gitee.com/quant1x/gox
   769  //
   770  // Do not remove or change the type signature.
   771  // See go.dev/issue/67401.
   772  //
   773  // Note that this comment is not part of the doc comment.
   774  //
   775  //go:linkname FuncForPC
   776  
   777  // FuncForPC returns a *[Func] describing the function that contains the
   778  // given program counter address, or else nil.
   779  //
   780  // If pc represents multiple functions because of inlining, it returns
   781  // the *Func describing the innermost function, but with an entry of
   782  // the outermost function.
   783  func FuncForPC(pc uintptr) *Func {
   784  	f := findfunc(pc)
   785  	if !f.valid() {
   786  		return nil
   787  	}
   788  	// This must interpret PC non-strictly so bad PCs (those between functions) don't crash the runtime.
   789  	// We just report the preceding function in that situation. See issue 29735.
   790  	// TODO: Perhaps we should report no function at all in that case.
   791  	// The runtime currently doesn't have function end info, alas.
   792  	u, uf := newInlineUnwinder(f, pc)
   793  	if !u.isInlined(uf) {
   794  		return f._Func()
   795  	}
   796  	sf := u.srcFunc(uf)
   797  	file, line := u.fileLine(uf)
   798  	fi := &funcinl{
   799  		ones:      ^uint32(0),
   800  		entry:     f.entry(), // entry of the real (the outermost) function.
   801  		name:      sf.name(),
   802  		file:      file,
   803  		line:      int32(line),
   804  		startLine: sf.startLine,
   805  	}
   806  	return (*Func)(unsafe.Pointer(fi))
   807  }
   808  
   809  // Name returns the name of the function.
   810  func (f *Func) Name() string {
   811  	if f == nil {
   812  		return ""
   813  	}
   814  	fn := f.raw()
   815  	if fn.isInlined() { // inlined version
   816  		fi := (*funcinl)(unsafe.Pointer(fn))
   817  		return funcNameForPrint(fi.name)
   818  	}
   819  	return funcNameForPrint(funcname(f.funcInfo()))
   820  }
   821  
   822  // Entry returns the entry address of the function.
   823  func (f *Func) Entry() uintptr {
   824  	fn := f.raw()
   825  	if fn.isInlined() { // inlined version
   826  		fi := (*funcinl)(unsafe.Pointer(fn))
   827  		return fi.entry
   828  	}
   829  	return fn.funcInfo().entry()
   830  }
   831  
   832  // FileLine returns the file name and line number of the
   833  // source code corresponding to the program counter pc.
   834  // The result will not be accurate if pc is not a program
   835  // counter within f.
   836  func (f *Func) FileLine(pc uintptr) (file string, line int) {
   837  	fn := f.raw()
   838  	if fn.isInlined() { // inlined version
   839  		fi := (*funcinl)(unsafe.Pointer(fn))
   840  		return fi.file, int(fi.line)
   841  	}
   842  	// Pass strict=false here, because anyone can call this function,
   843  	// and they might just be wrong about targetpc belonging to f.
   844  	file, line32 := funcline1(f.funcInfo(), pc, false)
   845  	return file, int(line32)
   846  }
   847  
   848  // startLine returns the starting line number of the function. i.e., the line
   849  // number of the func keyword.
   850  func (f *Func) startLine() int32 {
   851  	fn := f.raw()
   852  	if fn.isInlined() { // inlined version
   853  		fi := (*funcinl)(unsafe.Pointer(fn))
   854  		return fi.startLine
   855  	}
   856  	return fn.funcInfo().startLine
   857  }
   858  
   859  // findmoduledatap looks up the moduledata for a PC.
   860  //
   861  // It is nosplit because it's part of the isgoexception
   862  // implementation.
   863  //
   864  //go:nosplit
   865  func findmoduledatap(pc uintptr) *moduledata {
   866  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   867  		if datap.minpc <= pc && pc < datap.maxpc {
   868  			return datap
   869  		}
   870  	}
   871  	return nil
   872  }
   873  
   874  type funcInfo struct {
   875  	*_func
   876  	datap *moduledata
   877  }
   878  
   879  func (f funcInfo) valid() bool {
   880  	return f._func != nil
   881  }
   882  
   883  func (f funcInfo) _Func() *Func {
   884  	return (*Func)(unsafe.Pointer(f._func))
   885  }
   886  
   887  // isInlined reports whether f should be re-interpreted as a *funcinl.
   888  func (f *_func) isInlined() bool {
   889  	return f.entryOff == ^uint32(0) // see comment for funcinl.ones
   890  }
   891  
   892  // entry returns the entry PC for f.
   893  //
   894  // entry should be an internal detail,
   895  // but widely used packages access it using linkname.
   896  // Notable members of the hall of shame include:
   897  //   - github.com/phuslu/log
   898  //
   899  // Do not remove or change the type signature.
   900  // See go.dev/issue/67401.
   901  func (f funcInfo) entry() uintptr {
   902  	return f.datap.textAddr(f.entryOff)
   903  }
   904  
   905  //go:linkname badFuncInfoEntry runtime.funcInfo.entry
   906  func badFuncInfoEntry(funcInfo) uintptr
   907  
   908  // findfunc looks up function metadata for a PC.
   909  //
   910  // It is nosplit because it's part of the isgoexception
   911  // implementation.
   912  //
   913  // findfunc should be an internal detail,
   914  // but widely used packages access it using linkname.
   915  // Notable members of the hall of shame include:
   916  //   - github.com/phuslu/log
   917  //
   918  // Do not remove or change the type signature.
   919  // See go.dev/issue/67401.
   920  //
   921  //go:nosplit
   922  //go:linkname findfunc
   923  func findfunc(pc uintptr) funcInfo {
   924  	datap := findmoduledatap(pc)
   925  	if datap == nil {
   926  		return funcInfo{}
   927  	}
   928  	const nsub = uintptr(len(findfuncbucket{}.subbuckets))
   929  
   930  	pcOff, ok := datap.textOff(pc)
   931  	if !ok {
   932  		return funcInfo{}
   933  	}
   934  
   935  	x := uintptr(pcOff) + datap.text - datap.minpc // TODO: are datap.text and datap.minpc always equal?
   936  	if GOARCH == "wasm" {
   937  		// On Wasm, pcOff is the function index, whereas
   938  		// the "PC" is function index << 16 + block index.
   939  		x = uintptr(pcOff)<<16 + datap.text - datap.minpc
   940  	}
   941  	b := x / abi.FuncTabBucketSize
   942  	i := x % abi.FuncTabBucketSize / (abi.FuncTabBucketSize / nsub)
   943  
   944  	ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
   945  	idx := ffb.idx + uint32(ffb.subbuckets[i])
   946  
   947  	// Find the ftab entry.
   948  	for datap.ftab[idx+1].entryoff <= pcOff {
   949  		idx++
   950  	}
   951  
   952  	funcoff := datap.ftab[idx].funcoff
   953  	return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[funcoff])), datap}
   954  }
   955  
   956  // A srcFunc represents a logical function in the source code. This may
   957  // correspond to an actual symbol in the binary text, or it may correspond to a
   958  // source function that has been inlined.
   959  type srcFunc struct {
   960  	datap     *moduledata
   961  	nameOff   int32
   962  	startLine int32
   963  	funcID    abi.FuncID
   964  }
   965  
   966  func (f funcInfo) srcFunc() srcFunc {
   967  	if !f.valid() {
   968  		return srcFunc{}
   969  	}
   970  	return srcFunc{f.datap, f.nameOff, f.startLine, f.funcID}
   971  }
   972  
   973  // name should be an internal detail,
   974  // but widely used packages access it using linkname.
   975  // Notable members of the hall of shame include:
   976  //   - github.com/phuslu/log
   977  //
   978  // Do not remove or change the type signature.
   979  // See go.dev/issue/67401.
   980  func (s srcFunc) name() string {
   981  	if s.datap == nil {
   982  		return ""
   983  	}
   984  	return s.datap.funcName(s.nameOff)
   985  }
   986  
   987  //go:linkname badSrcFuncName runtime.srcFunc.name
   988  func badSrcFuncName(srcFunc) string
   989  
   990  type pcvalueCache struct {
   991  	entries [2][8]pcvalueCacheEnt
   992  	inUse   int
   993  }
   994  
   995  type pcvalueCacheEnt struct {
   996  	// targetpc and off together are the key of this cache entry.
   997  	targetpc uintptr
   998  	off      uint32
   999  
  1000  	val   int32   // The value of this entry.
  1001  	valPC uintptr // The PC at which val starts
  1002  }
  1003  
  1004  // pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc.
  1005  // It must be very cheap to calculate.
  1006  // For now, align to goarch.PtrSize and reduce mod the number of entries.
  1007  // In practice, this appears to be fairly randomly and evenly distributed.
  1008  func pcvalueCacheKey(targetpc uintptr) uintptr {
  1009  	return (targetpc / goarch.PtrSize) % uintptr(len(pcvalueCache{}.entries))
  1010  }
  1011  
  1012  // Returns the PCData value, and the PC where this value starts.
  1013  func pcvalue(f funcInfo, off uint32, targetpc uintptr, strict bool) (int32, uintptr) {
  1014  	// If true, when we get a cache hit, still look up the data and make sure it
  1015  	// matches the cached contents.
  1016  	const debugCheckCache = false
  1017  
  1018  	// If true, skip checking the cache entirely.
  1019  	const skipCache = false
  1020  
  1021  	if off == 0 {
  1022  		return -1, 0
  1023  	}
  1024  
  1025  	// Check the cache. This speeds up walks of deep stacks, which
  1026  	// tend to have the same recursive functions over and over,
  1027  	// or repetitive stacks between goroutines.
  1028  	var checkVal int32
  1029  	var checkPC uintptr
  1030  	ck := pcvalueCacheKey(targetpc)
  1031  	if !skipCache {
  1032  		mp := acquirem()
  1033  		cache := &mp.pcvalueCache
  1034  		// The cache can be used by the signal handler on this M. Avoid
  1035  		// re-entrant use of the cache. The signal handler can also write inUse,
  1036  		// but will always restore its value, so we can use a regular increment
  1037  		// even if we get signaled in the middle of it.
  1038  		cache.inUse++
  1039  		if cache.inUse == 1 {
  1040  			for i := range cache.entries[ck] {
  1041  				// We check off first because we're more
  1042  				// likely to have multiple entries with
  1043  				// different offsets for the same targetpc
  1044  				// than the other way around, so we'll usually
  1045  				// fail in the first clause.
  1046  				ent := &cache.entries[ck][i]
  1047  				if ent.off == off && ent.targetpc == targetpc {
  1048  					val, pc := ent.val, ent.valPC
  1049  					if debugCheckCache {
  1050  						checkVal, checkPC = ent.val, ent.valPC
  1051  						break
  1052  					} else {
  1053  						cache.inUse--
  1054  						releasem(mp)
  1055  						return val, pc
  1056  					}
  1057  				}
  1058  			}
  1059  		} else if debugCheckCache && (cache.inUse < 1 || cache.inUse > 2) {
  1060  			// Catch accounting errors or deeply reentrant use. In principle
  1061  			// "inUse" should never exceed 2.
  1062  			throw("cache.inUse out of range")
  1063  		}
  1064  		cache.inUse--
  1065  		releasem(mp)
  1066  	}
  1067  
  1068  	if !f.valid() {
  1069  		if strict && panicking.Load() == 0 {
  1070  			println("runtime: no module data for", hex(f.entry()))
  1071  			throw("no module data")
  1072  		}
  1073  		return -1, 0
  1074  	}
  1075  	datap := f.datap
  1076  	p := datap.pctab[off:]
  1077  	pc := f.entry()
  1078  	prevpc := pc
  1079  	val := int32(-1)
  1080  	for {
  1081  		var ok bool
  1082  		p, ok = step(p, &pc, &val, pc == f.entry())
  1083  		if !ok {
  1084  			break
  1085  		}
  1086  		if targetpc < pc {
  1087  			// Replace a random entry in the cache. Random
  1088  			// replacement prevents a performance cliff if
  1089  			// a recursive stack's cycle is slightly
  1090  			// larger than the cache.
  1091  			// Put the new element at the beginning,
  1092  			// since it is the most likely to be newly used.
  1093  			if debugCheckCache && checkPC != 0 {
  1094  				if checkVal != val || checkPC != prevpc {
  1095  					print("runtime: table value ", val, "@", prevpc, " != cache value ", checkVal, "@", checkPC, " at PC ", targetpc, " off ", off, "\n")
  1096  					throw("bad pcvalue cache")
  1097  				}
  1098  			} else {
  1099  				mp := acquirem()
  1100  				cache := &mp.pcvalueCache
  1101  				cache.inUse++
  1102  				if cache.inUse == 1 {
  1103  					e := &cache.entries[ck]
  1104  					ci := cheaprandn(uint32(len(cache.entries[ck])))
  1105  					e[ci] = e[0]
  1106  					e[0] = pcvalueCacheEnt{
  1107  						targetpc: targetpc,
  1108  						off:      off,
  1109  						val:      val,
  1110  						valPC:    prevpc,
  1111  					}
  1112  				}
  1113  				cache.inUse--
  1114  				releasem(mp)
  1115  			}
  1116  
  1117  			return val, prevpc
  1118  		}
  1119  		prevpc = pc
  1120  	}
  1121  
  1122  	// If there was a table, it should have covered all program counters.
  1123  	// If not, something is wrong.
  1124  	if panicking.Load() != 0 || !strict {
  1125  		return -1, 0
  1126  	}
  1127  
  1128  	print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
  1129  
  1130  	p = datap.pctab[off:]
  1131  	pc = f.entry()
  1132  	val = -1
  1133  	for {
  1134  		var ok bool
  1135  		p, ok = step(p, &pc, &val, pc == f.entry())
  1136  		if !ok {
  1137  			break
  1138  		}
  1139  		print("\tvalue=", val, " until pc=", hex(pc), "\n")
  1140  	}
  1141  
  1142  	throw("invalid runtime symbol table")
  1143  	return -1, 0
  1144  }
  1145  
  1146  func funcname(f funcInfo) string {
  1147  	if !f.valid() {
  1148  		return ""
  1149  	}
  1150  	return f.datap.funcName(f.nameOff)
  1151  }
  1152  
  1153  func funcpkgpath(f funcInfo) string {
  1154  	name := funcNameForPrint(funcname(f))
  1155  	i := len(name) - 1
  1156  	for ; i > 0; i-- {
  1157  		if name[i] == '/' {
  1158  			break
  1159  		}
  1160  	}
  1161  	for ; i < len(name); i++ {
  1162  		if name[i] == '.' {
  1163  			break
  1164  		}
  1165  	}
  1166  	return name[:i]
  1167  }
  1168  
  1169  func funcfile(f funcInfo, fileno int32) string {
  1170  	datap := f.datap
  1171  	if !f.valid() {
  1172  		return "?"
  1173  	}
  1174  	// Make sure the cu index and file offset are valid
  1175  	if fileoff := datap.cutab[f.cuOffset+uint32(fileno)]; fileoff != ^uint32(0) {
  1176  		return gostringnocopy(&datap.filetab[fileoff])
  1177  	}
  1178  	// pcln section is corrupt.
  1179  	return "?"
  1180  }
  1181  
  1182  // funcline1 should be an internal detail,
  1183  // but widely used packages access it using linkname.
  1184  // Notable members of the hall of shame include:
  1185  //   - github.com/phuslu/log
  1186  //
  1187  // Do not remove or change the type signature.
  1188  // See go.dev/issue/67401.
  1189  //
  1190  //go:linkname funcline1
  1191  func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) {
  1192  	datap := f.datap
  1193  	if !f.valid() {
  1194  		return "?", 0
  1195  	}
  1196  	fileno, _ := pcvalue(f, f.pcfile, targetpc, strict)
  1197  	line, _ = pcvalue(f, f.pcln, targetpc, strict)
  1198  	if fileno == -1 || line == -1 || int(fileno) >= len(datap.filetab) {
  1199  		// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
  1200  		return "?", 0
  1201  	}
  1202  	file = funcfile(f, fileno)
  1203  	return
  1204  }
  1205  
  1206  func funcline(f funcInfo, targetpc uintptr) (file string, line int32) {
  1207  	return funcline1(f, targetpc, true)
  1208  }
  1209  
  1210  func funcspdelta(f funcInfo, targetpc uintptr) int32 {
  1211  	x, _ := pcvalue(f, f.pcsp, targetpc, true)
  1212  	if debugPcln && x&(goarch.PtrSize-1) != 0 {
  1213  		print("invalid spdelta ", funcname(f), " ", hex(f.entry()), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
  1214  		throw("bad spdelta")
  1215  	}
  1216  	return x
  1217  }
  1218  
  1219  // funcMaxSPDelta returns the maximum spdelta at any point in f.
  1220  func funcMaxSPDelta(f funcInfo) int32 {
  1221  	datap := f.datap
  1222  	p := datap.pctab[f.pcsp:]
  1223  	pc := f.entry()
  1224  	val := int32(-1)
  1225  	most := int32(0)
  1226  	for {
  1227  		var ok bool
  1228  		p, ok = step(p, &pc, &val, pc == f.entry())
  1229  		if !ok {
  1230  			return most
  1231  		}
  1232  		most = max(most, val)
  1233  	}
  1234  }
  1235  
  1236  func pcdatastart(f funcInfo, table uint32) uint32 {
  1237  	return *(*uint32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
  1238  }
  1239  
  1240  func pcdatavalue(f funcInfo, table uint32, targetpc uintptr) int32 {
  1241  	if table >= f.npcdata {
  1242  		return -1
  1243  	}
  1244  	r, _ := pcvalue(f, pcdatastart(f, table), targetpc, true)
  1245  	return r
  1246  }
  1247  
  1248  func pcdatavalue1(f funcInfo, table uint32, targetpc uintptr, strict bool) int32 {
  1249  	if table >= f.npcdata {
  1250  		return -1
  1251  	}
  1252  	r, _ := pcvalue(f, pcdatastart(f, table), targetpc, strict)
  1253  	return r
  1254  }
  1255  
  1256  // Like pcdatavalue, but also return the start PC of this PCData value.
  1257  func pcdatavalue2(f funcInfo, table uint32, targetpc uintptr) (int32, uintptr) {
  1258  	if table >= f.npcdata {
  1259  		return -1, 0
  1260  	}
  1261  	return pcvalue(f, pcdatastart(f, table), targetpc, true)
  1262  }
  1263  
  1264  // funcdata returns a pointer to the ith funcdata for f.
  1265  // funcdata should be kept in sync with cmd/link:writeFuncs.
  1266  func funcdata(f funcInfo, i uint8) unsafe.Pointer {
  1267  	if i < 0 || i >= f.nfuncdata {
  1268  		return nil
  1269  	}
  1270  	base := f.datap.gofunc // load gofunc address early so that we calculate during cache misses
  1271  	p := uintptr(unsafe.Pointer(&f.nfuncdata)) + unsafe.Sizeof(f.nfuncdata) + uintptr(f.npcdata)*4 + uintptr(i)*4
  1272  	off := *(*uint32)(unsafe.Pointer(p))
  1273  	// Return off == ^uint32(0) ? 0 : f.datap.gofunc + uintptr(off), but without branches.
  1274  	// The compiler calculates mask on most architectures using conditional assignment.
  1275  	var mask uintptr
  1276  	if off == ^uint32(0) {
  1277  		mask = 1
  1278  	}
  1279  	mask--
  1280  	raw := base + uintptr(off)
  1281  	return unsafe.Pointer(raw & mask)
  1282  }
  1283  
  1284  // step advances to the next pc, value pair in the encoded table.
  1285  func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
  1286  	// For both uvdelta and pcdelta, the common case (~70%)
  1287  	// is that they are a single byte. If so, avoid calling readvarint.
  1288  	uvdelta := uint32(p[0])
  1289  	if uvdelta == 0 && !first {
  1290  		return nil, false
  1291  	}
  1292  	n := uint32(1)
  1293  	if uvdelta&0x80 != 0 {
  1294  		n, uvdelta = readvarint(p)
  1295  	}
  1296  	*val += int32(-(uvdelta & 1) ^ (uvdelta >> 1))
  1297  	p = p[n:]
  1298  
  1299  	pcdelta := uint32(p[0])
  1300  	n = 1
  1301  	if pcdelta&0x80 != 0 {
  1302  		n, pcdelta = readvarint(p)
  1303  	}
  1304  	p = p[n:]
  1305  	*pc += uintptr(pcdelta * sys.PCQuantum)
  1306  	return p, true
  1307  }
  1308  
  1309  // readvarint reads a varint from p.
  1310  func readvarint(p []byte) (read uint32, val uint32) {
  1311  	var v, shift, n uint32
  1312  	for {
  1313  		b := p[n]
  1314  		n++
  1315  		v |= uint32(b&0x7F) << (shift & 31)
  1316  		if b&0x80 == 0 {
  1317  			break
  1318  		}
  1319  		shift += 7
  1320  	}
  1321  	return n, v
  1322  }
  1323  
  1324  type stackmap struct {
  1325  	n        int32   // number of bitmaps
  1326  	nbit     int32   // number of bits in each bitmap
  1327  	bytedata [1]byte // bitmaps, each starting on a byte boundary
  1328  }
  1329  
  1330  //go:nowritebarrier
  1331  func stackmapdata(stkmap *stackmap, n int32) bitvector {
  1332  	// Check this invariant only when stackDebug is on at all.
  1333  	// The invariant is already checked by many of stackmapdata's callers,
  1334  	// and disabling it by default allows stackmapdata to be inlined.
  1335  	if stackDebug > 0 && (n < 0 || n >= stkmap.n) {
  1336  		throw("stackmapdata: index out of range")
  1337  	}
  1338  	return bitvector{stkmap.nbit, addb(&stkmap.bytedata[0], uintptr(n*((stkmap.nbit+7)>>3)))}
  1339  }
  1340  

View as plain text