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