Source file
src/runtime/traceback.go
Documentation: runtime
1
2
3
4
5 package runtime
6
7 import (
8 "runtime/internal/atomic"
9 "runtime/internal/sys"
10 "unsafe"
11 )
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36 const usesLR = sys.MinFrameSize > 0
37
38 var (
39
40 goexitPC uintptr
41 jmpdeferPC uintptr
42 mcallPC uintptr
43 morestackPC uintptr
44 mstartPC uintptr
45 rt0_goPC uintptr
46 asmcgocallPC uintptr
47 sigpanicPC uintptr
48 runfinqPC uintptr
49 bgsweepPC uintptr
50 forcegchelperPC uintptr
51 timerprocPC uintptr
52 gcBgMarkWorkerPC uintptr
53 systemstack_switchPC uintptr
54 systemstackPC uintptr
55 cgocallback_gofuncPC uintptr
56 skipPC uintptr
57
58 gogoPC uintptr
59
60 externalthreadhandlerp uintptr
61 )
62
63 func tracebackinit() {
64
65
66
67
68 goexitPC = funcPC(goexit)
69 jmpdeferPC = funcPC(jmpdefer)
70 mcallPC = funcPC(mcall)
71 morestackPC = funcPC(morestack)
72 mstartPC = funcPC(mstart)
73 rt0_goPC = funcPC(rt0_go)
74 asmcgocallPC = funcPC(asmcgocall)
75 sigpanicPC = funcPC(sigpanic)
76 runfinqPC = funcPC(runfinq)
77 bgsweepPC = funcPC(bgsweep)
78 forcegchelperPC = funcPC(forcegchelper)
79 timerprocPC = funcPC(timerproc)
80 gcBgMarkWorkerPC = funcPC(gcBgMarkWorker)
81 systemstack_switchPC = funcPC(systemstack_switch)
82 systemstackPC = funcPC(systemstack)
83 cgocallback_gofuncPC = funcPC(cgocallback_gofunc)
84 skipPC = funcPC(skipPleaseUseCallersFrames)
85
86
87 gogoPC = funcPC(gogo)
88 }
89
90
91
92 func tracebackdefers(gp *g, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer) {
93 var frame stkframe
94 for d := gp._defer; d != nil; d = d.link {
95 fn := d.fn
96 if fn == nil {
97
98 frame.pc = 0
99 frame.fn = funcInfo{}
100 frame.argp = 0
101 frame.arglen = 0
102 frame.argmap = nil
103 } else {
104 frame.pc = fn.fn
105 f := findfunc(frame.pc)
106 if !f.valid() {
107 print("runtime: unknown pc in defer ", hex(frame.pc), "\n")
108 throw("unknown pc")
109 }
110 frame.fn = f
111 frame.argp = uintptr(deferArgs(d))
112 frame.arglen, frame.argmap = getArgInfo(&frame, f, true, fn)
113 }
114 frame.continpc = frame.pc
115 if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) {
116 return
117 }
118 }
119 }
120
121 const sizeofSkipFunction = 256
122
123
124 func skipPleaseUseCallersFrames()
125
126
127
128
129
130
131
132
133
134
135
136 func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max int, callback func(*stkframe, unsafe.Pointer) bool, v unsafe.Pointer, flags uint) int {
137 if skip > 0 && callback != nil {
138 throw("gentraceback callback cannot be used with non-zero skip")
139 }
140 if goexitPC == 0 {
141 throw("gentraceback before goexitPC initialization")
142 }
143 g := getg()
144 if g == gp && g == g.m.curg {
145
146
147
148
149
150
151
152
153
154
155
156
157
158 throw("gentraceback cannot trace user goroutine on its own stack")
159 }
160 level, _, _ := gotraceback()
161
162 if pc0 == ^uintptr(0) && sp0 == ^uintptr(0) {
163 if gp.syscallsp != 0 {
164 pc0 = gp.syscallpc
165 sp0 = gp.syscallsp
166 if usesLR {
167 lr0 = 0
168 }
169 } else {
170 pc0 = gp.sched.pc
171 sp0 = gp.sched.sp
172 if usesLR {
173 lr0 = gp.sched.lr
174 }
175 }
176 }
177
178 nprint := 0
179 var frame stkframe
180 frame.pc = pc0
181 frame.sp = sp0
182 if usesLR {
183 frame.lr = lr0
184 }
185 waspanic := false
186 cgoCtxt := gp.cgoCtxt
187 printing := pcbuf == nil && callback == nil
188 _defer := gp._defer
189 elideWrapper := false
190
191 for _defer != nil && _defer.sp == _NoArgs {
192 _defer = _defer.link
193 }
194
195
196
197 if frame.pc == 0 {
198 if usesLR {
199 frame.pc = *(*uintptr)(unsafe.Pointer(frame.sp))
200 frame.lr = 0
201 } else {
202 frame.pc = uintptr(*(*sys.Uintreg)(unsafe.Pointer(frame.sp)))
203 frame.sp += sys.RegSize
204 }
205 }
206
207 f := findfunc(frame.pc)
208 if !f.valid() {
209 if callback != nil || printing {
210 print("runtime: unknown pc ", hex(frame.pc), "\n")
211 tracebackHexdump(gp.stack, &frame, 0)
212 }
213 if callback != nil {
214 throw("unknown pc")
215 }
216 return 0
217 }
218 frame.fn = f
219
220 var cache pcvalueCache
221
222 n := 0
223 for n < max {
224
225
226
227
228
229
230 f = frame.fn
231 if f.pcsp == 0 {
232
233
234 break
235 }
236
237
238
239 if frame.fp == 0 {
240
241
242
243 sp := frame.sp
244 if flags&_TraceJumpStack != 0 && f.entry == systemstackPC && gp == g.m.g0 && gp.m.curg != nil {
245 sp = gp.m.curg.sched.sp
246 frame.sp = sp
247 cgoCtxt = gp.m.curg.cgoCtxt
248 }
249 frame.fp = sp + uintptr(funcspdelta(f, frame.pc, &cache))
250 if !usesLR {
251
252 frame.fp += sys.RegSize
253 }
254 }
255 var flr funcInfo
256 if topofstack(f, gp.m != nil && gp == gp.m.g0) {
257 frame.lr = 0
258 flr = funcInfo{}
259 } else if usesLR && f.entry == jmpdeferPC {
260
261
262
263
264
265
266 if callback != nil {
267 throw("traceback_arm: found jmpdefer when tracing with callback")
268 }
269 frame.lr = 0
270 } else {
271 var lrPtr uintptr
272 if usesLR {
273 if n == 0 && frame.sp < frame.fp || frame.lr == 0 {
274 lrPtr = frame.sp
275 frame.lr = *(*uintptr)(unsafe.Pointer(lrPtr))
276 }
277 } else {
278 if frame.lr == 0 {
279 lrPtr = frame.fp - sys.RegSize
280 frame.lr = uintptr(*(*sys.Uintreg)(unsafe.Pointer(lrPtr)))
281 }
282 }
283 flr = findfunc(frame.lr)
284 if !flr.valid() {
285
286
287
288
289 doPrint := printing
290 if doPrint && gp.m.incgo {
291
292
293
294
295 doPrint = false
296 }
297 if callback != nil || doPrint {
298 print("runtime: unexpected return pc for ", funcname(f), " called from ", hex(frame.lr), "\n")
299 tracebackHexdump(gp.stack, &frame, lrPtr)
300 }
301 if callback != nil {
302 throw("unknown caller pc")
303 }
304 }
305 }
306
307 frame.varp = frame.fp
308 if !usesLR {
309
310 frame.varp -= sys.RegSize
311 }
312
313
314
315 if framepointer_enabled && GOARCH == "amd64" && frame.varp > frame.sp {
316 frame.varp -= sys.RegSize
317 }
318
319
320
321
322
323
324
325 if callback != nil || printing {
326 frame.argp = frame.fp + sys.MinFrameSize
327 frame.arglen, frame.argmap = getArgInfo(&frame, f, callback != nil, nil)
328 }
329
330
331
332
333
334
335
336
337
338
339
340 frame.continpc = frame.pc
341 if waspanic {
342 if _defer != nil && _defer.sp == frame.sp {
343 frame.continpc = _defer.pc
344 } else {
345 frame.continpc = 0
346 }
347 }
348
349
350 for _defer != nil && (_defer.sp == frame.sp || _defer.sp == _NoArgs) {
351 _defer = _defer.link
352 }
353
354 if callback != nil {
355 if !callback((*stkframe)(noescape(unsafe.Pointer(&frame))), v) {
356 return n
357 }
358 }
359
360 if pcbuf != nil {
361 if skip == 0 {
362 (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = frame.pc
363 } else {
364
365 tracepc := frame.pc
366 if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
367 tracepc--
368 }
369 inldata := funcdata(f, _FUNCDATA_InlTree)
370
371
372 if inldata == nil {
373 skip--
374 goto skipped
375 }
376
377 ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, &cache)
378 inltree := (*[1 << 20]inlinedCall)(inldata)
379
380 logicalSkipped := 0
381 for ix >= 0 && skip > 0 {
382 skip--
383 logicalSkipped++
384 ix = inltree[ix].parent
385 }
386
387
388 if skip > 0 {
389 skip--
390 goto skipped
391 }
392
393
394 (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = frame.pc
395
396
397 if n+1 < max {
398 n++
399 skipPC := funcPC(skipPleaseUseCallersFrames) + uintptr(logicalSkipped)
400 (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = skipPC
401 }
402 }
403 }
404
405 if printing {
406
407
408
409
410
411
412 name := funcname(f)
413 nextElideWrapper := elideWrapperCalling(name)
414 if (flags&_TraceRuntimeFrames) != 0 || showframe(f, gp, nprint == 0, elideWrapper && nprint != 0) {
415
416
417
418
419 tracepc := frame.pc
420 if (n > 0 || flags&_TraceTrap == 0) && frame.pc > f.entry && !waspanic {
421 tracepc--
422 }
423 file, line := funcline(f, tracepc)
424 inldata := funcdata(f, _FUNCDATA_InlTree)
425 if inldata != nil {
426 inltree := (*[1 << 20]inlinedCall)(inldata)
427 ix := pcdatavalue(f, _PCDATA_InlTreeIndex, tracepc, nil)
428 for ix != -1 {
429 name := funcnameFromNameoff(f, inltree[ix].func_)
430 print(name, "(...)\n")
431 print("\t", file, ":", line, "\n")
432
433 file = funcfile(f, inltree[ix].file)
434 line = inltree[ix].line
435 ix = inltree[ix].parent
436 }
437 }
438 if name == "runtime.gopanic" {
439 name = "panic"
440 }
441 print(name, "(")
442 argp := (*[100]uintptr)(unsafe.Pointer(frame.argp))
443 for i := uintptr(0); i < frame.arglen/sys.PtrSize; i++ {
444 if i >= 10 {
445 print(", ...")
446 break
447 }
448 if i != 0 {
449 print(", ")
450 }
451 print(hex(argp[i]))
452 }
453 print(")\n")
454 print("\t", file, ":", line)
455 if frame.pc > f.entry {
456 print(" +", hex(frame.pc-f.entry))
457 }
458 if g.m.throwing > 0 && gp == g.m.curg || level >= 2 {
459 print(" fp=", hex(frame.fp), " sp=", hex(frame.sp), " pc=", hex(frame.pc))
460 }
461 print("\n")
462 nprint++
463 }
464 elideWrapper = nextElideWrapper
465 }
466 n++
467
468 skipped:
469 if f.entry == cgocallback_gofuncPC && len(cgoCtxt) > 0 {
470 ctxt := cgoCtxt[len(cgoCtxt)-1]
471 cgoCtxt = cgoCtxt[:len(cgoCtxt)-1]
472
473
474
475
476 if skip == 0 && callback == nil {
477 n = tracebackCgoContext(pcbuf, printing, ctxt, n, max)
478 }
479 }
480
481 waspanic = f.entry == sigpanicPC
482
483
484 if !flr.valid() {
485 break
486 }
487
488
489 frame.fn = flr
490 frame.pc = frame.lr
491 frame.lr = 0
492 frame.sp = frame.fp
493 frame.fp = 0
494 frame.argmap = nil
495
496
497
498 if usesLR && waspanic {
499 x := *(*uintptr)(unsafe.Pointer(frame.sp))
500 frame.sp += sys.MinFrameSize
501 if GOARCH == "arm64" {
502
503 frame.sp += sys.PtrSize
504 }
505 f = findfunc(frame.pc)
506 frame.fn = f
507 if !f.valid() {
508 frame.pc = x
509 } else if funcspdelta(f, frame.pc, &cache) == 0 {
510 frame.lr = x
511 }
512 }
513 }
514
515 if printing {
516 n = nprint
517 }
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568 if callback != nil && n < max && _defer != nil {
569 if _defer != nil {
570 print("runtime: g", gp.goid, ": leftover defer sp=", hex(_defer.sp), " pc=", hex(_defer.pc), "\n")
571 }
572 for _defer = gp._defer; _defer != nil; _defer = _defer.link {
573 print("\tdefer ", _defer, " sp=", hex(_defer.sp), " pc=", hex(_defer.pc), "\n")
574 }
575 throw("traceback has leftover defers")
576 }
577
578 if callback != nil && n < max && frame.sp != gp.stktopsp {
579 print("runtime: g", gp.goid, ": frame.sp=", hex(frame.sp), " top=", hex(gp.stktopsp), "\n")
580 print("\tstack=[", hex(gp.stack.lo), "-", hex(gp.stack.hi), "] n=", n, " max=", max, "\n")
581 throw("traceback did not unwind completely")
582 }
583
584 return n
585 }
586
587
588
589 type reflectMethodValue struct {
590 fn uintptr
591 stack *bitvector
592 }
593
594
595
596
597
598
599
600
601
602 func getArgInfo(frame *stkframe, f funcInfo, needArgMap bool, ctxt *funcval) (arglen uintptr, argmap *bitvector) {
603 arglen = uintptr(f.args)
604 if needArgMap && f.args == _ArgsSizeUnknown {
605
606 switch funcname(f) {
607 case "reflect.makeFuncStub", "reflect.methodValueCall":
608
609
610 var mv *reflectMethodValue
611 if ctxt != nil {
612
613
614
615 mv = (*reflectMethodValue)(unsafe.Pointer(ctxt))
616 } else {
617
618
619
620
621
622 arg0 := frame.sp + sys.MinFrameSize
623 mv = *(**reflectMethodValue)(unsafe.Pointer(arg0))
624 }
625 if mv.fn != f.entry {
626 print("runtime: confused by ", funcname(f), "\n")
627 throw("reflect mismatch")
628 }
629 bv := mv.stack
630 arglen = uintptr(bv.n * sys.PtrSize)
631 argmap = bv
632 }
633 }
634 return
635 }
636
637
638
639
640 func tracebackCgoContext(pcbuf *uintptr, printing bool, ctxt uintptr, n, max int) int {
641 var cgoPCs [32]uintptr
642 cgoContextPCs(ctxt, cgoPCs[:])
643 var arg cgoSymbolizerArg
644 anySymbolized := false
645 for _, pc := range cgoPCs {
646 if pc == 0 || n >= max {
647 break
648 }
649 if pcbuf != nil {
650 (*[1 << 20]uintptr)(unsafe.Pointer(pcbuf))[n] = pc
651 }
652 if printing {
653 if cgoSymbolizer == nil {
654 print("non-Go function at pc=", hex(pc), "\n")
655 } else {
656 c := printOneCgoTraceback(pc, max-n, &arg)
657 n += c - 1
658 anySymbolized = true
659 }
660 }
661 n++
662 }
663 if anySymbolized {
664 arg.pc = 0
665 callCgoSymbolizer(&arg)
666 }
667 return n
668 }
669
670 func printcreatedby(gp *g) {
671
672 pc := gp.gopc
673 f := findfunc(pc)
674 if f.valid() && showframe(f, gp, false, false) && gp.goid != 1 {
675 print("created by ", funcname(f), "\n")
676 tracepc := pc
677 if pc > f.entry {
678 tracepc -= sys.PCQuantum
679 }
680 file, line := funcline(f, tracepc)
681 print("\t", file, ":", line)
682 if pc > f.entry {
683 print(" +", hex(pc-f.entry))
684 }
685 print("\n")
686 }
687 }
688
689 func traceback(pc, sp, lr uintptr, gp *g) {
690 traceback1(pc, sp, lr, gp, 0)
691 }
692
693
694
695
696
697
698
699 func tracebacktrap(pc, sp, lr uintptr, gp *g) {
700 traceback1(pc, sp, lr, gp, _TraceTrap)
701 }
702
703 func traceback1(pc, sp, lr uintptr, gp *g, flags uint) {
704
705 if iscgo && gp.m != nil && gp.m.ncgo > 0 && gp.syscallsp != 0 && gp.m.cgoCallers != nil && gp.m.cgoCallers[0] != 0 {
706
707
708
709
710
711
712 atomic.Store(&gp.m.cgoCallersUse, 1)
713 cgoCallers := *gp.m.cgoCallers
714 gp.m.cgoCallers[0] = 0
715 atomic.Store(&gp.m.cgoCallersUse, 0)
716
717 printCgoTraceback(&cgoCallers)
718 }
719
720 var n int
721 if readgstatus(gp)&^_Gscan == _Gsyscall {
722
723 pc = gp.syscallpc
724 sp = gp.syscallsp
725 flags &^= _TraceTrap
726 }
727
728
729 n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags)
730 if n == 0 && (flags&_TraceRuntimeFrames) == 0 {
731 n = gentraceback(pc, sp, lr, gp, 0, nil, _TracebackMaxFrames, nil, nil, flags|_TraceRuntimeFrames)
732 }
733 if n == _TracebackMaxFrames {
734 print("...additional frames elided...\n")
735 }
736 printcreatedby(gp)
737 }
738
739 func callers(skip int, pcbuf []uintptr) int {
740 sp := getcallersp(unsafe.Pointer(&skip))
741 pc := getcallerpc()
742 gp := getg()
743 var n int
744 systemstack(func() {
745 n = gentraceback(pc, sp, 0, gp, skip, &pcbuf[0], len(pcbuf), nil, nil, 0)
746 })
747 return n
748 }
749
750 func gcallers(gp *g, skip int, pcbuf []uintptr) int {
751 return gentraceback(^uintptr(0), ^uintptr(0), 0, gp, skip, &pcbuf[0], len(pcbuf), nil, nil, 0)
752 }
753
754 func showframe(f funcInfo, gp *g, firstFrame, elideWrapper bool) bool {
755 g := getg()
756 if g.m.throwing > 0 && gp != nil && (gp == g.m.curg || gp == g.m.caughtsig.ptr()) {
757 return true
758 }
759 level, _, _ := gotraceback()
760 if level > 1 {
761
762 return true
763 }
764
765 if !f.valid() {
766 return false
767 }
768
769 if elideWrapper {
770 file, _ := funcline(f, f.entry)
771 if file == "<autogenerated>" {
772 return false
773 }
774 }
775
776 name := funcname(f)
777
778
779
780
781
782
783 if name == "runtime.gopanic" && !firstFrame {
784 return true
785 }
786
787 return contains(name, ".") && (!hasprefix(name, "runtime.") || isExportedRuntime(name))
788 }
789
790
791
792 func isExportedRuntime(name string) bool {
793 const n = len("runtime.")
794 return len(name) > n && name[:n] == "runtime." && 'A' <= name[n] && name[n] <= 'Z'
795 }
796
797
798
799 func elideWrapperCalling(name string) bool {
800
801
802 return !(name == "runtime.gopanic" || name == "runtime.sigpanic" || name == "runtime.panicwrap")
803 }
804
805 var gStatusStrings = [...]string{
806 _Gidle: "idle",
807 _Grunnable: "runnable",
808 _Grunning: "running",
809 _Gsyscall: "syscall",
810 _Gwaiting: "waiting",
811 _Gdead: "dead",
812 _Gcopystack: "copystack",
813 }
814
815 func goroutineheader(gp *g) {
816 gpstatus := readgstatus(gp)
817
818 isScan := gpstatus&_Gscan != 0
819 gpstatus &^= _Gscan
820
821
822 var status string
823 if 0 <= gpstatus && gpstatus < uint32(len(gStatusStrings)) {
824 status = gStatusStrings[gpstatus]
825 } else {
826 status = "???"
827 }
828
829
830 if gpstatus == _Gwaiting && gp.waitreason != "" {
831 status = gp.waitreason
832 }
833
834
835 var waitfor int64
836 if (gpstatus == _Gwaiting || gpstatus == _Gsyscall) && gp.waitsince != 0 {
837 waitfor = (nanotime() - gp.waitsince) / 60e9
838 }
839 print("goroutine ", gp.goid, " [", status)
840 if isScan {
841 print(" (scan)")
842 }
843 if waitfor >= 1 {
844 print(", ", waitfor, " minutes")
845 }
846 if gp.lockedm != 0 {
847 print(", locked to thread")
848 }
849 print("]:\n")
850 }
851
852 func tracebackothers(me *g) {
853 level, _, _ := gotraceback()
854
855
856 g := getg()
857 gp := g.m.curg
858 if gp != nil && gp != me {
859 print("\n")
860 goroutineheader(gp)
861 traceback(^uintptr(0), ^uintptr(0), 0, gp)
862 }
863
864 lock(&allglock)
865 for _, gp := range allgs {
866 if gp == me || gp == g.m.curg || readgstatus(gp) == _Gdead || isSystemGoroutine(gp) && level < 2 {
867 continue
868 }
869 print("\n")
870 goroutineheader(gp)
871
872
873
874
875 if gp.m != g.m && readgstatus(gp)&^_Gscan == _Grunning {
876 print("\tgoroutine running on other thread; stack unavailable\n")
877 printcreatedby(gp)
878 } else {
879 traceback(^uintptr(0), ^uintptr(0), 0, gp)
880 }
881 }
882 unlock(&allglock)
883 }
884
885
886
887
888 func tracebackHexdump(stk stack, frame *stkframe, bad uintptr) {
889 const expand = 32 * sys.PtrSize
890 const maxExpand = 256 * sys.PtrSize
891
892 lo, hi := frame.sp, frame.sp
893
894 if frame.fp != 0 && frame.fp < lo {
895 lo = frame.fp
896 }
897 if frame.fp != 0 && frame.fp > hi {
898 hi = frame.fp
899 }
900
901 lo, hi = lo-expand, hi+expand
902
903 if lo < frame.sp-maxExpand {
904 lo = frame.sp - maxExpand
905 }
906 if hi > frame.sp+maxExpand {
907 hi = frame.sp + maxExpand
908 }
909
910 if lo < stk.lo {
911 lo = stk.lo
912 }
913 if hi > stk.hi {
914 hi = stk.hi
915 }
916
917
918 print("stack: frame={sp:", hex(frame.sp), ", fp:", hex(frame.fp), "} stack=[", hex(stk.lo), ",", hex(stk.hi), ")\n")
919 hexdumpWords(lo, hi, func(p uintptr) byte {
920 switch p {
921 case frame.fp:
922 return '>'
923 case frame.sp:
924 return '<'
925 case bad:
926 return '!'
927 }
928 return 0
929 })
930 }
931
932
933 func topofstack(f funcInfo, g0 bool) bool {
934 pc := f.entry
935 return pc == goexitPC ||
936 pc == mstartPC ||
937 pc == mcallPC ||
938 pc == morestackPC ||
939 pc == rt0_goPC ||
940 externalthreadhandlerp != 0 && pc == externalthreadhandlerp ||
941
942
943
944
945
946 (g0 && pc == asmcgocallPC)
947 }
948
949
950
951 func isSystemGoroutine(gp *g) bool {
952 pc := gp.startpc
953 return pc == runfinqPC && !fingRunning ||
954 pc == bgsweepPC ||
955 pc == forcegchelperPC ||
956 pc == timerprocPC ||
957 pc == gcBgMarkWorkerPC
958 }
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
1109
1110
1111
1112
1113
1114 func SetCgoTraceback(version int, traceback, context, symbolizer unsafe.Pointer) {
1115 if version != 0 {
1116 panic("unsupported version")
1117 }
1118
1119 if cgoTraceback != nil && cgoTraceback != traceback ||
1120 cgoContext != nil && cgoContext != context ||
1121 cgoSymbolizer != nil && cgoSymbolizer != symbolizer {
1122 panic("call SetCgoTraceback only once")
1123 }
1124
1125 cgoTraceback = traceback
1126 cgoContext = context
1127 cgoSymbolizer = symbolizer
1128
1129
1130
1131 if _cgo_set_context_function != nil {
1132 cgocall(_cgo_set_context_function, context)
1133 }
1134 }
1135
1136 var cgoTraceback unsafe.Pointer
1137 var cgoContext unsafe.Pointer
1138 var cgoSymbolizer unsafe.Pointer
1139
1140
1141 type cgoTracebackArg struct {
1142 context uintptr
1143 sigContext uintptr
1144 buf *uintptr
1145 max uintptr
1146 }
1147
1148
1149 type cgoContextArg struct {
1150 context uintptr
1151 }
1152
1153
1154 type cgoSymbolizerArg struct {
1155 pc uintptr
1156 file *byte
1157 lineno uintptr
1158 funcName *byte
1159 entry uintptr
1160 more uintptr
1161 data uintptr
1162 }
1163
1164
1165 func printCgoTraceback(callers *cgoCallers) {
1166 if cgoSymbolizer == nil {
1167 for _, c := range callers {
1168 if c == 0 {
1169 break
1170 }
1171 print("non-Go function at pc=", hex(c), "\n")
1172 }
1173 return
1174 }
1175
1176 var arg cgoSymbolizerArg
1177 for _, c := range callers {
1178 if c == 0 {
1179 break
1180 }
1181 printOneCgoTraceback(c, 0x7fffffff, &arg)
1182 }
1183 arg.pc = 0
1184 callCgoSymbolizer(&arg)
1185 }
1186
1187
1188
1189
1190 func printOneCgoTraceback(pc uintptr, max int, arg *cgoSymbolizerArg) int {
1191 c := 0
1192 arg.pc = pc
1193 for {
1194 if c > max {
1195 break
1196 }
1197 callCgoSymbolizer(arg)
1198 if arg.funcName != nil {
1199
1200
1201
1202 println(gostringnocopy(arg.funcName))
1203 } else {
1204 println("non-Go function")
1205 }
1206 print("\t")
1207 if arg.file != nil {
1208 print(gostringnocopy(arg.file), ":", arg.lineno, " ")
1209 }
1210 print("pc=", hex(pc), "\n")
1211 c++
1212 if arg.more == 0 {
1213 break
1214 }
1215 }
1216 return c
1217 }
1218
1219
1220 func callCgoSymbolizer(arg *cgoSymbolizerArg) {
1221 call := cgocall
1222 if panicking > 0 || getg().m.curg != getg() {
1223
1224
1225 call = asmcgocall
1226 }
1227 if msanenabled {
1228 msanwrite(unsafe.Pointer(arg), unsafe.Sizeof(cgoSymbolizerArg{}))
1229 }
1230 call(cgoSymbolizer, noescape(unsafe.Pointer(arg)))
1231 }
1232
1233
1234 func cgoContextPCs(ctxt uintptr, buf []uintptr) {
1235 if cgoTraceback == nil {
1236 return
1237 }
1238 call := cgocall
1239 if panicking > 0 || getg().m.curg != getg() {
1240
1241
1242 call = asmcgocall
1243 }
1244 arg := cgoTracebackArg{
1245 context: ctxt,
1246 buf: (*uintptr)(noescape(unsafe.Pointer(&buf[0]))),
1247 max: uintptr(len(buf)),
1248 }
1249 if msanenabled {
1250 msanwrite(unsafe.Pointer(&arg), unsafe.Sizeof(arg))
1251 }
1252 call(cgoTraceback, noescape(unsafe.Pointer(&arg)))
1253 }
1254
View as plain text