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

View as plain text