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

View as plain text