github.com/stingnevermore/go@v0.0.0-20180120041312-3810f5bfed72/src/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. 17 callers []uintptr 18 19 // stackExpander expands callers into a sequence of Frames, 20 // tracking the necessary state across PCs. 21 stackExpander stackExpander 22 23 // elideWrapper indicates that, if the next frame is an 24 // autogenerated wrapper function, it should be elided from 25 // the stack. 26 elideWrapper bool 27 } 28 29 // Frame is the information returned by Frames for each call frame. 30 type Frame struct { 31 // PC is the program counter for the location in this frame. 32 // For a frame that calls another frame, this will be the 33 // program counter of a call instruction. Because of inlining, 34 // multiple frames may have the same PC value, but different 35 // symbolic information. 36 PC uintptr 37 38 // Func is the Func value of this call frame. This may be nil 39 // for non-Go code or fully inlined functions. 40 Func *Func 41 42 // Function is the package path-qualified function name of 43 // this call frame. If non-empty, this string uniquely 44 // identifies a single function in the program. 45 // This may be the empty string if not known. 46 // If Func is not nil then Function == Func.Name(). 47 Function string 48 49 // File and Line are the file name and line number of the 50 // location in this frame. For non-leaf frames, this will be 51 // the location of a call. These may be the empty string and 52 // zero, respectively, if not known. 53 File string 54 Line int 55 56 // Entry point program counter for the function; may be zero 57 // if not known. If Func is not nil then Entry == 58 // Func.Entry(). 59 Entry uintptr 60 } 61 62 // stackExpander expands a call stack of PCs into a sequence of 63 // Frames. It tracks state across PCs necessary to perform this 64 // expansion. 65 // 66 // This is the core of the Frames implementation, but is a separate 67 // internal API to make it possible to use within the runtime without 68 // heap-allocating the PC slice. The only difference with the public 69 // Frames API is that the caller is responsible for threading the PC 70 // slice between expansion steps in this API. If escape analysis were 71 // smarter, we may not need this (though it may have to be a lot 72 // smarter). 73 type stackExpander struct { 74 // pcExpander expands the current PC into a sequence of Frames. 75 pcExpander pcExpander 76 77 // If previous caller in iteration was a panic, then the next 78 // PC in the call stack is the address of the faulting 79 // instruction instead of the return address of the call. 80 wasPanic bool 81 82 // skip > 0 indicates that skip frames in the expansion of the 83 // first PC should be skipped over and callers[1] should also 84 // be skipped. 85 skip int 86 } 87 88 // CallersFrames takes a slice of PC values returned by Callers and 89 // prepares to return function/file/line information. 90 // Do not change the slice until you are done with the Frames. 91 func CallersFrames(callers []uintptr) *Frames { 92 ci := &Frames{} 93 ci.callers = ci.stackExpander.init(callers) 94 return ci 95 } 96 97 func (se *stackExpander) init(callers []uintptr) []uintptr { 98 if len(callers) >= 1 { 99 pc := callers[0] 100 s := pc - skipPC 101 if s >= 0 && s < sizeofSkipFunction { 102 // Ignore skip frame callers[0] since this means the caller trimmed the PC slice. 103 return callers[1:] 104 } 105 } 106 if len(callers) >= 2 { 107 pc := callers[1] 108 s := pc - skipPC 109 if s > 0 && s < sizeofSkipFunction { 110 // Skip the first s inlined frames when we expand the first PC. 111 se.skip = int(s) 112 } 113 } 114 return callers 115 } 116 117 // Next returns frame information for the next caller. 118 // If more is false, there are no more callers (the Frame value is valid). 119 func (ci *Frames) Next() (frame Frame, more bool) { 120 ci.callers, frame, more = ci.stackExpander.next(ci.callers, ci.elideWrapper) 121 ci.elideWrapper = elideWrapperCalling(frame.Function) 122 return 123 } 124 125 func (se *stackExpander) next(callers []uintptr, elideWrapper bool) (ncallers []uintptr, frame Frame, more bool) { 126 ncallers = callers 127 again: 128 if !se.pcExpander.more { 129 // Expand the next PC. 130 if len(ncallers) == 0 { 131 se.wasPanic = false 132 return ncallers, Frame{}, false 133 } 134 se.pcExpander.init(ncallers[0], se.wasPanic) 135 ncallers = ncallers[1:] 136 se.wasPanic = se.pcExpander.funcInfo.valid() && se.pcExpander.funcInfo.entry == sigpanicPC 137 if se.skip > 0 { 138 for ; se.skip > 0; se.skip-- { 139 se.pcExpander.next() 140 } 141 se.skip = 0 142 // Drop skipPleaseUseCallersFrames. 143 ncallers = ncallers[1:] 144 } 145 if !se.pcExpander.more { 146 // No symbolic information for this PC. 147 // However, we return at least one frame for 148 // every PC, so return an invalid frame. 149 return ncallers, Frame{}, len(ncallers) > 0 150 } 151 } 152 153 frame = se.pcExpander.next() 154 if elideWrapper && frame.File == "<autogenerated>" { 155 // Ignore autogenerated functions such as pointer 156 // method forwarding functions. These are an 157 // implementation detail that doesn't reflect the 158 // source code. 159 goto again 160 } 161 return ncallers, frame, se.pcExpander.more || len(ncallers) > 0 162 } 163 164 // A pcExpander expands a single PC into a sequence of Frames. 165 type pcExpander struct { 166 // more indicates that the next call to next will return a 167 // valid frame. 168 more bool 169 170 // pc is the pc being expanded. 171 pc uintptr 172 173 // frames is a pre-expanded set of Frames to return from the 174 // iterator. If this is set, then this is everything that will 175 // be returned from the iterator. 176 frames []Frame 177 178 // funcInfo is the funcInfo of the function containing pc. 179 funcInfo funcInfo 180 181 // inlTree is the inlining tree of the function containing pc. 182 inlTree *[1 << 20]inlinedCall 183 184 // file and line are the file name and line number of the next 185 // frame. 186 file string 187 line int32 188 189 // inlIndex is the inlining index of the next frame, or -1 if 190 // the next frame is an outermost frame. 191 inlIndex int32 192 } 193 194 // init initializes this pcExpander to expand pc. It sets ex.more if 195 // pc expands to any Frames. 196 // 197 // A pcExpander can be reused by calling init again. 198 // 199 // If pc was a "call" to sigpanic, panicCall should be true. In this 200 // case, pc is treated as the address of a faulting instruction 201 // instead of the return address of a call. 202 func (ex *pcExpander) init(pc uintptr, panicCall bool) { 203 ex.more = false 204 205 ex.funcInfo = findfunc(pc) 206 if !ex.funcInfo.valid() { 207 if cgoSymbolizer != nil { 208 // Pre-expand cgo frames. We could do this 209 // incrementally, too, but there's no way to 210 // avoid allocation in this case anyway. 211 ex.frames = expandCgoFrames(pc) 212 ex.more = len(ex.frames) > 0 213 } 214 return 215 } 216 217 ex.more = true 218 entry := ex.funcInfo.entry 219 ex.pc = pc 220 if ex.pc > entry && !panicCall { 221 ex.pc-- 222 } 223 224 // file and line are the innermost position at pc. 225 ex.file, ex.line = funcline1(ex.funcInfo, ex.pc, false) 226 227 // Get inlining tree at pc 228 inldata := funcdata(ex.funcInfo, _FUNCDATA_InlTree) 229 if inldata != nil { 230 ex.inlTree = (*[1 << 20]inlinedCall)(inldata) 231 ex.inlIndex = pcdatavalue(ex.funcInfo, _PCDATA_InlTreeIndex, ex.pc, nil) 232 } else { 233 ex.inlTree = nil 234 ex.inlIndex = -1 235 } 236 } 237 238 // next returns the next Frame in the expansion of pc and sets ex.more 239 // if there are more Frames to follow. 240 func (ex *pcExpander) next() Frame { 241 if !ex.more { 242 return Frame{} 243 } 244 245 if len(ex.frames) > 0 { 246 // Return pre-expended frame. 247 frame := ex.frames[0] 248 ex.frames = ex.frames[1:] 249 ex.more = len(ex.frames) > 0 250 return frame 251 } 252 253 if ex.inlIndex >= 0 { 254 // Return inner inlined frame. 255 call := ex.inlTree[ex.inlIndex] 256 frame := Frame{ 257 PC: ex.pc, 258 Func: nil, // nil for inlined functions 259 Function: funcnameFromNameoff(ex.funcInfo, call.func_), 260 File: ex.file, 261 Line: int(ex.line), 262 Entry: ex.funcInfo.entry, 263 } 264 ex.file = funcfile(ex.funcInfo, call.file) 265 ex.line = call.line 266 ex.inlIndex = call.parent 267 return frame 268 } 269 270 // No inlining or pre-expanded frames. 271 ex.more = false 272 return Frame{ 273 PC: ex.pc, 274 Func: ex.funcInfo._Func(), 275 Function: funcname(ex.funcInfo), 276 File: ex.file, 277 Line: int(ex.line), 278 Entry: ex.funcInfo.entry, 279 } 280 } 281 282 // expandCgoFrames expands frame information for pc, known to be 283 // a non-Go function, using the cgoSymbolizer hook. expandCgoFrames 284 // returns nil if pc could not be expanded. 285 func expandCgoFrames(pc uintptr) []Frame { 286 arg := cgoSymbolizerArg{pc: pc} 287 callCgoSymbolizer(&arg) 288 289 if arg.file == nil && arg.funcName == nil { 290 // No useful information from symbolizer. 291 return nil 292 } 293 294 var frames []Frame 295 for { 296 frames = append(frames, Frame{ 297 PC: pc, 298 Func: nil, 299 Function: gostring(arg.funcName), 300 File: gostring(arg.file), 301 Line: int(arg.lineno), 302 Entry: arg.entry, 303 }) 304 if arg.more == 0 { 305 break 306 } 307 callCgoSymbolizer(&arg) 308 } 309 310 // No more frames for this PC. Tell the symbolizer we are done. 311 // We don't try to maintain a single cgoSymbolizerArg for the 312 // whole use of Frames, because there would be no good way to tell 313 // the symbolizer when we are done. 314 arg.pc = 0 315 callCgoSymbolizer(&arg) 316 317 return frames 318 } 319 320 // NOTE: Func does not expose the actual unexported fields, because we return *Func 321 // values to users, and we want to keep them from being able to overwrite the data 322 // with (say) *f = Func{}. 323 // All code operating on a *Func must call raw() to get the *_func 324 // or funcInfo() to get the funcInfo instead. 325 326 // A Func represents a Go function in the running binary. 327 type Func struct { 328 opaque struct{} // unexported field to disallow conversions 329 } 330 331 func (f *Func) raw() *_func { 332 return (*_func)(unsafe.Pointer(f)) 333 } 334 335 func (f *Func) funcInfo() funcInfo { 336 fn := f.raw() 337 return funcInfo{fn, findmoduledatap(fn.entry)} 338 } 339 340 // PCDATA and FUNCDATA table indexes. 341 // 342 // See funcdata.h and ../cmd/internal/obj/funcdata.go. 343 const ( 344 _PCDATA_StackMapIndex = 0 345 _PCDATA_InlTreeIndex = 1 346 _FUNCDATA_ArgsPointerMaps = 0 347 _FUNCDATA_LocalsPointerMaps = 1 348 _FUNCDATA_InlTree = 2 349 _ArgsSizeUnknown = -0x80000000 350 ) 351 352 // moduledata records information about the layout of the executable 353 // image. It is written by the linker. Any changes here must be 354 // matched changes to the code in cmd/internal/ld/symtab.go:symtab. 355 // moduledata is stored in statically allocated non-pointer memory; 356 // none of the pointers here are visible to the garbage collector. 357 type moduledata struct { 358 pclntable []byte 359 ftab []functab 360 filetab []uint32 361 findfunctab uintptr 362 minpc, maxpc uintptr 363 364 text, etext uintptr 365 noptrdata, enoptrdata uintptr 366 data, edata uintptr 367 bss, ebss uintptr 368 noptrbss, enoptrbss uintptr 369 end, gcdata, gcbss uintptr 370 types, etypes uintptr 371 372 textsectmap []textsect 373 typelinks []int32 // offsets from types 374 itablinks []*itab 375 376 ptab []ptabEntry 377 378 pluginpath string 379 pkghashes []modulehash 380 381 modulename string 382 modulehashes []modulehash 383 384 hasmain uint8 // 1 if module contains the main function, 0 otherwise 385 386 gcdatamask, gcbssmask bitvector 387 388 typemap map[typeOff]*_type // offset to *_rtype in previous module 389 390 bad bool // module failed to load and should be ignored 391 392 next *moduledata 393 } 394 395 // A modulehash is used to compare the ABI of a new module or a 396 // package in a new module with the loaded program. 397 // 398 // For each shared library a module links against, the linker creates an entry in the 399 // moduledata.modulehashes slice containing the name of the module, the abi hash seen 400 // at link time and a pointer to the runtime abi hash. These are checked in 401 // moduledataverify1 below. 402 // 403 // For each loaded plugin, the pkghashes slice has a modulehash of the 404 // newly loaded package that can be used to check the plugin's version of 405 // a package against any previously loaded version of the package. 406 // This is done in plugin.lastmoduleinit. 407 type modulehash struct { 408 modulename string 409 linktimehash string 410 runtimehash *string 411 } 412 413 // pinnedTypemaps are the map[typeOff]*_type from the moduledata objects. 414 // 415 // These typemap objects are allocated at run time on the heap, but the 416 // only direct reference to them is in the moduledata, created by the 417 // linker and marked SNOPTRDATA so it is ignored by the GC. 418 // 419 // To make sure the map isn't collected, we keep a second reference here. 420 var pinnedTypemaps []map[typeOff]*_type 421 422 var firstmoduledata moduledata // linker symbol 423 var lastmoduledatap *moduledata // linker symbol 424 var modulesSlice *[]*moduledata // see activeModules 425 426 // activeModules returns a slice of active modules. 427 // 428 // A module is active once its gcdatamask and gcbssmask have been 429 // assembled and it is usable by the GC. 430 // 431 // This is nosplit/nowritebarrier because it is called by the 432 // cgo pointer checking code. 433 //go:nosplit 434 //go:nowritebarrier 435 func activeModules() []*moduledata { 436 p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice))) 437 if p == nil { 438 return nil 439 } 440 return *p 441 } 442 443 // modulesinit creates the active modules slice out of all loaded modules. 444 // 445 // When a module is first loaded by the dynamic linker, an .init_array 446 // function (written by cmd/link) is invoked to call addmoduledata, 447 // appending to the module to the linked list that starts with 448 // firstmoduledata. 449 // 450 // There are two times this can happen in the lifecycle of a Go 451 // program. First, if compiled with -linkshared, a number of modules 452 // built with -buildmode=shared can be loaded at program initialization. 453 // Second, a Go program can load a module while running that was built 454 // with -buildmode=plugin. 455 // 456 // After loading, this function is called which initializes the 457 // moduledata so it is usable by the GC and creates a new activeModules 458 // list. 459 // 460 // Only one goroutine may call modulesinit at a time. 461 func modulesinit() { 462 modules := new([]*moduledata) 463 for md := &firstmoduledata; md != nil; md = md.next { 464 if md.bad { 465 continue 466 } 467 *modules = append(*modules, md) 468 if md.gcdatamask == (bitvector{}) { 469 md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data) 470 md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss) 471 } 472 } 473 474 // Modules appear in the moduledata linked list in the order they are 475 // loaded by the dynamic loader, with one exception: the 476 // firstmoduledata itself the module that contains the runtime. This 477 // is not always the first module (when using -buildmode=shared, it 478 // is typically libstd.so, the second module). The order matters for 479 // typelinksinit, so we swap the first module with whatever module 480 // contains the main function. 481 // 482 // See Issue #18729. 483 for i, md := range *modules { 484 if md.hasmain != 0 { 485 (*modules)[0] = md 486 (*modules)[i] = &firstmoduledata 487 break 488 } 489 } 490 491 atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules)) 492 } 493 494 type functab struct { 495 entry uintptr 496 funcoff uintptr 497 } 498 499 // Mapping information for secondary text sections 500 501 type textsect struct { 502 vaddr uintptr // prelinked section vaddr 503 length uintptr // section length 504 baseaddr uintptr // relocated section address 505 } 506 507 const minfunc = 16 // minimum function size 508 const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table 509 510 // findfunctab is an array of these structures. 511 // Each bucket represents 4096 bytes of the text segment. 512 // Each subbucket represents 256 bytes of the text segment. 513 // To find a function given a pc, locate the bucket and subbucket for 514 // that pc. Add together the idx and subbucket value to obtain a 515 // function index. Then scan the functab array starting at that 516 // index to find the target function. 517 // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead. 518 type findfuncbucket struct { 519 idx uint32 520 subbuckets [16]byte 521 } 522 523 func moduledataverify() { 524 for datap := &firstmoduledata; datap != nil; datap = datap.next { 525 moduledataverify1(datap) 526 } 527 } 528 529 const debugPcln = false 530 531 func moduledataverify1(datap *moduledata) { 532 // See golang.org/s/go12symtab for header: 0xfffffffb, 533 // two zero bytes, a byte giving the PC quantum, 534 // and a byte giving the pointer width in bytes. 535 pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable)) 536 pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable)) 537 if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize { 538 println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7])) 539 throw("invalid function symbol table\n") 540 } 541 542 // ftab is lookup table for function by program counter. 543 nftab := len(datap.ftab) - 1 544 for i := 0; i < nftab; i++ { 545 // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function. 546 if datap.ftab[i].entry > datap.ftab[i+1].entry { 547 f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap} 548 f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap} 549 f2name := "end" 550 if i+1 < nftab { 551 f2name = funcname(f2) 552 } 553 println("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name) 554 for j := 0; j <= i; j++ { 555 print("\t", hex(datap.ftab[j].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}), "\n") 556 } 557 throw("invalid runtime symbol table") 558 } 559 } 560 561 if datap.minpc != datap.ftab[0].entry || 562 datap.maxpc != datap.ftab[nftab].entry { 563 throw("minpc or maxpc invalid") 564 } 565 566 for _, modulehash := range datap.modulehashes { 567 if modulehash.linktimehash != *modulehash.runtimehash { 568 println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename) 569 throw("abi mismatch") 570 } 571 } 572 } 573 574 // FuncForPC returns a *Func describing the function that contains the 575 // given program counter address, or else nil. 576 // 577 // If pc represents multiple functions because of inlining, it returns 578 // the *Func describing the outermost function. 579 func FuncForPC(pc uintptr) *Func { 580 return findfunc(pc)._Func() 581 } 582 583 // Name returns the name of the function. 584 func (f *Func) Name() string { 585 if f == nil { 586 return "" 587 } 588 return funcname(f.funcInfo()) 589 } 590 591 // Entry returns the entry address of the function. 592 func (f *Func) Entry() uintptr { 593 return f.raw().entry 594 } 595 596 // FileLine returns the file name and line number of the 597 // source code corresponding to the program counter pc. 598 // The result will not be accurate if pc is not a program 599 // counter within f. 600 func (f *Func) FileLine(pc uintptr) (file string, line int) { 601 // Pass strict=false here, because anyone can call this function, 602 // and they might just be wrong about targetpc belonging to f. 603 file, line32 := funcline1(f.funcInfo(), pc, false) 604 return file, int(line32) 605 } 606 607 func findmoduledatap(pc uintptr) *moduledata { 608 for datap := &firstmoduledata; datap != nil; datap = datap.next { 609 if datap.minpc <= pc && pc < datap.maxpc { 610 return datap 611 } 612 } 613 return nil 614 } 615 616 type funcInfo struct { 617 *_func 618 datap *moduledata 619 } 620 621 func (f funcInfo) valid() bool { 622 return f._func != nil 623 } 624 625 func (f funcInfo) _Func() *Func { 626 return (*Func)(unsafe.Pointer(f._func)) 627 } 628 629 func findfunc(pc uintptr) funcInfo { 630 datap := findmoduledatap(pc) 631 if datap == nil { 632 return funcInfo{} 633 } 634 const nsub = uintptr(len(findfuncbucket{}.subbuckets)) 635 636 x := pc - datap.minpc 637 b := x / pcbucketsize 638 i := x % pcbucketsize / (pcbucketsize / nsub) 639 640 ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{}))) 641 idx := ffb.idx + uint32(ffb.subbuckets[i]) 642 643 // If the idx is beyond the end of the ftab, set it to the end of the table and search backward. 644 // This situation can occur if multiple text sections are generated to handle large text sections 645 // and the linker has inserted jump tables between them. 646 647 if idx >= uint32(len(datap.ftab)) { 648 idx = uint32(len(datap.ftab) - 1) 649 } 650 if pc < datap.ftab[idx].entry { 651 652 // With multiple text sections, the idx might reference a function address that 653 // is higher than the pc being searched, so search backward until the matching address is found. 654 655 for datap.ftab[idx].entry > pc && idx > 0 { 656 idx-- 657 } 658 if idx == 0 { 659 throw("findfunc: bad findfunctab entry idx") 660 } 661 } else { 662 663 // linear search to find func with pc >= entry. 664 for datap.ftab[idx+1].entry <= pc { 665 idx++ 666 } 667 } 668 return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff])), datap} 669 } 670 671 type pcvalueCache struct { 672 entries [16]pcvalueCacheEnt 673 } 674 675 type pcvalueCacheEnt struct { 676 // targetpc and off together are the key of this cache entry. 677 targetpc uintptr 678 off int32 679 // val is the value of this cached pcvalue entry. 680 val int32 681 } 682 683 func pcvalue(f funcInfo, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 { 684 if off == 0 { 685 return -1 686 } 687 688 // Check the cache. This speeds up walks of deep stacks, which 689 // tend to have the same recursive functions over and over. 690 // 691 // This cache is small enough that full associativity is 692 // cheaper than doing the hashing for a less associative 693 // cache. 694 if cache != nil { 695 for i := range cache.entries { 696 // We check off first because we're more 697 // likely to have multiple entries with 698 // different offsets for the same targetpc 699 // than the other way around, so we'll usually 700 // fail in the first clause. 701 ent := &cache.entries[i] 702 if ent.off == off && ent.targetpc == targetpc { 703 return ent.val 704 } 705 } 706 } 707 708 if !f.valid() { 709 if strict && panicking == 0 { 710 print("runtime: no module data for ", hex(f.entry), "\n") 711 throw("no module data") 712 } 713 return -1 714 } 715 datap := f.datap 716 p := datap.pclntable[off:] 717 pc := f.entry 718 val := int32(-1) 719 for { 720 var ok bool 721 p, ok = step(p, &pc, &val, pc == f.entry) 722 if !ok { 723 break 724 } 725 if targetpc < pc { 726 // Replace a random entry in the cache. Random 727 // replacement prevents a performance cliff if 728 // a recursive stack's cycle is slightly 729 // larger than the cache. 730 if cache != nil { 731 ci := fastrandn(uint32(len(cache.entries))) 732 cache.entries[ci] = pcvalueCacheEnt{ 733 targetpc: targetpc, 734 off: off, 735 val: val, 736 } 737 } 738 739 return val 740 } 741 } 742 743 // If there was a table, it should have covered all program counters. 744 // If not, something is wrong. 745 if panicking != 0 || !strict { 746 return -1 747 } 748 749 print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n") 750 751 p = datap.pclntable[off:] 752 pc = f.entry 753 val = -1 754 for { 755 var ok bool 756 p, ok = step(p, &pc, &val, pc == f.entry) 757 if !ok { 758 break 759 } 760 print("\tvalue=", val, " until pc=", hex(pc), "\n") 761 } 762 763 throw("invalid runtime symbol table") 764 return -1 765 } 766 767 func cfuncname(f funcInfo) *byte { 768 if !f.valid() || f.nameoff == 0 { 769 return nil 770 } 771 return &f.datap.pclntable[f.nameoff] 772 } 773 774 func funcname(f funcInfo) string { 775 return gostringnocopy(cfuncname(f)) 776 } 777 778 func funcnameFromNameoff(f funcInfo, nameoff int32) string { 779 datap := f.datap 780 if !f.valid() { 781 return "" 782 } 783 cstr := &datap.pclntable[nameoff] 784 return gostringnocopy(cstr) 785 } 786 787 func funcfile(f funcInfo, fileno int32) string { 788 datap := f.datap 789 if !f.valid() { 790 return "?" 791 } 792 return gostringnocopy(&datap.pclntable[datap.filetab[fileno]]) 793 } 794 795 func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) { 796 datap := f.datap 797 if !f.valid() { 798 return "?", 0 799 } 800 fileno := int(pcvalue(f, f.pcfile, targetpc, nil, strict)) 801 line = pcvalue(f, f.pcln, targetpc, nil, strict) 802 if fileno == -1 || line == -1 || fileno >= len(datap.filetab) { 803 // print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n") 804 return "?", 0 805 } 806 file = gostringnocopy(&datap.pclntable[datap.filetab[fileno]]) 807 return 808 } 809 810 func funcline(f funcInfo, targetpc uintptr) (file string, line int32) { 811 return funcline1(f, targetpc, true) 812 } 813 814 func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 { 815 x := pcvalue(f, f.pcsp, targetpc, cache, true) 816 if x&(sys.PtrSize-1) != 0 { 817 print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") 818 } 819 return x 820 } 821 822 func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache) int32 { 823 if table < 0 || table >= f.npcdata { 824 return -1 825 } 826 off := *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4)) 827 return pcvalue(f, off, targetpc, cache, true) 828 } 829 830 func funcdata(f funcInfo, i int32) unsafe.Pointer { 831 if i < 0 || i >= f.nfuncdata { 832 return nil 833 } 834 p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4) 835 if sys.PtrSize == 8 && uintptr(p)&4 != 0 { 836 if uintptr(unsafe.Pointer(f._func))&4 != 0 { 837 println("runtime: misaligned func", f._func) 838 } 839 p = add(p, 4) 840 } 841 return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize)) 842 } 843 844 // step advances to the next pc, value pair in the encoded table. 845 func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) { 846 // For both uvdelta and pcdelta, the common case (~70%) 847 // is that they are a single byte. If so, avoid calling readvarint. 848 uvdelta := uint32(p[0]) 849 if uvdelta == 0 && !first { 850 return nil, false 851 } 852 n := uint32(1) 853 if uvdelta&0x80 != 0 { 854 n, uvdelta = readvarint(p) 855 } 856 p = p[n:] 857 if uvdelta&1 != 0 { 858 uvdelta = ^(uvdelta >> 1) 859 } else { 860 uvdelta >>= 1 861 } 862 vdelta := int32(uvdelta) 863 pcdelta := uint32(p[0]) 864 n = 1 865 if pcdelta&0x80 != 0 { 866 n, pcdelta = readvarint(p) 867 } 868 p = p[n:] 869 *pc += uintptr(pcdelta * sys.PCQuantum) 870 *val += vdelta 871 return p, true 872 } 873 874 // readvarint reads a varint from p. 875 func readvarint(p []byte) (read uint32, val uint32) { 876 var v, shift, n uint32 877 for { 878 b := p[n] 879 n++ 880 v |= uint32(b&0x7F) << (shift & 31) 881 if b&0x80 == 0 { 882 break 883 } 884 shift += 7 885 } 886 return n, v 887 } 888 889 type stackmap struct { 890 n int32 // number of bitmaps 891 nbit int32 // number of bits in each bitmap 892 bytedata [1]byte // bitmaps, each starting on a byte boundary 893 } 894 895 //go:nowritebarrier 896 func stackmapdata(stkmap *stackmap, n int32) bitvector { 897 if n < 0 || n >= stkmap.n { 898 throw("stackmapdata: index out of range") 899 } 900 return bitvector{stkmap.nbit, (*byte)(add(unsafe.Pointer(&stkmap.bytedata), uintptr(n*((stkmap.nbit+7)>>3))))} 901 } 902 903 // inlinedCall is the encoding of entries in the FUNCDATA_InlTree table. 904 type inlinedCall struct { 905 parent int32 // index of parent in the inltree, or < 0 906 file int32 // fileno index into filetab 907 line int32 // line number of the call site 908 func_ int32 // offset into pclntab for name of called function 909 }