Source file src/runtime/symtab.go

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

View as plain text