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

View as plain text