github.com/twelsh-aw/go/src@v0.0.0-20230516233729-a56fe86a7c81/runtime/symtab.go (about)

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