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