Why the Frame's value represents the program counter + 1 in the pc function

223 Views Asked by At

I am confused when studying the pkg/errors. In the file stack.go, we can see the comment about the struct Frame as below:

// Frame represents a program counter inside a stack frame.
// For historical reasons if Frame is interpreted as a uintptr
// its value represents the program counter + 1.
type Frame uintptr

// pc returns the program counter for this frame;
// multiple frames may have the same PC value.
func (f Frame) pc() uintptr { return uintptr(f) - 1 }

Could anyone tell me Why the pc function get the uintptr(f) - 1 as the program counter value. I write some code about the pc to test, I can get the right answer althought rewrite the pc function as below:

type Frame uintptr

func (f Frame) pc() uintptr { return uintptr(f) }

func (f Frame) line() int {
    fn := runtime.FuncForPC(f.pc())
    if fn == nil {
        return 0
    }
    _, line := fn.FileLine(f.pc())
    return line
}

func main() {

    var pc, _, line, _ = runtime.Caller(0)
    fmt.Printf("pc:%v, line:%v\n", pc, line)

    fmt.Println("-------------")

    frame := Frame(pc)
    line = frame.line()
    fmt.Printf("Frame:%v, line:%v\n", uintptr(frame), line)
}

The result of the code is :

pc:4779003, line:23
-------------
Frame:4779003, line:23
1

There are 1 best solutions below

2
On

https://github.com/golang/go/blob/897b3da2e079b9b940b309747305a5379fffa6ec/src/runtime/traceback.go#L339

// Normally, pc is a return address. In that case, we want to look up
// file/line information using pc-1, because that is the pc of the
// call instruction (more precisely, the last byte of the call instruction).
// Callers expect the pc buffer to contain return addresses and do the
// same -1 themselves, so we keep pc unchanged.
// When the pc is from a signal (e.g. profiler or segv) then we want
// to look up file/line information using pc, and we store pc+1 in the
// pc buffer so callers can unconditionally subtract 1 before looking up.
// See issue 34123.