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