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