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 // expandCgoFrames expands frame information for pc, known to be 152 // a non-Go function, using the cgoSymbolizer hook. expandCgoFrames 153 // returns nil if pc could not be expanded. 154 func expandCgoFrames(pc uintptr) []Frame { 155 arg := cgoSymbolizerArg{pc: pc} 156 callCgoSymbolizer(&arg) 157 158 if arg.file == nil && arg.funcName == nil { 159 // No useful information from symbolizer. 160 return nil 161 } 162 163 var frames []Frame 164 for { 165 frames = append(frames, Frame{ 166 PC: pc, 167 Func: nil, 168 Function: gostring(arg.funcName), 169 File: gostring(arg.file), 170 Line: int(arg.lineno), 171 Entry: arg.entry, 172 // funcInfo is zero, which implies !funcInfo.valid(). 173 // That ensures that we use the File/Line info given here. 174 }) 175 if arg.more == 0 { 176 break 177 } 178 callCgoSymbolizer(&arg) 179 } 180 181 // No more frames for this PC. Tell the symbolizer we are done. 182 // We don't try to maintain a single cgoSymbolizerArg for the 183 // whole use of Frames, because there would be no good way to tell 184 // the symbolizer when we are done. 185 arg.pc = 0 186 callCgoSymbolizer(&arg) 187 188 return frames 189 } 190 191 // NOTE: Func does not expose the actual unexported fields, because we return *Func 192 // values to users, and we want to keep them from being able to overwrite the data 193 // with (say) *f = Func{}. 194 // All code operating on a *Func must call raw() to get the *_func 195 // or funcInfo() to get the funcInfo instead. 196 197 // A Func represents a Go function in the running binary. 198 type Func struct { 199 opaque struct{} // unexported field to disallow conversions 200 } 201 202 func (f *Func) raw() *_func { 203 return (*_func)(unsafe.Pointer(f)) 204 } 205 206 func (f *Func) funcInfo() funcInfo { 207 fn := f.raw() 208 return funcInfo{fn, findmoduledatap(fn.entry)} 209 } 210 211 // PCDATA and FUNCDATA table indexes. 212 // 213 // See funcdata.h and ../cmd/internal/objabi/funcdata.go. 214 const ( 215 _PCDATA_RegMapIndex = 0 216 _PCDATA_StackMapIndex = 1 217 _PCDATA_InlTreeIndex = 2 218 219 _FUNCDATA_ArgsPointerMaps = 0 220 _FUNCDATA_LocalsPointerMaps = 1 221 _FUNCDATA_RegPointerMaps = 2 222 _FUNCDATA_StackObjects = 3 223 _FUNCDATA_InlTree = 4 224 225 _ArgsSizeUnknown = -0x80000000 226 ) 227 228 // A FuncID identifies particular functions that need to be treated 229 // specially by the runtime. 230 // Note that in some situations involving plugins, there may be multiple 231 // copies of a particular special runtime function. 232 // Note: this list must match the list in cmd/internal/objabi/funcid.go. 233 type funcID uint8 234 235 const ( 236 funcID_normal funcID = iota // not a special function 237 funcID_runtime_main 238 funcID_goexit 239 funcID_jmpdefer 240 funcID_mcall 241 funcID_morestack 242 funcID_mstart 243 funcID_rt0_go 244 funcID_asmcgocall 245 funcID_sigpanic 246 funcID_runfinq 247 funcID_gcBgMarkWorker 248 funcID_systemstack_switch 249 funcID_systemstack 250 funcID_cgocallback_gofunc 251 funcID_gogo 252 funcID_externalthreadhandler 253 funcID_debugCallV1 254 funcID_gopanic 255 funcID_panicwrap 256 funcID_wrapper // any autogenerated code (hash/eq algorithms, method wrappers, etc.) 257 ) 258 259 // moduledata records information about the layout of the executable 260 // image. It is written by the linker. Any changes here must be 261 // matched changes to the code in cmd/internal/ld/symtab.go:symtab. 262 // moduledata is stored in statically allocated non-pointer memory; 263 // none of the pointers here are visible to the garbage collector. 264 type moduledata struct { 265 pclntable []byte 266 ftab []functab 267 filetab []uint32 268 findfunctab uintptr 269 minpc, maxpc uintptr 270 271 text, etext uintptr 272 noptrdata, enoptrdata uintptr 273 data, edata uintptr 274 bss, ebss uintptr 275 noptrbss, enoptrbss uintptr 276 end, gcdata, gcbss uintptr 277 types, etypes uintptr 278 279 textsectmap []textsect 280 typelinks []int32 // offsets from types 281 itablinks []*itab 282 283 ptab []ptabEntry 284 285 pluginpath string 286 pkghashes []modulehash 287 288 modulename string 289 modulehashes []modulehash 290 291 hasmain uint8 // 1 if module contains the main function, 0 otherwise 292 293 gcdatamask, gcbssmask bitvector 294 295 typemap map[typeOff]*_type // offset to *_rtype in previous module 296 297 bad bool // module failed to load and should be ignored 298 299 next *moduledata 300 } 301 302 // A modulehash is used to compare the ABI of a new module or a 303 // package in a new module with the loaded program. 304 // 305 // For each shared library a module links against, the linker creates an entry in the 306 // moduledata.modulehashes slice containing the name of the module, the abi hash seen 307 // at link time and a pointer to the runtime abi hash. These are checked in 308 // moduledataverify1 below. 309 // 310 // For each loaded plugin, the pkghashes slice has a modulehash of the 311 // newly loaded package that can be used to check the plugin's version of 312 // a package against any previously loaded version of the package. 313 // This is done in plugin.lastmoduleinit. 314 type modulehash struct { 315 modulename string 316 linktimehash string 317 runtimehash *string 318 } 319 320 // pinnedTypemaps are the map[typeOff]*_type from the moduledata objects. 321 // 322 // These typemap objects are allocated at run time on the heap, but the 323 // only direct reference to them is in the moduledata, created by the 324 // linker and marked SNOPTRDATA so it is ignored by the GC. 325 // 326 // To make sure the map isn't collected, we keep a second reference here. 327 var pinnedTypemaps []map[typeOff]*_type 328 329 var firstmoduledata moduledata // linker symbol 330 var lastmoduledatap *moduledata // linker symbol 331 var modulesSlice *[]*moduledata // see activeModules 332 333 // activeModules returns a slice of active modules. 334 // 335 // A module is active once its gcdatamask and gcbssmask have been 336 // assembled and it is usable by the GC. 337 // 338 // This is nosplit/nowritebarrier because it is called by the 339 // cgo pointer checking code. 340 //go:nosplit 341 //go:nowritebarrier 342 func activeModules() []*moduledata { 343 p := (*[]*moduledata)(atomic.Loadp(unsafe.Pointer(&modulesSlice))) 344 if p == nil { 345 return nil 346 } 347 return *p 348 } 349 350 // modulesinit creates the active modules slice out of all loaded modules. 351 // 352 // When a module is first loaded by the dynamic linker, an .init_array 353 // function (written by cmd/link) is invoked to call addmoduledata, 354 // appending to the module to the linked list that starts with 355 // firstmoduledata. 356 // 357 // There are two times this can happen in the lifecycle of a Go 358 // program. First, if compiled with -linkshared, a number of modules 359 // built with -buildmode=shared can be loaded at program initialization. 360 // Second, a Go program can load a module while running that was built 361 // with -buildmode=plugin. 362 // 363 // After loading, this function is called which initializes the 364 // moduledata so it is usable by the GC and creates a new activeModules 365 // list. 366 // 367 // Only one goroutine may call modulesinit at a time. 368 func modulesinit() { 369 modules := new([]*moduledata) 370 for md := &firstmoduledata; md != nil; md = md.next { 371 if md.bad { 372 continue 373 } 374 *modules = append(*modules, md) 375 if md.gcdatamask == (bitvector{}) { 376 md.gcdatamask = progToPointerMask((*byte)(unsafe.Pointer(md.gcdata)), md.edata-md.data) 377 md.gcbssmask = progToPointerMask((*byte)(unsafe.Pointer(md.gcbss)), md.ebss-md.bss) 378 } 379 } 380 381 // Modules appear in the moduledata linked list in the order they are 382 // loaded by the dynamic loader, with one exception: the 383 // firstmoduledata itself the module that contains the runtime. This 384 // is not always the first module (when using -buildmode=shared, it 385 // is typically libstd.so, the second module). The order matters for 386 // typelinksinit, so we swap the first module with whatever module 387 // contains the main function. 388 // 389 // See Issue #18729. 390 for i, md := range *modules { 391 if md.hasmain != 0 { 392 (*modules)[0] = md 393 (*modules)[i] = &firstmoduledata 394 break 395 } 396 } 397 398 atomicstorep(unsafe.Pointer(&modulesSlice), unsafe.Pointer(modules)) 399 } 400 401 type functab struct { 402 entry uintptr 403 funcoff uintptr 404 } 405 406 // Mapping information for secondary text sections 407 408 type textsect struct { 409 vaddr uintptr // prelinked section vaddr 410 length uintptr // section length 411 baseaddr uintptr // relocated section address 412 } 413 414 const minfunc = 16 // minimum function size 415 const pcbucketsize = 256 * minfunc // size of bucket in the pc->func lookup table 416 417 // findfunctab is an array of these structures. 418 // Each bucket represents 4096 bytes of the text segment. 419 // Each subbucket represents 256 bytes of the text segment. 420 // To find a function given a pc, locate the bucket and subbucket for 421 // that pc. Add together the idx and subbucket value to obtain a 422 // function index. Then scan the functab array starting at that 423 // index to find the target function. 424 // This table uses 20 bytes for every 4096 bytes of code, or ~0.5% overhead. 425 type findfuncbucket struct { 426 idx uint32 427 subbuckets [16]byte 428 } 429 430 func moduledataverify() { 431 for datap := &firstmoduledata; datap != nil; datap = datap.next { 432 moduledataverify1(datap) 433 } 434 } 435 436 const debugPcln = false 437 438 func moduledataverify1(datap *moduledata) { 439 // See golang.org/s/go12symtab for header: 0xfffffffb, 440 // two zero bytes, a byte giving the PC quantum, 441 // and a byte giving the pointer width in bytes. 442 pcln := *(**[8]byte)(unsafe.Pointer(&datap.pclntable)) 443 pcln32 := *(**[2]uint32)(unsafe.Pointer(&datap.pclntable)) 444 if pcln32[0] != 0xfffffffb || pcln[4] != 0 || pcln[5] != 0 || pcln[6] != sys.PCQuantum || pcln[7] != sys.PtrSize { 445 println("runtime: function symbol table header:", hex(pcln32[0]), hex(pcln[4]), hex(pcln[5]), hex(pcln[6]), hex(pcln[7])) 446 throw("invalid function symbol table\n") 447 } 448 449 // ftab is lookup table for function by program counter. 450 nftab := len(datap.ftab) - 1 451 for i := 0; i < nftab; i++ { 452 // NOTE: ftab[nftab].entry is legal; it is the address beyond the final function. 453 if datap.ftab[i].entry > datap.ftab[i+1].entry { 454 f1 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i].funcoff])), datap} 455 f2 := funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[i+1].funcoff])), datap} 456 f2name := "end" 457 if i+1 < nftab { 458 f2name = funcname(f2) 459 } 460 println("function symbol table not sorted by program counter:", hex(datap.ftab[i].entry), funcname(f1), ">", hex(datap.ftab[i+1].entry), f2name) 461 for j := 0; j <= i; j++ { 462 print("\t", hex(datap.ftab[j].entry), " ", funcname(funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[j].funcoff])), datap}), "\n") 463 } 464 if GOOS == "aix" && isarchive { 465 println("-Wl,-bnoobjreorder is mandatory on aix/ppc64 with c-archive") 466 } 467 throw("invalid runtime symbol table") 468 } 469 } 470 471 if datap.minpc != datap.ftab[0].entry || 472 datap.maxpc != datap.ftab[nftab].entry { 473 throw("minpc or maxpc invalid") 474 } 475 476 for _, modulehash := range datap.modulehashes { 477 if modulehash.linktimehash != *modulehash.runtimehash { 478 println("abi mismatch detected between", datap.modulename, "and", modulehash.modulename) 479 throw("abi mismatch") 480 } 481 } 482 } 483 484 // FuncForPC returns a *Func describing the function that contains the 485 // given program counter address, or else nil. 486 // 487 // If pc represents multiple functions because of inlining, it returns 488 // the a *Func describing the innermost function, but with an entry 489 // of the outermost function. 490 func FuncForPC(pc uintptr) *Func { 491 f := findfunc(pc) 492 if !f.valid() { 493 return nil 494 } 495 if inldata := funcdata(f, _FUNCDATA_InlTree); inldata != nil { 496 // Note: strict=false so bad PCs (those between functions) don't crash the runtime. 497 // We just report the preceding function in that situation. See issue 29735. 498 // TODO: Perhaps we should report no function at all in that case. 499 // The runtime currently doesn't have function end info, alas. 500 if ix := pcdatavalue1(f, _PCDATA_InlTreeIndex, pc, nil, false); ix >= 0 { 501 inltree := (*[1 << 20]inlinedCall)(inldata) 502 name := funcnameFromNameoff(f, inltree[ix].func_) 503 file, line := funcline(f, pc) 504 fi := &funcinl{ 505 entry: f.entry, // entry of the real (the outermost) function. 506 name: name, 507 file: file, 508 line: int(line), 509 } 510 return (*Func)(unsafe.Pointer(fi)) 511 } 512 } 513 return f._Func() 514 } 515 516 // Name returns the name of the function. 517 func (f *Func) Name() string { 518 if f == nil { 519 return "" 520 } 521 fn := f.raw() 522 if fn.entry == 0 { // inlined version 523 fi := (*funcinl)(unsafe.Pointer(fn)) 524 return fi.name 525 } 526 return funcname(f.funcInfo()) 527 } 528 529 // Entry returns the entry address of the function. 530 func (f *Func) Entry() uintptr { 531 fn := f.raw() 532 if fn.entry == 0 { // inlined version 533 fi := (*funcinl)(unsafe.Pointer(fn)) 534 return fi.entry 535 } 536 return fn.entry 537 } 538 539 // FileLine returns the file name and line number of the 540 // source code corresponding to the program counter pc. 541 // The result will not be accurate if pc is not a program 542 // counter within f. 543 func (f *Func) FileLine(pc uintptr) (file string, line int) { 544 fn := f.raw() 545 if fn.entry == 0 { // inlined version 546 fi := (*funcinl)(unsafe.Pointer(fn)) 547 return fi.file, fi.line 548 } 549 // Pass strict=false here, because anyone can call this function, 550 // and they might just be wrong about targetpc belonging to f. 551 file, line32 := funcline1(f.funcInfo(), pc, false) 552 return file, int(line32) 553 } 554 555 func findmoduledatap(pc uintptr) *moduledata { 556 for datap := &firstmoduledata; datap != nil; datap = datap.next { 557 if datap.minpc <= pc && pc < datap.maxpc { 558 return datap 559 } 560 } 561 return nil 562 } 563 564 type funcInfo struct { 565 *_func 566 datap *moduledata 567 } 568 569 func (f funcInfo) valid() bool { 570 return f._func != nil 571 } 572 573 func (f funcInfo) _Func() *Func { 574 return (*Func)(unsafe.Pointer(f._func)) 575 } 576 577 func findfunc(pc uintptr) funcInfo { 578 datap := findmoduledatap(pc) 579 if datap == nil { 580 return funcInfo{} 581 } 582 const nsub = uintptr(len(findfuncbucket{}.subbuckets)) 583 584 x := pc - datap.minpc 585 b := x / pcbucketsize 586 i := x % pcbucketsize / (pcbucketsize / nsub) 587 588 ffb := (*findfuncbucket)(add(unsafe.Pointer(datap.findfunctab), b*unsafe.Sizeof(findfuncbucket{}))) 589 idx := ffb.idx + uint32(ffb.subbuckets[i]) 590 591 // If the idx is beyond the end of the ftab, set it to the end of the table and search backward. 592 // This situation can occur if multiple text sections are generated to handle large text sections 593 // and the linker has inserted jump tables between them. 594 595 if idx >= uint32(len(datap.ftab)) { 596 idx = uint32(len(datap.ftab) - 1) 597 } 598 if pc < datap.ftab[idx].entry { 599 // With multiple text sections, the idx might reference a function address that 600 // is higher than the pc being searched, so search backward until the matching address is found. 601 602 for datap.ftab[idx].entry > pc && idx > 0 { 603 idx-- 604 } 605 if idx == 0 { 606 throw("findfunc: bad findfunctab entry idx") 607 } 608 } else { 609 // linear search to find func with pc >= entry. 610 for datap.ftab[idx+1].entry <= pc { 611 idx++ 612 } 613 } 614 return funcInfo{(*_func)(unsafe.Pointer(&datap.pclntable[datap.ftab[idx].funcoff])), datap} 615 } 616 617 type pcvalueCache struct { 618 entries [2][8]pcvalueCacheEnt 619 } 620 621 type pcvalueCacheEnt struct { 622 // targetpc and off together are the key of this cache entry. 623 targetpc uintptr 624 off int32 625 // val is the value of this cached pcvalue entry. 626 val int32 627 } 628 629 // pcvalueCacheKey returns the outermost index in a pcvalueCache to use for targetpc. 630 // It must be very cheap to calculate. 631 // For now, align to sys.PtrSize and reduce mod the number of entries. 632 // In practice, this appears to be fairly randomly and evenly distributed. 633 func pcvalueCacheKey(targetpc uintptr) uintptr { 634 return (targetpc / sys.PtrSize) % uintptr(len(pcvalueCache{}.entries)) 635 } 636 637 func pcvalue(f funcInfo, off int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 { 638 if off == 0 { 639 return -1 640 } 641 642 // Check the cache. This speeds up walks of deep stacks, which 643 // tend to have the same recursive functions over and over. 644 // 645 // This cache is small enough that full associativity is 646 // cheaper than doing the hashing for a less associative 647 // cache. 648 if cache != nil { 649 x := pcvalueCacheKey(targetpc) 650 for i := range cache.entries[x] { 651 // We check off first because we're more 652 // likely to have multiple entries with 653 // different offsets for the same targetpc 654 // than the other way around, so we'll usually 655 // fail in the first clause. 656 ent := &cache.entries[x][i] 657 if ent.off == off && ent.targetpc == targetpc { 658 return ent.val 659 } 660 } 661 } 662 663 if !f.valid() { 664 if strict && panicking == 0 { 665 print("runtime: no module data for ", hex(f.entry), "\n") 666 throw("no module data") 667 } 668 return -1 669 } 670 datap := f.datap 671 p := datap.pclntable[off:] 672 pc := f.entry 673 val := int32(-1) 674 for { 675 var ok bool 676 p, ok = step(p, &pc, &val, pc == f.entry) 677 if !ok { 678 break 679 } 680 if targetpc < pc { 681 // Replace a random entry in the cache. Random 682 // replacement prevents a performance cliff if 683 // a recursive stack's cycle is slightly 684 // larger than the cache. 685 // Put the new element at the beginning, 686 // since it is the most likely to be newly used. 687 if cache != nil { 688 x := pcvalueCacheKey(targetpc) 689 e := &cache.entries[x] 690 ci := fastrand() % uint32(len(cache.entries[x])) 691 e[ci] = e[0] 692 e[0] = pcvalueCacheEnt{ 693 targetpc: targetpc, 694 off: off, 695 val: val, 696 } 697 } 698 699 return val 700 } 701 } 702 703 // If there was a table, it should have covered all program counters. 704 // If not, something is wrong. 705 if panicking != 0 || !strict { 706 return -1 707 } 708 709 print("runtime: invalid pc-encoded table f=", funcname(f), " pc=", hex(pc), " targetpc=", hex(targetpc), " tab=", p, "\n") 710 711 p = datap.pclntable[off:] 712 pc = f.entry 713 val = -1 714 for { 715 var ok bool 716 p, ok = step(p, &pc, &val, pc == f.entry) 717 if !ok { 718 break 719 } 720 print("\tvalue=", val, " until pc=", hex(pc), "\n") 721 } 722 723 throw("invalid runtime symbol table") 724 return -1 725 } 726 727 func cfuncname(f funcInfo) *byte { 728 if !f.valid() || f.nameoff == 0 { 729 return nil 730 } 731 return &f.datap.pclntable[f.nameoff] 732 } 733 734 func funcname(f funcInfo) string { 735 return gostringnocopy(cfuncname(f)) 736 } 737 738 func funcnameFromNameoff(f funcInfo, nameoff int32) string { 739 datap := f.datap 740 if !f.valid() { 741 return "" 742 } 743 cstr := &datap.pclntable[nameoff] 744 return gostringnocopy(cstr) 745 } 746 747 func funcfile(f funcInfo, fileno int32) string { 748 datap := f.datap 749 if !f.valid() { 750 return "?" 751 } 752 return gostringnocopy(&datap.pclntable[datap.filetab[fileno]]) 753 } 754 755 func funcline1(f funcInfo, targetpc uintptr, strict bool) (file string, line int32) { 756 datap := f.datap 757 if !f.valid() { 758 return "?", 0 759 } 760 fileno := int(pcvalue(f, f.pcfile, targetpc, nil, strict)) 761 line = pcvalue(f, f.pcln, targetpc, nil, strict) 762 if fileno == -1 || line == -1 || fileno >= len(datap.filetab) { 763 // print("looking for ", hex(targetpc), " in ", funcname(f), " got file=", fileno, " line=", lineno, "\n") 764 return "?", 0 765 } 766 file = gostringnocopy(&datap.pclntable[datap.filetab[fileno]]) 767 return 768 } 769 770 func funcline(f funcInfo, targetpc uintptr) (file string, line int32) { 771 return funcline1(f, targetpc, true) 772 } 773 774 func funcspdelta(f funcInfo, targetpc uintptr, cache *pcvalueCache) int32 { 775 x := pcvalue(f, f.pcsp, targetpc, cache, true) 776 if x&(sys.PtrSize-1) != 0 { 777 print("invalid spdelta ", funcname(f), " ", hex(f.entry), " ", hex(targetpc), " ", hex(f.pcsp), " ", x, "\n") 778 } 779 return x 780 } 781 782 func pcdatastart(f funcInfo, table int32) int32 { 783 return *(*int32)(add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(table)*4)) 784 } 785 786 func pcdatavalue(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache) int32 { 787 if table < 0 || table >= f.npcdata { 788 return -1 789 } 790 return pcvalue(f, pcdatastart(f, table), targetpc, cache, true) 791 } 792 793 func pcdatavalue1(f funcInfo, table int32, targetpc uintptr, cache *pcvalueCache, strict bool) int32 { 794 if table < 0 || table >= f.npcdata { 795 return -1 796 } 797 return pcvalue(f, pcdatastart(f, table), targetpc, cache, strict) 798 } 799 800 func funcdata(f funcInfo, i uint8) unsafe.Pointer { 801 if i < 0 || i >= f.nfuncdata { 802 return nil 803 } 804 p := add(unsafe.Pointer(&f.nfuncdata), unsafe.Sizeof(f.nfuncdata)+uintptr(f.npcdata)*4) 805 if sys.PtrSize == 8 && uintptr(p)&4 != 0 { 806 if uintptr(unsafe.Pointer(f._func))&4 != 0 { 807 println("runtime: misaligned func", f._func) 808 } 809 p = add(p, 4) 810 } 811 return *(*unsafe.Pointer)(add(p, uintptr(i)*sys.PtrSize)) 812 } 813 814 // step advances to the next pc, value pair in the encoded table. 815 func step(p []byte, pc *uintptr, val *int32, first bool) (newp []byte, ok bool) { 816 // For both uvdelta and pcdelta, the common case (~70%) 817 // is that they are a single byte. If so, avoid calling readvarint. 818 uvdelta := uint32(p[0]) 819 if uvdelta == 0 && !first { 820 return nil, false 821 } 822 n := uint32(1) 823 if uvdelta&0x80 != 0 { 824 n, uvdelta = readvarint(p) 825 } 826 *val += int32(-(uvdelta & 1) ^ (uvdelta >> 1)) 827 p = p[n:] 828 829 pcdelta := uint32(p[0]) 830 n = 1 831 if pcdelta&0x80 != 0 { 832 n, pcdelta = readvarint(p) 833 } 834 p = p[n:] 835 *pc += uintptr(pcdelta * sys.PCQuantum) 836 return p, true 837 } 838 839 // readvarint reads a varint from p. 840 func readvarint(p []byte) (read uint32, val uint32) { 841 var v, shift, n uint32 842 for { 843 b := p[n] 844 n++ 845 v |= uint32(b&0x7F) << (shift & 31) 846 if b&0x80 == 0 { 847 break 848 } 849 shift += 7 850 } 851 return n, v 852 } 853 854 type stackmap struct { 855 n int32 // number of bitmaps 856 nbit int32 // number of bits in each bitmap 857 bytedata [1]byte // bitmaps, each starting on a byte boundary 858 } 859 860 //go:nowritebarrier 861 func stackmapdata(stkmap *stackmap, n int32) bitvector { 862 // Check this invariant only when stackDebug is on at all. 863 // The invariant is already checked by many of stackmapdata's callers, 864 // and disabling it by default allows stackmapdata to be inlined. 865 if stackDebug > 0 && (n < 0 || n >= stkmap.n) { 866 throw("stackmapdata: index out of range") 867 } 868 return bitvector{stkmap.nbit, addb(&stkmap.bytedata[0], uintptr(n*((stkmap.nbit+7)>>3)))} 869 } 870 871 // inlinedCall is the encoding of entries in the FUNCDATA_InlTree table. 872 type inlinedCall struct { 873 parent int16 // index of parent in the inltree, or < 0 874 funcID funcID // type of the called function 875 _ byte 876 file int32 // fileno index into filetab 877 line int32 // line number of the call site 878 func_ int32 // offset into pclntab for name of called function 879 parentPc int32 // position of an instruction whose source position is the call site (offset from entry) 880 } 881
View as plain text