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 5package runtime 6 7import ( 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. 15type 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. 25type 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. 65func 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). 73func (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. 154func 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. 198type Func struct { 199 opaque struct{} // unexported field to disallow conversions 200} 201 202func (f *Func) raw() *_func { 203 return (*_func)(unsafe.Pointer(f)) 204} 205 206func (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. 214const ( 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. 234type funcID uint8 235 236const ( 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. 267type 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. 317type 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. 330var pinnedTypemaps []map[typeOff]*_type 331 332var firstmoduledata moduledata // linker symbol 333var lastmoduledatap *moduledata // linker symbol 334var 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 345func 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. 371func 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 404type functab struct { 405 entry uintptr 406 funcoff uintptr 407} 408 409// Mapping information for secondary text sections 410 411type textsect struct { 412 vaddr uintptr // prelinked section vaddr 413 length uintptr // section length 414 baseaddr uintptr // relocated section address 415} 416 417const minfunc = 16 // minimum function size 418const 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. 428type findfuncbucket struct { 429 idx uint32 430 subbuckets [16]byte 431} 432 433func moduledataverify() { 434 for datap := &firstmoduledata; datap != nil; datap = datap.next { 435 moduledataverify1(datap) 436 } 437} 438 439const debugPcln = false 440 441func 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. 493func 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. 520func (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. 533func (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. 546func (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 558func 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 567type funcInfo struct { 568 *_func 569 datap *moduledata 570} 571 572func (f funcInfo) valid() bool { 573 return f._func != nil 574} 575 576func (f funcInfo) _Func() *Func { 577 return (*Func)(unsafe.Pointer(f._func)) 578} 579 580func 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 628type pcvalueCache struct { 629 entries [2][8]pcvalueCacheEnt 630} 631 632type 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. 644func pcvalueCacheKey(targetpc uintptr) uintptr { 645 return (targetpc / sys.PtrSize) % uintptr(len(pcvalueCache{}.entries)) 646} 647 648func 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 738func cfuncname(f funcInfo) *byte { 739 if !f.valid() || f.nameoff == 0 { 740 return nil 741 } 742 return &f.datap.pclntable[f.nameoff] 743} 744 745func funcname(f funcInfo) string { 746 return gostringnocopy(cfuncname(f)) 747} 748 749func cfuncnameFromNameoff(f funcInfo, nameoff int32) *byte { 750 if !f.valid() { 751 return nil 752 } 753 return &f.datap.pclntable[nameoff] 754} 755 756func funcnameFromNameoff(f funcInfo, nameoff int32) string { 757 return gostringnocopy(cfuncnameFromNameoff(f, nameoff)) 758} 759 760func 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 768func 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 783func funcline(f funcInfo, targetpc uintptr) (file string, line int32) { 784 return funcline1(f, targetpc, true) 785} 786 787func 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. 796func 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 814func pcdatastart(f funcInfo, table int32) int32 { 815 return *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4)) 816} 817 818func 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 825func 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 832func 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. 847func 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. 872func 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 886type 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 893func 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. 904type 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