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