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

View as plain text