@@ -45,6 +45,10 @@ const (
45
45
// unwindTrap indicates that the initial PC and SP are from a trap, not a
46
46
// return PC from a call.
47
47
//
48
+ // The unwindTrap flag is updated during unwinding. If set, frame.pc is the
49
+ // address of a faulting instruction instead of the return address of a
50
+ // call. It also means the liveness at pc may not be known.
51
+ //
48
52
// TODO: Distinguish frame.continpc, which is really the stack map PC, from
49
53
// the actual continuation PC, which is computed differently depending on
50
54
// this flag and a few other things.
@@ -461,6 +465,11 @@ func (u *unwinder) next() {
461
465
}
462
466
463
467
injectedCall := f .funcID == funcID_sigpanic || f .funcID == funcID_asyncPreempt || f .funcID == funcID_debugCallV2
468
+ if injectedCall {
469
+ u .flags |= unwindTrap
470
+ } else {
471
+ u .flags &^= unwindTrap
472
+ }
464
473
465
474
// Unwind to next frame.
466
475
u .calleeFuncID = f .funcID
@@ -541,6 +550,25 @@ func (u *unwinder) finishInternal() {
541
550
}
542
551
}
543
552
553
+ // symPC returns the PC that should be used for symbolizing the current frame.
554
+ // Specifically, this is the PC of the last instruction executed in this frame.
555
+ //
556
+ // If this frame did a normal call, then frame.pc is a return PC, so this will
557
+ // return frame.pc-1, which points into the CALL instruction. If the frame was
558
+ // interrupted by a signal (e.g., profiler, segv, etc) then frame.pc is for the
559
+ // trapped instruction, so this returns frame.pc. See issue #34123. Finally,
560
+ // frame.pc can be at function entry when the frame is initialized without
561
+ // actually running code, like in runtime.mstart, in which case this returns
562
+ // frame.pc because that's the best we can do.
563
+ func (u * unwinder ) symPC () uintptr {
564
+ if u .flags & unwindTrap == 0 && u .frame .pc > u .frame .fn .entry () {
565
+ // Regular call.
566
+ return u .frame .pc - 1
567
+ }
568
+ // Trapping instruction or we're at the function entry point.
569
+ return u .frame .pc
570
+ }
571
+
544
572
// Generic traceback. Handles runtime stack prints (pcbuf == nil),
545
573
// and the runtime.Callers function (pcbuf != nil).
546
574
// A little clunky to merge these, but avoids
@@ -581,24 +609,9 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
581
609
frame := & u .frame
582
610
f := frame .fn
583
611
584
- // Backup to the CALL instruction to read inlining info
585
- //
586
- // Normally, pc is a return address. In that case, we want to look up
587
- // file/line information using pc-1, because that is the pc of the
588
- // call instruction (more precisely, the last byte of the call instruction).
589
- // When the pc is from a signal (e.g. profiler or segv) then pc is for
590
- // the trapped instruction, not a return address, so we use pc unchanged.
591
- // See issue 34123.
592
- // The pc can be at function entry when the frame is initialized without
593
- // actually running code, like runtime.mstart.
594
- callPC := frame .pc
595
- if (n > 0 || flags & _TraceTrap == 0 ) && frame .pc > f .entry () && u .calleeFuncID != funcID_sigpanic {
596
- callPC --
597
- }
598
-
599
612
if pcbuf != nil {
600
613
// TODO: Why does cache escape? (Same below)
601
- for iu , uf := newInlineUnwinder (f , callPC , noEscapePtr (& u .cache )); uf .valid (); uf = iu .next (uf ) {
614
+ for iu , uf := newInlineUnwinder (f , u . symPC () , noEscapePtr (& u .cache )); uf .valid (); uf = iu .next (uf ) {
602
615
sf := iu .srcFunc (uf )
603
616
if sf .funcID == funcID_wrapper && elideWrapperCalling (u .calleeFuncID ) {
604
617
// ignore wrappers
@@ -623,7 +636,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
623
636
// any frames. And don't elide wrappers that
624
637
// called panic rather than the wrapped
625
638
// function. Otherwise, leave them out.
626
- for iu , uf := newInlineUnwinder (f , callPC , noEscapePtr (& u .cache )); uf .valid (); uf = iu .next (uf ) {
639
+ for iu , uf := newInlineUnwinder (f , u . symPC () , noEscapePtr (& u .cache )); uf .valid (); uf = iu .next (uf ) {
627
640
sf := iu .srcFunc (uf )
628
641
if (flags & _TraceRuntimeFrames ) != 0 || showframe (sf , gp , nprint == 0 , u .calleeFuncID ) {
629
642
name := sf .name ()
@@ -640,7 +653,7 @@ func gentraceback(pc0, sp0, lr0 uintptr, gp *g, skip int, pcbuf *uintptr, max in
640
653
print ("..." )
641
654
} else {
642
655
argp := unsafe .Pointer (frame .argp )
643
- printArgs (f , argp , callPC )
656
+ printArgs (f , argp , u . symPC () )
644
657
}
645
658
print (")\n " )
646
659
print ("\t " , file , ":" , line )
0 commit comments