github.com/4ad/go@v0.0.0-20161219182952-69a12818b605/src/runtime/symtab.go (about)

     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/sys"
     9  	"unsafe"
    10  )
    11  
    12  // Frames may be used to get function/file/line information for a
    13  // slice of PC values returned by Callers.
    14  type Frames struct {
    15  	callers []uintptr
    16  
    17  	// If previous caller in iteration was a panic, then
    18  	// ci.callers[0] is the address of the faulting instruction
    19  	// instead of the return address of the call.
    20  	wasPanic bool
    21  
    22  	// Frames to return for subsequent calls to the Next method.
    23  	// Used for non-Go frames.
    24  	frames *[]Frame
    25  }
    26  
    27  // Frame is the information returned by Frames for each call frame.
    28  type Frame struct {
    29  	// Program counter for this frame; multiple frames may have
    30  	// the same PC value.
    31  	PC uintptr
    32  
    33  	// Func for this frame; may be nil for non-Go code or fully
    34  	// inlined functions.
    35  	Func *Func
    36  
    37  	// Function name, file name, and line number for this call frame.
    38  	// May be the empty string or zero if not known.
    39  	// If Func is not nil then Function == Func.Name().
    40  	Function string
    41  	File     string
    42  	Line     int
    43  
    44  	// Entry point for the function; may be zero if not known.
    45  	// If Func is not nil then Entry == Func.Entry().
    46  	Entry uintptr
    47  }
    48  
    49  // CallersFrames takes a slice of PC values returned by Callers and
    50  // prepares to return function/file/line information.
    51  // Do not change the slice until you are done with the Frames.
    52  func CallersFrames(callers []uintptr) *Frames {
    53  	return &Frames{callers: callers}
    54  }
    55  
    56  // Next returns frame information for the next caller.
    57  // If more is false, there are no more callers (the Frame value is valid).
    58  func (ci *Frames) Next() (frame Frame, more bool) {
    59  	if ci.frames != nil {
    60  		// We have saved up frames to return.
    61  		f := (*ci.frames)[0]
    62  		if len(*ci.frames) == 1 {
    63  			ci.frames = nil
    64  		} else {
    65  			*ci.frames = (*ci.frames)[1:]
    66  		}
    67  		return f, ci.frames != nil || len(ci.callers) > 0
    68  	}
    69  
    70  	if len(ci.callers) == 0 {
    71  		ci.wasPanic = false
    72  		return Frame{}, false
    73  	}
    74  	pc := ci.callers[0]
    75  	ci.callers = ci.callers[1:]
    76  	more = len(ci.callers) > 0
    77  	f := FuncForPC(pc)
    78  	if f == nil {
    79  		ci.wasPanic = false
    80  		if cgoSymbolizer != nil {
    81  			return ci.cgoNext(pc, more)
    82  		}
    83  		return Frame{}, more
    84  	}
    85  
    86  	entry := f.Entry()
    87  	xpc := pc
    88  	// SPARC64's PC holds the address of the *current* instruction.
    89  	if xpc > entry && !ci.wasPanic && sys.GoarchSparc64 == 0 {
    90  		xpc--
    91  	}
    92  	file, line := f.FileLine(xpc)
    93  
    94  	function := f.Name()
    95  	ci.wasPanic = entry == sigpanicPC
    96  
    97  	frame = Frame{
    98  		PC:       xpc,
    99  		Func:     f,
   100  		Function: function,
   101  		File:     file,
   102  		Line:     line,
   103  		Entry:    entry,
   104  	}
   105  
   106  	return frame, more
   107  }
   108  
   109  // cgoNext returns frame information for pc, known to be a non-Go function,
   110  // using the cgoSymbolizer hook.
   111  func (ci *Frames) cgoNext(pc uintptr, more bool) (Frame, bool) {
   112  	arg := cgoSymbolizerArg{pc: pc}
   113  	callCgoSymbolizer(&arg)
   114  
   115  	if arg.file == nil && arg.funcName == nil {
   116  		// No useful information from symbolizer.
   117  		return Frame{}, more
   118  	}
   119  
   120  	var frames []Frame
   121  	for {
   122  		frames = append(frames, Frame{
   123  			PC:       pc,
   124  			Func:     nil,
   125  			Function: gostring(arg.funcName),
   126  			File:     gostring(arg.file),
   127  			Line:     int(arg.lineno),
   128  			Entry:    arg.entry,
   129  		})
   130  		if arg.more == 0 {
   131  			break
   132  		}
   133  		callCgoSymbolizer(&arg)
   134  	}
   135  
   136  	// No more frames for this PC. Tell the symbolizer we are done.
   137  	// We don't try to maintain a single cgoSymbolizerArg for the
   138  	// whole use of Frames, because there would be no good way to tell
   139  	// the symbolizer when we are done.
   140  	arg.pc = 0
   141  	callCgoSymbolizer(&arg)
   142  
   143  	if len(frames) == 1 {
   144  		// Return a single frame.
   145  		return frames[0], more
   146  	}
   147  
   148  	// Return the first frame we saw and store the rest to be
   149  	// returned by later calls to Next.
   150  	rf := frames[0]
   151  	frames = frames[1:]
   152  	ci.frames = new([]Frame)
   153  	*ci.frames = frames
   154  	return rf, true
   155  }
   156  
   157  // NOTE: Func does not expose the actual unexported fields, because we return *Func
   158  // values to users, and we want to keep them from being able to overwrite the data
   159  // with (say) *f = Func{}.
   160  // All code operating on a *Func must call raw to get the *_func instead.
   161  
   162  // A Func represents a Go function in the running binary.
   163  type Func struct {
   164  	opaque struct{} // unexported field to disallow conversions
   165  }
   166  
   167  func (f *Func) raw() *_func {
   168  	return (*_func)(unsafe.Pointer(f))
   169  }
   170  
   171  // funcdata.h
   172  const (
   173  	_PCDATA_StackMapIndex       = 0
   174  	_FUNCDATA_ArgsPointerMaps   = 0
   175  	_FUNCDATA_LocalsPointerMaps = 1
   176  	_ArgsSizeUnknown            = -0x80000000
   177  )
   178  
   179  // moduledata records information about the layout of the executable
   180  // image. It is written by the linker. Any changes here must be
   181  // matched changes to the code in cmd/internal/ld/symtab.go:symtab.
   182  // moduledata is stored in read-only memory; none of the pointers here
   183  // are visible to the garbage collector.
   184  type moduledata struct {
   185  	pclntable    []byte
   186  	ftab         []functab
   187  	filetab      []uint32
   188  	findfunctab  uintptr
   189  	minpc, maxpc uintptr
   190  
   191  	text, etext           uintptr
   192  	noptrdata, enoptrdata uintptr
   193  	data, edata           uintptr
   194  	bss, ebss             uintptr
   195  	noptrbss, enoptrbss   uintptr
   196  	end, gcdata, gcbss    uintptr
   197  	types, etypes         uintptr
   198  
   199  	typelinks []int32 // offsets from types
   200  	itablinks []*itab
   201  
   202  	modulename   string
   203  	modulehashes []modulehash
   204  
   205  	gcdatamask, gcbssmask bitvector
   206  
   207  	typemap map[typeOff]*_type // offset to *_rtype in previous module
   208  
   209  	next *moduledata
   210  }
   211  
   212  // For each shared library a module links against, the linker creates an entry in the
   213  // moduledata.modulehashes slice containing the name of the module, the abi hash seen
   214  // at link time and a pointer to the runtime abi hash. These are checked in
   215  // moduledataverify1 below.
   216  type modulehash struct {
   217  	modulename   string
   218  	linktimehash string
   219  	runtimehash  *string
   220  }
   221  
   222  var firstmoduledata moduledata  // linker symbol
   223  var lastmoduledatap *moduledata // linker symbol
   224  
   225  type functab struct {
   226  	entry   uintptr
   227  	funcoff uintptr
   228  }
   229  
   230  const minfunc = 16                 // minimum function size
   231  const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table
   232  
   233  // findfunctab is an array of these structures.
   234  // Each bucket represents 4096 bytes of the text segment.
   235  // Each subbucket represents 256 bytes of the text segment.
   236  // To find a function given a pc, locate the bucket and subbucket for
   237  // that pc. Add together the idx and subbucket value to obtain a
   238  // function index. Then scan the functab array starting at that
   239  // index to find the target function.
   240  // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead.
   241  type findfuncbucket struct {
   242  	idx        uint32
   243  	subbuckets [16]byte
   244  }
   245  
   246  func moduledataverify() {
   247  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   248  		moduledataverify1(datap)
   249  	}
   250  }
   251  
   252  const debugPcln = false
   253  
   254  func moduledataverify1(datap *moduledata) {
   255  	// See golang.org/s/go12symtab for header: 0xfffffffb,
   256  	// two zero bytes, a byte giving the PC quantum,
   257  	// and a byte giving the pointer width in bytes.
   258  	pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable))
   259  	pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable))
   260  	if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize {
   261  		println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7]))
   262  		throw("invalid function symbol table\n")
   263  	}
   264  
   265  	// ftab is lookup table for function by program counter.
   266  	nftab := len(datap.ftab) - 1
   267  	var pcCache pcvalueCache
   268  	for i := 0; i < nftab; i++ {
   269  		// NOTE: ftab[nftab].entry is legal; it is the address beyond the final function.
   270  		if datap.ftab[i].entry > datap.ftab[i+1].entry {
   271  			f1 := (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff]))
   272  			f2 := (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff]))
   273  			f2name := "end"
   274  			if i+1 < nftab {
   275  				f2name = funcname(f2)
   276  			}
   277  			println("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name)
   278  			for j := 0; j <= i; j++ {
   279  				print("\t", hex(datap.ftab[j].entry), " ", funcname((*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff]))), "\n")
   280  			}
   281  			throw("invalid runtime symbol table")
   282  		}
   283  
   284  		if debugPcln || nftab-i < 5 {
   285  			// Check a PC near but not at the very end.
   286  			// The very end might be just padding that is not covered by the tables.
   287  			// No architecture rounds function entries to more than 16 bytes,
   288  			// but if one came along we'd need to subtract more here.
   289  			// But don't use the next PC if it corresponds to a foreign object chunk
   290  			// (no pcln table, f2.pcln == 0). That chunk might have an alignment
   291  			// more than 16 bytes.
   292  			f := (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff]))
   293  			end := f.entry
   294  			if i+1 < nftab {
   295  				f2 := (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff]))
   296  				if f2.pcln != 0 {
   297  					end = f2.entry - 16
   298  					if end < f.entry {
   299  						end = f.entry
   300  					}
   301  				}
   302  			}
   303  			pcvalue(f, f.pcfile, end, &pcCache, true)
   304  			pcvalue(f, f.pcln, end, &pcCache, true)
   305  			pcvalue(f, f.pcsp, end, &pcCache, true)
   306  		}
   307  	}
   308  
   309  	if datap.minpc != datap.ftab[0].entry ||
   310  		datap.maxpc != datap.ftab[nftab].entry {
   311  		throw("minpc or maxpc invalid")
   312  	}
   313  
   314  	for _, modulehash := range datap.modulehashes {
   315  		if modulehash.linktimehash != *modulehash.runtimehash {
   316  			println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename)
   317  			throw("abi mismatch")
   318  		}
   319  	}
   320  }
   321  
   322  // FuncForPC returns a *Func describing the function that contains the
   323  // given program counter address, or else nil.
   324  func FuncForPC(pc uintptr) *Func {
   325  	return (*Func)(unsafe.Pointer(findfunc(pc)))
   326  }
   327  
   328  // Name returns the name of the function.
   329  func (f *Func) Name() string {
   330  	return funcname(f.raw())
   331  }
   332  
   333  // Entry returns the entry address of the function.
   334  func (f *Func) Entry() uintptr {
   335  	return f.raw().entry
   336  }
   337  
   338  // FileLine returns the file name and line number of the
   339  // source code corresponding to the program counter pc.
   340  // The result will not be accurate if pc is not a program
   341  // counter within f.
   342  func (f *Func) FileLine(pc uintptr) (file string, line int) {
   343  	// Pass strict=false here, because anyone can call this function,
   344  	// and they might just be wrong about targetpc belonging to f.
   345  	file, line32 := funcline1(f.raw(), pc, false)
   346  	return file, int(line32)
   347  }
   348  
   349  func findmoduledatap(pc uintptr) *moduledata {
   350  	for datap := &firstmoduledata; datap != nil; datap = datap.next {
   351  		if datap.minpc <= pc && pc < datap.maxpc {
   352  			return datap
   353  		}
   354  	}
   355  	return nil
   356  }
   357  
   358  func funcNameForPc(pc uintptr) string {
   359  	f := findfunc(pc)
   360  	if f == nil {
   361  		return "nil"
   362  	}
   363  	s := funcname(f)
   364  	if pc != f.entry {
   365  		s += "+" + itox(uint64(pc-f.entry))
   366  	}
   367  	return s
   368  }
   369  
   370  func itox(v uint64) string {
   371  	const dig = "0123456789abcdef"
   372  	buf := rawbyteslice(100)
   373  	i := len(buf)
   374  	for i--; i > 0; i-- {
   375  		buf[i] = dig[v%16]
   376  		if v < 16 {
   377  			break
   378  		}
   379  		v /= 16
   380  	}
   381  	i--
   382  	buf[i] = 'x'
   383  	i--
   384  	buf[i] = '0'
   385  	return slicebytetostringtmp(buf[i:])
   386  }
   387  
   388  func findfunc(pc uintptr) *_func {
   389  	datap := findmoduledatap(pc)
   390  	if datap == nil {
   391  		return nil
   392  	}
   393  	const nsub = uintptr(len(findfuncbucket{}.subbuckets))
   394  
   395  	x := pc - datap.minpc
   396  	b := x / pcbucketsize
   397  	i := x % pcbucketsize / (pcbucketsize / nsub)
   398  
   399  	ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{})))
   400  	idx := ffb.idx + uint32(ffb.subbuckets[i])
   401  	if pc < datap.ftab[idx].entry {
   402  		throw("findfunc: bad findfunctab entry")
   403  	}
   404  
   405  	// linear search to find func with pc >= entry.
   406  	for datap.ftab[idx+1].entry <= pc {
   407  		idx++
   408  	}
   409  	return (*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff]))
   410  }
   411  
   412  type pcvalueCache struct {
   413  	entries [16]pcvalueCacheEnt
   414  }
   415  
   416  type pcvalueCacheEnt struct {
   417  	// targetpc and off together are the key of this cache entry.
   418  	targetpc uintptr
   419  	off      int32
   420  	// val is the value of this cached pcvalue entry.
   421  	val int32
   422  }
   423  
   424  func pcvalue(f *_func, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 {
   425  	if off == 0 {
   426  		return -1
   427  	}
   428  
   429  	// Check the cache. This speeds up walks of deep stacks, which
   430  	// tend to have the same recursive functions over and over.
   431  	//
   432  	// This cache is small enough that full associativity is
   433  	// cheaper than doing the hashing for a less associative
   434  	// cache.
   435  	if cache != nil {
   436  		for _, ent := range cache.entries {
   437  			// We check off first because we're more
   438  			// likely to have multiple entries with
   439  			// different offsets for the same targetpc
   440  			// than the other way around, so we'll usually
   441  			// fail in the first clause.
   442  			if ent.off == off && ent.targetpc == targetpc {
   443  				return ent.val
   444  			}
   445  		}
   446  	}
   447  
   448  	datap := findmoduledatap(f.entry) // inefficient
   449  	if datap == nil {
   450  		if strict && panicking == 0 {
   451  			print("runtime: no module data for ", hex(f.entry), "\n")
   452  			throw("no module data")
   453  		}
   454  		return -1
   455  	}
   456  	p := datap.pclntable[off:]
   457  	pc := f.entry
   458  	val := int32(-1)
   459  	for {
   460  		var ok bool
   461  		p, ok = step(p, &pc, &val, pc == f.entry)
   462  		if !ok {
   463  			break
   464  		}
   465  		if targetpc < pc {
   466  			// Replace a random entry in the cache. Random
   467  			// replacement prevents a performance cliff if
   468  			// a recursive stack's cycle is slightly
   469  			// larger than the cache.
   470  			if cache != nil {
   471  				ci := fastrand1() % uint32(len(cache.entries))
   472  				cache.entries[ci] = pcvalueCacheEnt{
   473  					targetpc: targetpc,
   474  					off:      off,
   475  					val:      val,
   476  				}
   477  			}
   478  
   479  			return val
   480  		}
   481  	}
   482  
   483  	// If there was a table, it should have covered all program counters.
   484  	// If not, something is wrong.
   485  	if panicking != 0 || !strict {
   486  		return -1
   487  	}
   488  
   489  	print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n")
   490  
   491  	p = datap.pclntable[off:]
   492  	pc = f.entry
   493  	val = -1
   494  	for {
   495  		var ok bool
   496  		p, ok = step(p, &pc, &val, pc == f.entry)
   497  		if !ok {
   498  			break
   499  		}
   500  		print("\tvalue=", val, " until pc=", hex(pc), "\n")
   501  	}
   502  
   503  	throw("invalid runtime symbol table")
   504  	return -1
   505  }
   506  
   507  func cfuncname(f *_func) *byte {
   508  	if f == nil || f.nameoff == 0 {
   509  		return nil
   510  	}
   511  	datap := findmoduledatap(f.entry) // inefficient
   512  	if datap == nil {
   513  		return nil
   514  	}
   515  	return &datap.pclntable[f.nameoff]
   516  }
   517  
   518  func funcname(f *_func) string {
   519  	return gostringnocopy(cfuncname(f))
   520  }
   521  
   522  func funcline1(f *_func, targetpc uintptr, strict bool) (file string, line int32) {
   523  	datap := findmoduledatap(f.entry) // inefficient
   524  	if datap == nil {
   525  		return "?", 0
   526  	}
   527  	fileno := int(pcvalue(f, f.pcfile, targetpc, nil, strict))
   528  	line = pcvalue(f, f.pcln, targetpc, nil, strict)
   529  	if fileno == -1 || line == -1 || fileno >= len(datap.filetab) {
   530  		// print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n")
   531  		return "?", 0
   532  	}
   533  	file = gostringnocopy(&datap.pclntable[datap.filetab[fileno]])
   534  	return
   535  }
   536  
   537  func funcline(f *_func, targetpc uintptr) (file string, line int32) {
   538  	return funcline1(f, targetpc, true)
   539  }
   540  
   541  func funcspdelta(f *_func, targetpc uintptr, cache *pcvalueCache) int32 {
   542  	x := pcvalue(f, f.pcsp, targetpc, cache, true)
   543  	if x&(sys.PtrSize-1) != 0 {
   544  		print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n")
   545  	}
   546  	return x
   547  }
   548  
   549  func pcdatavalue(f *_func, table int32, targetpc uintptr, cache *pcvalueCache) int32 {
   550  	if table < 0 || table >= f.npcdata {
   551  		return -1
   552  	}
   553  	off := *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4))
   554  	return pcvalue(f, off, targetpc, cache, true)
   555  }
   556  
   557  func funcdata(f *_func, i int32) unsafe.Pointer {
   558  	if i < 0 || i >= f.nfuncdata {
   559  		return nil
   560  	}
   561  	p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4)
   562  	if sys.PtrSize == 8 && uintptr(p)&4 != 0 {
   563  		if uintptr(unsafe.Pointer(f))&4 != 0 {
   564  			println("runtime: misaligned func", f)
   565  		}
   566  		p = add(p, 4)
   567  	}
   568  	return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize))
   569  }
   570  
   571  // step advances to the next pc, value pair in the encoded table.
   572  func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) {
   573  	p, uvdelta := readvarint(p)
   574  	if uvdelta == 0 && !first {
   575  		return nil, false
   576  	}
   577  	if uvdelta&1 != 0 {
   578  		uvdelta = ^(uvdelta >> 1)
   579  	} else {
   580  		uvdelta >>= 1
   581  	}
   582  	vdelta := int32(uvdelta)
   583  	p, pcdelta := readvarint(p)
   584  	*pc += uintptr(pcdelta * sys.PCQuantum)
   585  	*val += vdelta
   586  	return p, true
   587  }
   588  
   589  // readvarint reads a varint from p.
   590  func readvarint(p []byte) (newp []byte, val uint32) {
   591  	var v, shift uint32
   592  	for {
   593  		b := p[0]
   594  		p = p[1:]
   595  		v |= (uint32(b) & 0x7F) << shift
   596  		if b&0x80 == 0 {
   597  			break
   598  		}
   599  		shift += 7
   600  	}
   601  	return p, v
   602  }
   603  
   604  type stackmap struct {
   605  	n        int32   // number of bitmaps
   606  	nbit     int32   // number of bits in each bitmap
   607  	bytedata [1]byte // bitmaps, each starting on a 32-bit boundary
   608  }
   609  
   610  //go:nowritebarrier
   611  func stackmapdata(stkmap *stackmap, n int32) bitvector {
   612  	if n < 0 || n >= stkmap.n {
   613  		throw("stackmapdata: index out of range")
   614  	}
   615  	return bitvector{stkmap.nbit, (*byte)(add(unsafe.Pointer(&stkmap.bytedata), uintptr(n*((stkmap.nbit+31)/32*4))))}
   616  }