Black Lives Matter. Support the Equal Justice Initiative.

Source file src/runtime/symtab.go

Documentation: runtime

     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  	"runtime/internal/atomic"
     9  	"runtime/internal/sys"
    10  	"unsafe"
    11  )
    12  
    13  // Frames may be used to get function/file/line information for a
    14  // slice of PC values returned by Callers.
    15  type Frames struct {
    16  	// callers is a slice of PCs that have not yet been expanded to frames.
    17  	callers []uintptr
    18  
    19  	// frames is a slice of Frames that have yet to be returned.
    20  	frames     []Frame
    21  	frameStore [2]Frame
    22  }
    23  
    24  // Frame is the information returned by Frames for each call frame.
    25  type Frame struct {
    26  	// PC is the program counter for the location in this frame.
    27  	// For a frame that calls another frame, this will be the
    28  	// program counter of a call instruction. Because of inlining,
    29  	// multiple frames may have the same PC value, but different
    30  	// symbolic information.
    31  	PC uintptr
    32  
    33  	// Func is the Func value of this call frame. This may be nil
    34  	// for non-Go code or fully inlined functions.
    35  	Func *Func
    36  
    37  	// Function is the package path-qualified function name of
    38  	// this call frame. If non-empty, this string uniquely
    39  	// identifies a single function in the program.
    40  	// This may be the empty string if not known.
    41  	// If Func is not nil then Function == Func.Name().
    42  	Function string
    43  
    44  	// File and Line are the file name and line number of the
    45  	// location in this frame. For non-leaf frames, this will be
    46  	// the location of a call. These may be the empty string and
    47  	// zero, respectively, if not known.
    48  	File string
    49  	Line int
    50  
    51  	// Entry point program counter for the function; may be zero
    52  	// if not known. If Func is not nil then Entry ==
    53  	// Func.Entry().
    54  	Entry uintptr
    55  
    56  	// The runtime's internal view of the function. This field
    57  	// is set (funcInfo.valid() returns true) only for Go functions,
    58  	// not for C functions.
    59  	funcInfo funcInfo
    60  }
    61  
    62  // CallersFrames takes a slice of PC values returned by Callers and
    63  // prepares to return function/file/line information.
    64  // Do not change the slice until you are done with the Frames.
    65  func CallersFrames(callers []uintptr) *Frames {
    66  	f := &Frames{callers: callers}
    67  	f.frames = f.frameStore[:0]
    68  	return f
    69  }
    70  
    71  // Next returns frame information for the next caller.
    72  // If more is false, there are no more callers (the Frame value is valid).
    73  func (ci *Frames) Next() (frame Frame, more bool) {
    74  	for len(ci.frames) < 2 {
    75  		// Find the next frame.
    76  		// We need to look for 2 frames so we know what
    77  		// to return for the "more" result.
    78  		if len(ci.callers) == 0 {
    79  			break
    80  		}
    81  		pc := ci.callers[0]
    82  		ci.callers = ci.callers[1:]
    83  		funcInfo := findfunc(pc)
    84  		if !funcInfo.valid() {
    85  			if cgoSymbolizer != nil {
    86  				// Pre-expand cgo frames. We could do this
    87  				// incrementally, too, but there's no way to
    88  				// avoid allocation in this case anyway.
    89  				ci.frames = append(ci.frames, expandCgoFrames(pc)...)
    90  			}
    91  			continue
    92  		}
    93  		f := funcInfo._Func()
    94  		entry := f.Entry()
    95  		if pc > entry {
    96  			// We store the pc of the start of the instruction following
    97  			// the instruction in question (the call or the inline mark).
    98  			// This is done for historical reasons, and to make FuncForPC
    99  			// work correctly for entries in the result of runtime.Callers.
   100  			pc--
   101  		}
   102  		name := funcname(funcInfo)
   103  		if inldata := funcdata(funcInfo, _FUNCDATA_InlTree); inldata != nil {
   104  			inltree := (*[1 << 20]inlinedCall)(inldata)
   105  			ix := pcdatavalue(funcInfo, _PCDATA_InlTreeIndex, pc, nil)
   106  			if ix >= 0 {
   107  				// Note: entry is not modified. It always refers to a real frame, not an inlined one.
   108  				f = nil
   109  				name = funcnameFromNameoff(funcInfo, inltree[ix].func_)
   110  				// File/line is already correct.
   111  				// TODO: remove file/line from InlinedCall?
   112  			}
   113  		}
   114  		ci.frames = append(ci.frames, Frame{
   115  			PC:       pc,
   116  			Func:     f,
   117  			Function: name,
   118  			Entry:    entry,
   119  			funcInfo: funcInfo,
   120  			// Note: File,Line set below
   121  		})
   122  	}
   123  
   124  	// Pop one frame from the frame list. Keep the rest.
   125  	// Avoid allocation in the common case, which is 1 or 2 frames.
   126  	switch len(ci.frames) {
   127  	case 0: // In the rare case when there are no frames at all, we return Frame{}.
   128  		return
   129  	case 1:
   130  		frame = ci.frames[0]
   131  		ci.frames = ci.frameStore[:0]
   132  	case 2:
   133  		frame = ci.frames[0]
   134  		ci.frameStore[0] = ci.frames[1]
   135  		ci.frames = ci.frameStore[:1]
   136  	default:
   137  		frame = ci.frames[0]
   138  		ci.frames = ci.frames[1:]
   139  	}
   140  	more = len(ci.frames) > 0
   141  	if frame.funcInfo.valid() {
   142  		// Compute file/line just before we need to return it,
   143  		// as it can be expensive. This avoids computing file/line
   144  		// for the Frame we find but don't return. See issue 32093.
   145  		file, line := funcline1(frame.funcInfo, frame.PC, false)
   146  		frame.File, frame.Line = file, int(line)
   147  	}
   148  	return
   149  }
   150  
   151  // runtime_expandFinalInlineFrame expands the final pc in stk to include all
   152  // "callers" if pc is inline.
   153  //
   154  //go:linkname runtime_expandFinalInlineFrame runtime/pprof.runtime_expandFinalInlineFrame
   155  func runtime_expandFinalInlineFrame(stk []uintptr) []uintptr {
   156  	if len(stk) == 0 {
   157  		return stk
   158  	}
   159  	pc := stk[len(stk)-1]
   160  	tracepc := pc - 1
   161  
   162  	f := findfunc(tracepc)
   163  	if !f.valid() {
   164  		// Not a Go function.
   165  		return stk
   166  	}
   167  
   168  	inldata := funcdata(f, _FUNCDATA_InlTree)
   169  	if inldata == nil {
   170  		// Nothing inline in f.
   171  		return stk
   172  	}
   173  
   174  	// Treat the previous func as normal. We haven't actually checked, but
   175  	// since this pc was included in the stack, we know it shouldn't be
   176  	// elided.
   177  	lastFuncID := funcID_normal
   178  
   179  	// Remove pc from stk; we'll re-add it below.
   180  	stk = stk[:len(stk)-1]
   181  
   182  	// See inline expansion in gentraceback.
   183  	var cache pcvalueCache
   184  	inltree := (*[1 << 20]inlinedCall)(inldata)
   185  	for {
   186  		ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, &cache)
   187  		if ix < 0 {
   188  			break
   189  		}
   190  		if inltree[ix].funcID == funcID_wrapper && elideWrapperCalling(lastFuncID) {
   191  			// ignore wrappers
   192  		} else {
   193  			stk = append(stk, pc)
   194  		}
   195  		lastFuncID = inltree[ix].funcID
   196  		// Back up to an instruction in the "caller".
   197  		tracepc = f.entry + uintptr(inltree[ix].parentPc)
   198  		pc = tracepc + 1
   199  	}
   200  
   201  	// N.B. we want to keep the last parentPC which is not inline.
   202  	stk = append(stk, pc)
   203  
   204  	return stk
   205  }
   206  
   207  // expandCgoFrames expands frame information for pc, known to be
   208  // a non-Go function, using the cgoSymbolizer hook. expandCgoFrames
   209  // returns nil if pc could not be expanded.
   210  func expandCgoFrames(pc uintptr) []Frame {
   211  	arg := cgoSymbolizerArg{pc: pc}
   212  	callCgoSymbolizer(&arg)
   213  
   214  	if arg.file == nil && arg.funcName == nil {
   215  		// No useful information from symbolizer.
   216  		return nil
   217  	}
   218  
   219  	var frames []Frame
   220  	for {
   221  		frames = append(frames, Frame{
   222  			PC:       pc,
   223  			Func:     nil,
   224  			Function: gostring(arg.funcName),
   225  			File:     gostring(arg.file),
   226  			Line:     int(arg.lineno),
   227  			Entry:    arg.entry,
   228  			// funcInfo is zero, which implies !funcInfo.valid().
   229  			// That ensures that we use the File/Line info given here.
   230  		})
   231  		if arg.more == 0 {
   232  			break
   233  		}
   234  		callCgoSymbolizer(&arg)
   235  	}
   236  
   237  	// No more frames for this PC. Tell the symbolizer we are done.
   238  	// We don't try to maintain a single cgoSymbolizerArg for the
   239  	// whole use of Frames, because there would be no good way to tell
   240  	// the symbolizer when we are done.
   241  	arg.pc = 0
   242  	callCgoSymbolizer(&arg)
   243  
   244  	return frames
   245  }
   246  
   247  // NOTE: Func does not expose the actual unexported fields, because we return *Func
   248  // values to users, and we want to keep them from being able to overwrite the data
   249  // with (say) *f = Func{}.
   250  // All code operating on a *Func must call raw() to get the *_func
   251  // or funcInfo() to get the funcInfo instead.
   252  
   253  // A Func represents a Go function in the running binary.
   254  type Func struct {
   255  	opaque struct{} // unexported field to disallow conversions
   256  }
   257  
   258  func (f *Func) raw() *_func {
   259  	return (*_func)(unsafe.Pointer(f))
   260  }
   261  
   262  func (f *Func) funcInfo() funcInfo {
   263  	fn := f.raw()
   264  	return funcInfo{fn, findmoduledatap(fn.entry)}
   265  }
   266  
   267  // PCDATA and FUNCDATA table indexes.
   268  //
   269  // See funcdata.h and ../cmd/internal/objabi/funcdata.go.
   270  const (
   271  	_PCDATA_RegMapIndex   = 0 // if !go115ReduceLiveness
   272  	_PCDATA_UnsafePoint   = 0 // if go115ReduceLiveness
   273  	_PCDATA_StackMapIndex = 1
   274  	_PCDATA_InlTreeIndex  = 2
   275  
   276  	_FUNCDATA_ArgsPointerMaps    = 0
   277  	_FUNCDATA_LocalsPointerMaps  = 1
   278  	_FUNCDATA_RegPointerMaps     = 2 // if !go115ReduceLiveness
   279  	_FUNCDATA_StackObjects       = 3
   280  	_FUNCDATA_InlTree            = 4
   281  	_FUNCDATA_OpenCodedDeferInfo = 5
   282  
   283  	_ArgsSizeUnknown = -0x80000000
   284  )
   285  
   286  const (
   287  	// PCDATA_UnsafePoint values.
   288  	_PCDATA_UnsafePointSafe   = -1 // Safe for async preemption
   289  	_PCDATA_UnsafePointUnsafe = -2 // Unsafe for async preemption
   290  
   291  	// _PCDATA_Restart1(2) apply on a sequence of instructions, within
   292  	// which if an async preemption happens, we should back off the PC
   293  	// to the start of the sequence when resume.
   294  	// We need two so we can distinguish the start/end of the sequence
   295  	// in case that two sequences are next to each other.
   296  	_PCDATA_Restart1 = -3
   297  	_PCDATA_Restart2 = -4
   298  
   299  	// Like _PCDATA_RestartAtEntry, but back to function entry if async
   300  	// preempted.
   301  	_PCDATA_RestartAtEntry = -5
   302  )
   303  
   304  // A FuncID identifies particular functions that need to be treated
   305  // specially by the runtime.
   306  // Note that in some situations involving plugins, there may be multiple
   307  // copies of a particular special runtime function.
   308  // Note: this list must match the list in cmd/internal/objabi/funcid.go.
   309  type funcID uint8
   310  
   311  const (
   312  	funcID_normal funcID = iota // not a special function
   313  	funcID_runtime_main
   314  	funcID_goexit
   315  	funcID_jmpdefer
   316  	funcID_mcall
   317  	funcID_morestack
   318  	funcID_mstart
   319  	funcID_rt0_go
   320  	funcID_asmcgocall
   321  	funcID_sigpanic
   322  	funcID_runfinq
   323  	funcID_gcBgMarkWorker
   324  	funcID_systemstack_switch
   325  	funcID_systemstack
   326  	funcID_cgocallback_gofunc
   327  	funcID_gogo
   328  	funcID_externalthreadhandler
   329  	funcID_debugCallV1
   330  	funcID_gopanic
   331  	funcID_panicwrap
   332  	funcID_handleAsyncEvent
   333  	funcID_asyncPreempt
   334  	funcID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.)
   335  )
   336  
   337  // moduledata records information about the layout of the executable
   338  // image. It is written by the linker. Any changes here must be
   339  // matched changes to the code in cmd/internal/ld/symtab.go:symtab.
   340  // moduledata is stored in statically allocated non-pointer memory;
   341  // none of the pointers here are visible to the garbage collector.
   342  type moduledata struct {
   343  	pclntable    []byte
   344  	ftab         []functab
   345  	filetab      []uint32
   346  	findfunctab  uintptr
   347  	minpc, maxpc uintptr
   348  
   349  	text, etext           uintptr
   350  	noptrdata, enoptrdata uintptr
   351  	data, edata           uintptr
   352  	bss, ebss             uintptr
   353  	noptrbss, enoptrbss   uintptr
   354  	end, gcdata, gcbss    uintptr
   355  	types, etypes         uintptr
   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  	modulename   string
   367  	modulehashes []modulehash
   368  
   369  	hasmain uint8 // 1 if module contains the main function, 0 otherwise
   370  
   371  	gcdatamask, gcbssmask bitvector
   372  
   373  	typemap map[typeOff]*_type // offset to *_rtype in previous module
   374  
   375  	bad bool // module failed to load and should be ignored
   376  
   377  	next *moduledata
   378  }
   379  
   380  // A modulehash is used to compare the ABI of a new module or a
   381  // package in a new module with the loaded program.
   382  //
   383  // For each shared library a module links against, the linker creates an entry in the
   384  // moduledata.modulehashes slice containing the name of the module, the abi hash seen
   385  // at link time and a pointer to the runtime abi hash. These are checked in
   386  // moduledataverify1 below.
   387  //
   388  // For each loaded plugin, the pkghashes slice has a modulehash of the
   389  // newly loaded package that can be used to check the plugin's version of
   390  // a package against any previously loaded version of the package.
   391  // This is done in plugin.lastmoduleinit.
   392  type modulehash struct {
   393  	modulename   string
   394  	linktimehash string
   395  	runtimehash  *string
   396  }
   397  
   398  // pinnedTypemaps are the map[typeOff]*_type from the moduledata objects.
   399  //
   400  // These typemap objects are allocated at run time on the heap, but the
   401  // only direct reference to them is in the moduledata, created by the
   402  // linker and marked SNOPTRDATA so it is ignored by the GC.
   403  //
   404  // To make sure the map isn't collected, we keep a second reference here.
   405  var pinnedTypemaps []map[typeOff]*_type
   406  
   407  var firstmoduledata moduledata  // linker symbol
   408  var lastmoduledatap *moduledata // linker symbol
   409  var modulesSlice *[]*moduledata // see activeModules
   410  
   411  // activeModules returns a slice of active modules.
   412  //
   413  // A module is active once its gcdatamask and gcbssmask have been
   414  // assembled and it is usable by the GC.
   415  //
   416  // This is nosplit/nowritebarrier because it is called by the
   417  // cgo pointer checking code.
   418  //go:nosplit
   419  //go:nowritebarrier
   420  func activeModules() []*moduledata {
   421  	p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice)))
   422  	if p == nil {
   423  		return nil
   424  	}
   425  	return *p
   426  }
   427  
   428  // modulesinit creates the active modules slice out of all loaded modules.
   429  //
   430  // When a module is first loaded by the dynamic linker, an .init_array
   431  // function (written by cmd/link) is invoked to call addmoduledata,
   432  // appending to the module to the linked list that starts with
   433  // firstmoduledata.
   434  //
   435  // There are two times this can happen in the lifecycle of a Go
   436  // program. First, if compiled with -linkshared, a number of modules
   437  // built with -buildmode=shared can be loaded at program initialization.
   438  // Second, a Go program can load a module while running that was built
   439  // with -buildmode=plugin.
   440  //
   441  // After loading, this function is called which initializes the
   442  // moduledata so it is usable by the GC and creates a new activeModules
   443  // list.
   444  //
   445  // Only one goroutine may call modulesinit at a time.
   446  func modulesinit() {
   447  	modules := new([]*moduledata)
   448  	for md := &firstmoduledata; md != nil; md = md.next {
   449  		if md.bad {
   450  			continue
   451  		}
   452  		*modules = append(*modules, md)
   453  		if md.gcdatamask == (bitvector{}) {
   454  			md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data)
   455  			md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss)
   456  		}
   457  	}
   458  
   459  	// Modules appear in the moduledata linked list in the order they are
   460  	// loaded by the dynamic loader, with one exception: the
   461  	// firstmoduledata itself the module that contains the runtime. This
   462  	// is not always the first module (when using -buildmode=shared, it
   463  	// is typically libstd.so, the second module). The order matters for
   464  	// typelinksinit, so we swap the first module with whatever module
   465  	// contains the main function.
   466  	//
   467  	// See Issue #18729.
   468  	for i, md := range *modules {
   469  		if md.hasmain != 0 {
   470  			(*modules)[0] = md
   471  			(*modules)[i] = &firstmoduledata
   472  			break
   473  		}
   474  	}
   475  
   476  	atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules))
   477  }
   478  
   479  type functab struct {
   480  	entry   uintptr
   481  	funcoff uintptr
   482  }
   483  
   484  // Mapping information for secondary text sections
   485  
   486  type textsect struct {
   487  	vaddr    uintptr // prelinked section vaddr
   488  	length   uintptr // section length
   489  	baseaddr uintptr // relocated section address
   490  }
   491  
   492  const minfunc = 16                 // minimum function size
   493  const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table
   494  
   495  // findfunctab is an array of these structures.
   496  // Each bucket represents 4096 bytes of the text segment.
   497  // Each subbucket represents 256 bytes of the text segment.
   498  // To find a function given a pc, locate the bucket and subbucket for
   499  // that pc. Add together the idx and subbucket value to obtain a
   500  // function index. Then scan the functab array starting at that
   501  // index to find the target function.
   502  // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead.
   503  type findfuncbucket struct {
   504  	idx        uint32
   505  	subbuckets [16]byte
   506  }
   507  
   508  func moduledataverify() {
   509  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   510  		moduledataverify1(datap)
   511  	}
   512  }
   513  
   514  const debugPcln = false
   515  
   516  func moduledataverify1(datap *moduledata) {
   517  	// See golang.org/s/go12symtab for header: 0xfffffffb,
   518  	// two zero bytes, a byte giving the PC quantum,
   519  	// and a byte giving the pointer width in bytes.
   520  	pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable))
   521  	pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable))
   522  	if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize {
   523  		println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
   524  		throw("invalid function symbol table\n")
   525  	}
   526  
   527  	// ftab is lookup table for function by program counter.
   528  	nftab := len(datap.ftab) - 1
   529  	for i := 0; i < nftab; i++ {
   530  		// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
   531  		if datap.ftab[i].entry > datap.ftab[i+1].entry {
   532  			f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap}
   533  			f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap}
   534  			f2name := "end"
   535  			if i+1 < nftab {
   536  				f2name = funcname(f2)
   537  			}
   538  			println("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name)
   539  			for j := 0; j <= i; j++ {
   540  				print("\t", hex(datap.ftab[j].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}), "\n")
   541  			}
   542  			if GOOS == "aix" && isarchive {
   543  				println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive")
   544  			}
   545  			throw("invalid runtime symbol table")
   546  		}
   547  	}
   548  
   549  	if datap.minpc != datap.ftab[0].entry ||
   550  		datap.maxpc != datap.ftab[nftab].entry {
   551  		throw("minpc or maxpc invalid")
   552  	}
   553  
   554  	for _, modulehash := range datap.modulehashes {
   555  		if modulehash.linktimehash != *modulehash.runtimehash {
   556  			println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename)
   557  			throw("abi mismatch")
   558  		}
   559  	}
   560  }
   561  
   562  // FuncForPC returns a *Func describing the function that contains the
   563  // given program counter address, or else nil.
   564  //
   565  // If pc represents multiple functions because of inlining, it returns
   566  // the *Func describing the innermost function, but with an entry of
   567  // the outermost function.
   568  func FuncForPC(pc uintptr) *Func {
   569  	f := findfunc(pc)
   570  	if !f.valid() {
   571  		return nil
   572  	}
   573  	if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil {
   574  		// Note: strict=false so bad PCs (those between functions) don't crash the runtime.
   575  		// We just report the preceding function in that situation. See issue 29735.
   576  		// TODO: Perhaps we should report no function at all in that case.
   577  		// The runtime currently doesn't have function end info, alas.
   578  		if ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, pc, nil, false); ix >= 0 {
   579  			inltree := (*[1 << 20]inlinedCall)(inldata)
   580  			name := funcnameFromNameoff(f, inltree[ix].func_)
   581  			file, line := funcline(f, pc)
   582  			fi := &funcinl{
   583  				entry: f.entry, // entry of the real (the outermost) function.
   584  				name:  name,
   585  				file:  file,
   586  				line:  int(line),
   587  			}
   588  			return (*Func)(unsafe.Pointer(fi))
   589  		}
   590  	}
   591  	return f._Func()
   592  }
   593  
   594  // Name returns the name of the function.
   595  func (f *Func) Name() string {
   596  	if f == nil {
   597  		return ""
   598  	}
   599  	fn := f.raw()
   600  	if fn.entry == 0 { // inlined version
   601  		fi := (*funcinl)(unsafe.Pointer(fn))
   602  		return fi.name
   603  	}
   604  	return funcname(f.funcInfo())
   605  }
   606  
   607  // Entry returns the entry address of the function.
   608  func (f *Func) Entry() uintptr {
   609  	fn := f.raw()
   610  	if fn.entry == 0 { // inlined version
   611  		fi := (*funcinl)(unsafe.Pointer(fn))
   612  		return fi.entry
   613  	}
   614  	return fn.entry
   615  }
   616  
   617  // FileLine returns the file name and line number of the
   618  // source code corresponding to the program counter pc.
   619  // The result will not be accurate if pc is not a program
   620  // counter within f.
   621  func (f *Func) FileLine(pc uintptr) (file string, line int) {
   622  	fn := f.raw()
   623  	if fn.entry == 0 { // inlined version
   624  		fi := (*funcinl)(unsafe.Pointer(fn))
   625  		return fi.file, fi.line
   626  	}
   627  	// Pass strict=false here, because anyone can call this function,
   628  	// and they might just be wrong about targetpc belonging to f.
   629  	file, line32 := funcline1(f.funcInfo(), pc, false)
   630  	return file, int(line32)
   631  }
   632  
   633  func findmoduledatap(pc uintptr) *moduledata {
   634  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   635  		if datap.minpc <= pc && pc < datap.maxpc {
   636  			return datap
   637  		}
   638  	}
   639  	return nil
   640  }
   641  
   642  type funcInfo struct {
   643  	*_func
   644  	datap *moduledata
   645  }
   646  
   647  func (f funcInfo) valid() bool {
   648  	return f._func != nil
   649  }
   650  
   651  func (f funcInfo) _Func() *Func {
   652  	return (*Func)(unsafe.Pointer(f._func))
   653  }
   654  
   655  func findfunc(pc uintptr) funcInfo {
   656  	datap := findmoduledatap(pc)
   657  	if datap == nil {
   658  		return funcInfo{}
   659  	}
   660  	const nsub = uintptr(len(findfuncbucket{}.subbuckets))
   661  
   662  	x := pc - datap.minpc
   663  	b := x / pcbucketsize
   664  	i := x % pcbucketsize / (pcbucketsize / nsub)
   665  
   666  	ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
   667  	idx := ffb.idx + uint32(ffb.subbuckets[i])
   668  
   669  	// If the idx is beyond the end of the ftab, set it to the end of the table and search backward.
   670  	// This situation can occur if multiple text sections are generated to handle large text sections
   671  	// and the linker has inserted jump tables between them.
   672  
   673  	if idx >= uint32(len(datap.ftab)) {
   674  		idx = uint32(len(datap.ftab) - 1)
   675  	}
   676  	if pc < datap.ftab[idx].entry {
   677  		// With multiple text sections, the idx might reference a function address that
   678  		// is higher than the pc being searched, so search backward until the matching address is found.
   679  
   680  		for datap.ftab[idx].entry > pc && idx > 0 {
   681  			idx--
   682  		}
   683  		if idx == 0 {
   684  			throw("findfunc: bad findfunctab entry idx")
   685  		}
   686  	} else {
   687  		// linear search to find func with pc >= entry.
   688  		for datap.ftab[idx+1].entry <= pc {
   689  			idx++
   690  		}
   691  	}
   692  	funcoff := datap.ftab[idx].funcoff
   693  	if funcoff == ^uintptr(0) {
   694  		// With multiple text sections, there may be functions inserted by the external
   695  		// linker that are not known by Go. This means there may be holes in the PC
   696  		// range covered by the func table. The invalid funcoff value indicates a hole.
   697  		// See also cmd/link/internal/ld/pcln.go:pclntab
   698  		return funcInfo{}
   699  	}
   700  	return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[funcoff])), datap}
   701  }
   702  
   703  type pcvalueCache struct {
   704  	entries [2][8]pcvalueCacheEnt
   705  }
   706  
   707  type pcvalueCacheEnt struct {
   708  	// targetpc and off together are the key of this cache entry.
   709  	targetpc uintptr
   710  	off      int32
   711  	// val is the value of this cached pcvalue entry.
   712  	val int32
   713  }
   714  
   715  // pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc.
   716  // It must be very cheap to calculate.
   717  // For now, align to sys.PtrSize and reduce mod the number of entries.
   718  // In practice, this appears to be fairly randomly and evenly distributed.
   719  func pcvalueCacheKey(targetpc uintptr) uintptr {
   720  	return (targetpc / sys.PtrSize) % uintptr(len(pcvalueCache{}.entries))
   721  }
   722  
   723  // Returns the PCData value, and the PC where this value starts.
   724  // TODO: the start PC is returned only when cache is nil.
   725  func pcvalue(f funcInfo, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) (int32, uintptr) {
   726  	if off == 0 {
   727  		return -1, 0
   728  	}
   729  
   730  	// Check the cache. This speeds up walks of deep stacks, which
   731  	// tend to have the same recursive functions over and over.
   732  	//
   733  	// This cache is small enough that full associativity is
   734  	// cheaper than doing the hashing for a less associative
   735  	// cache.
   736  	if cache != nil {
   737  		x := pcvalueCacheKey(targetpc)
   738  		for i := range cache.entries[x] {
   739  			// We check off first because we're more
   740  			// likely to have multiple entries with
   741  			// different offsets for the same targetpc
   742  			// than the other way around, so we'll usually
   743  			// fail in the first clause.
   744  			ent := &cache.entries[x][i]
   745  			if ent.off == off && ent.targetpc == targetpc {
   746  				return ent.val, 0
   747  			}
   748  		}
   749  	}
   750  
   751  	if !f.valid() {
   752  		if strict && panicking == 0 {
   753  			print("runtime: no module data for ", hex(f.entry), "\n")
   754  			throw("no module data")
   755  		}
   756  		return -1, 0
   757  	}
   758  	datap := f.datap
   759  	p := datap.pclntable[off:]
   760  	pc := f.entry
   761  	prevpc := pc
   762  	val := int32(-1)
   763  	for {
   764  		var ok bool
   765  		p, ok = step(p, &pc, &val, pc == f.entry)
   766  		if !ok {
   767  			break
   768  		}
   769  		if targetpc < pc {
   770  			// Replace a random entry in the cache. Random
   771  			// replacement prevents a performance cliff if
   772  			// a recursive stack's cycle is slightly
   773  			// larger than the cache.
   774  			// Put the new element at the beginning,
   775  			// since it is the most likely to be newly used.
   776  			if cache != nil {
   777  				x := pcvalueCacheKey(targetpc)
   778  				e := &cache.entries[x]
   779  				ci := fastrand() % uint32(len(cache.entries[x]))
   780  				e[ci] = e[0]
   781  				e[0] = pcvalueCacheEnt{
   782  					targetpc: targetpc,
   783  					off:      off,
   784  					val:      val,
   785  				}
   786  			}
   787  
   788  			return val, prevpc
   789  		}
   790  		prevpc = pc
   791  	}
   792  
   793  	// If there was a table, it should have covered all program counters.
   794  	// If not, something is wrong.
   795  	if panicking != 0 || !strict {
   796  		return -1, 0
   797  	}
   798  
   799  	print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
   800  
   801  	p = datap.pclntable[off:]
   802  	pc = f.entry
   803  	val = -1
   804  	for {
   805  		var ok bool
   806  		p, ok = step(p, &pc, &val, pc == f.entry)
   807  		if !ok {
   808  			break
   809  		}
   810  		print("\tvalue=", val, " until pc=", hex(pc), "\n")
   811  	}
   812  
   813  	throw("invalid runtime symbol table")
   814  	return -1, 0
   815  }
   816  
   817  func cfuncname(f funcInfo) *byte {
   818  	if !f.valid() || f.nameoff == 0 {
   819  		return nil
   820  	}
   821  	return &f.datap.pclntable[f.nameoff]
   822  }
   823  
   824  func funcname(f funcInfo) string {
   825  	return gostringnocopy(cfuncname(f))
   826  }
   827  
   828  func cfuncnameFromNameoff(f funcInfo, nameoff int32) *byte {
   829  	if !f.valid() {
   830  		return nil
   831  	}
   832  	return &f.datap.pclntable[nameoff]
   833  }
   834  
   835  func funcnameFromNameoff(f funcInfo, nameoff int32) string {
   836  	return gostringnocopy(cfuncnameFromNameoff(f, nameoff))
   837  }
   838  
   839  func funcfile(f funcInfo, fileno int32) string {
   840  	datap := f.datap
   841  	if !f.valid() {
   842  		return "?"
   843  	}
   844  	return gostringnocopy(&datap.pclntable[datap.filetab[fileno]])
   845  }
   846  
   847  func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) {
   848  	datap := f.datap
   849  	if !f.valid() {
   850  		return "?", 0
   851  	}
   852  	fileno, _ := pcvalue(f, f.pcfile, targetpc, nil, strict)
   853  	line, _ = pcvalue(f, f.pcln, targetpc, nil, strict)
   854  	if fileno == -1 || line == -1 || int(fileno) >= len(datap.filetab) {
   855  		// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
   856  		return "?", 0
   857  	}
   858  	file = gostringnocopy(&datap.pclntable[datap.filetab[fileno]])
   859  	return
   860  }
   861  
   862  func funcline(f funcInfo, targetpc uintptr) (file string, line int32) {
   863  	return funcline1(f, targetpc, true)
   864  }
   865  
   866  func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 {
   867  	x, _ := pcvalue(f, f.pcsp, targetpc, cache, true)
   868  	if x&(sys.PtrSize-1) != 0 {
   869  		print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
   870  	}
   871  	return x
   872  }
   873  
   874  // funcMaxSPDelta returns the maximum spdelta at any point in f.
   875  func funcMaxSPDelta(f funcInfo) int32 {
   876  	datap := f.datap
   877  	p := datap.pclntable[f.pcsp:]
   878  	pc := f.entry
   879  	val := int32(-1)
   880  	max := int32(0)
   881  	for {
   882  		var ok bool
   883  		p, ok = step(p, &pc, &val, pc == f.entry)
   884  		if !ok {
   885  			return max
   886  		}
   887  		if val > max {
   888  			max = val
   889  		}
   890  	}
   891  }
   892  
   893  func pcdatastart(f funcInfo, table int32) int32 {
   894  	return *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
   895  }
   896  
   897  func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache) int32 {
   898  	if table < 0 || table >= f.npcdata {
   899  		return -1
   900  	}
   901  	r, _ := pcvalue(f, pcdatastart(f, table), targetpc, cache, true)
   902  	return r
   903  }
   904  
   905  func pcdatavalue1(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
   906  	if table < 0 || table >= f.npcdata {
   907  		return -1
   908  	}
   909  	r, _ := pcvalue(f, pcdatastart(f, table), targetpc, cache, strict)
   910  	return r
   911  }
   912  
   913  // Like pcdatavalue, but also return the start PC of this PCData value.
   914  // It doesn't take a cache.
   915  func pcdatavalue2(f funcInfo, table int32, targetpc uintptr) (int32, uintptr) {
   916  	if table < 0 || table >= f.npcdata {
   917  		return -1, 0
   918  	}
   919  	return pcvalue(f, pcdatastart(f, table), targetpc, nil, true)
   920  }
   921  
   922  func funcdata(f funcInfo, i uint8) unsafe.Pointer {
   923  	if i < 0 || i >= f.nfuncdata {
   924  		return nil
   925  	}
   926  	p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
   927  	if sys.PtrSize == 8 && uintptr(p)&4 != 0 {
   928  		if uintptr(unsafe.Pointer(f._func))&4 != 0 {
   929  			println("runtime: misaligned func", f._func)
   930  		}
   931  		p = add(p, 4)
   932  	}
   933  	return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize))
   934  }
   935  
   936  // step advances to the next pc, value pair in the encoded table.
   937  func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
   938  	// For both uvdelta and pcdelta, the common case (~70%)
   939  	// is that they are a single byte. If so, avoid calling readvarint.
   940  	uvdelta := uint32(p[0])
   941  	if uvdelta == 0 && !first {
   942  		return nil, false
   943  	}
   944  	n := uint32(1)
   945  	if uvdelta&0x80 != 0 {
   946  		n, uvdelta = readvarint(p)
   947  	}
   948  	*val += int32(-(uvdelta & 1) ^ (uvdelta >> 1))
   949  	p = p[n:]
   950  
   951  	pcdelta := uint32(p[0])
   952  	n = 1
   953  	if pcdelta&0x80 != 0 {
   954  		n, pcdelta = readvarint(p)
   955  	}
   956  	p = p[n:]
   957  	*pc += uintptr(pcdelta * sys.PCQuantum)
   958  	return p, true
   959  }
   960  
   961  // readvarint reads a varint from p.
   962  func readvarint(p []byte) (read uint32, val uint32) {
   963  	var v, shift, n uint32
   964  	for {
   965  		b := p[n]
   966  		n++
   967  		v |= uint32(b&0x7F) << (shift & 31)
   968  		if b&0x80 == 0 {
   969  			break
   970  		}
   971  		shift += 7
   972  	}
   973  	return n, v
   974  }
   975  
   976  type stackmap struct {
   977  	n        int32   // number of bitmaps
   978  	nbit     int32   // number of bits in each bitmap
   979  	bytedata [1]byte // bitmaps, each starting on a byte boundary
   980  }
   981  
   982  //go:nowritebarrier
   983  func stackmapdata(stkmap *stackmap, n int32) bitvector {
   984  	// Check this invariant only when stackDebug is on at all.
   985  	// The invariant is already checked by many of stackmapdata's callers,
   986  	// and disabling it by default allows stackmapdata to be inlined.
   987  	if stackDebug > 0 && (n < 0 || n >= stkmap.n) {
   988  		throw("stackmapdata: index out of range")
   989  	}
   990  	return bitvector{stkmap.nbit, addb(&stkmap.bytedata[0], uintptr(n*((stkmap.nbit+7)>>3)))}
   991  }
   992  
   993  // inlinedCall is the encoding of entries in the FUNCDATA_InlTree table.
   994  type inlinedCall struct {
   995  	parent   int16  // index of parent in the inltree, or < 0
   996  	funcID   funcID // type of the called function
   997  	_        byte
   998  	file     int32 // fileno index into filetab
   999  	line     int32 // line number of the call site
  1000  	func_    int32 // offset into pclntab for name of called function
  1001  	parentPc int32 // position of an instruction whose source position is the call site (offset from entry)
  1002  }
  1003  

View as plain text