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