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