...
Run Format

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

View as plain text