Skip to content
This repository has been archived by the owner on Dec 1, 2021. It is now read-only.

Return errors.Frame to a uintptr #193

Merged
merged 2 commits into from
Jan 9, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions format_test.go
Expand Up @@ -385,6 +385,7 @@ func TestFormatWrappedNew(t *testing.T) {
}

func testFormatRegexp(t *testing.T, n int, arg interface{}, format, want string) {
t.Helper()
got := fmt.Sprintf(format, arg)
gotLines := strings.SplitN(got, "\n", -1)
wantLines := strings.SplitN(want, "\n", -1)
Expand Down
85 changes: 51 additions & 34 deletions stack.go
Expand Up @@ -11,7 +11,42 @@ import (
)

// Frame represents a program counter inside a stack frame.
type Frame runtime.Frame
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 }

// file returns the full path to the file that contains the
// function for this Frame's pc.
func (f Frame) file() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
file, _ := fn.FileLine(f.pc())
return file
}

// line returns the line number of source code of the
// function for this Frame's pc.
func (f Frame) line() int {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return 0
}
_, line := fn.FileLine(f.pc())
return line
}

// name returns the name of this function, if known.
func (f Frame) name() string {
fn := runtime.FuncForPC(f.pc())
if fn == nil {
return "unknown"
}
return fn.Name()
}

// Format formats the frame according to the fmt.Formatter interface.
//
Expand All @@ -35,25 +70,16 @@ func (f Frame) format(w io.Writer, s fmt.State, verb rune) {
case 's':
switch {
case s.Flag('+'):
if f.Function == "" {
io.WriteString(w, "unknown")
} else {
io.WriteString(w, f.Function)
io.WriteString(w, "\n\t")
io.WriteString(w, f.File)
}
io.WriteString(w, f.name())
io.WriteString(w, "\n\t")
io.WriteString(w, f.file())
default:
file := f.File
if file == "" {
file = "unknown"
}
io.WriteString(w, path.Base(file))
io.WriteString(w, path.Base(f.file()))
}
case 'd':
io.WriteString(w, strconv.Itoa(f.Line))
io.WriteString(w, strconv.Itoa(f.line()))
case 'n':
name := f.Function
io.WriteString(s, funcname(name))
io.WriteString(w, funcname(f.name()))
case 'v':
f.format(w, s, 's')
io.WriteString(w, ":")
Expand All @@ -79,9 +105,9 @@ func (st StackTrace) Format(s fmt.State, verb rune) {
switch {
case s.Flag('+'):
b.Grow(len(st) * stackMinLen)
for _, fr := range st {
for _, f := range st {
b.WriteByte('\n')
fr.format(&b, s, verb)
f.format(&b, s, verb)
}
case s.Flag('#'):
fmt.Fprintf(&b, "%#v", []Frame(st))
Expand Down Expand Up @@ -125,29 +151,20 @@ func (s *stack) Format(st fmt.State, verb rune) {
case 'v':
switch {
case st.Flag('+'):
frames := runtime.CallersFrames(*s)
for {
frame, more := frames.Next()
fmt.Fprintf(st, "\n%+v", Frame(frame))
if !more {
break
}
for _, pc := range *s {
f := Frame(pc)
fmt.Fprintf(st, "\n%+v", f)
}
}
}
}

func (s *stack) StackTrace() StackTrace {
var st []Frame
frames := runtime.CallersFrames(*s)
for {
frame, more := frames.Next()
st = append(st, Frame(frame))
if !more {
break
}
f := make([]Frame, len(*s))
for i := 0; i < len(f); i++ {
f[i] = Frame((*s)[i])
}
return st
return f
}

func callers() *stack {
Expand Down
12 changes: 6 additions & 6 deletions stack_test.go
Expand Up @@ -35,19 +35,19 @@ func TestFrameFormat(t *testing.T) {
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go",
}, {
Frame{},
0,
"%s",
"unknown",
}, {
Frame{},
0,
"%+s",
"unknown",
}, {
initpc,
"%d",
"9",
}, {
Frame{},
0,
"%d",
"0",
}, {
Expand All @@ -69,7 +69,7 @@ func TestFrameFormat(t *testing.T) {
"%n",
"X.val",
}, {
Frame{},
0,
"%n",
"",
}, {
Expand All @@ -82,7 +82,7 @@ func TestFrameFormat(t *testing.T) {
"github.com/pkg/errors.init\n" +
"\t.+/github.com/pkg/errors/stack_test.go:9",
}, {
Frame{},
0,
"%v",
"unknown:0",
}}
Expand Down Expand Up @@ -246,7 +246,7 @@ func caller() Frame {
n := runtime.Callers(2, pcs[:])
frames := runtime.CallersFrames(pcs[:n])
frame, _ := frames.Next()
return Frame(frame)
return Frame(frame.PC)
}

//go:noinline
Expand Down