aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorAnton Lindqvist <anton@basename.se>2018-12-08 11:03:31 +0100
committerDmitry Vyukov <dvyukov@google.com>2018-12-08 18:59:10 +0100
commit33508266251f6db13ef34741e36b1dce2c9e1b49 (patch)
tree1ad2b075084b644277307831b2f0e39564c2279b /pkg
parent977de94f014bc4c0ebd2acc2c0177d196f6cd730 (diff)
pkg/report: add initial symbolize suppport to OpenBSD
Diffstat (limited to 'pkg')
-rw-r--r--pkg/report/openbsd.go91
-rw-r--r--pkg/report/openbsd_test.go89
2 files changed, 174 insertions, 6 deletions
diff --git a/pkg/report/openbsd.go b/pkg/report/openbsd.go
index c87a1dc10..bdf525f03 100644
--- a/pkg/report/openbsd.go
+++ b/pkg/report/openbsd.go
@@ -6,23 +6,46 @@ package report
import (
"bufio"
"bytes"
+ "fmt"
+ "path/filepath"
"regexp"
+ "strconv"
+ "strings"
+ "github.com/google/syzkaller/pkg/symbolizer"
"github.com/google/syzkaller/sys/targets"
)
type openbsd struct {
- kernelSrc string
- kernelObj string
- ignores []*regexp.Regexp
+ kernelSrc string
+ kernelObj string
+ kernelObject string
+ symbols map[string][]symbolizer.Symbol
+ ignores []*regexp.Regexp
}
+var (
+ openbsdSymbolizeRe = regexp.MustCompile(` at ([A-Za-z0-9_]+)\+0x([0-9a-f]+)`)
+)
+
func ctorOpenbsd(target *targets.Target, kernelSrc, kernelObj string,
ignores []*regexp.Regexp) (Reporter, []string, error) {
+ var symbols map[string][]symbolizer.Symbol
+ kernelObject := ""
+ if kernelObj != "" {
+ kernelObject = filepath.Join(kernelObj, target.KernelObject)
+ var err error
+ symbols, err = symbolizer.ReadSymbols(kernelObject)
+ if err != nil {
+ return nil, nil, err
+ }
+ }
ctx := &openbsd{
- kernelSrc: kernelSrc,
- kernelObj: kernelObj,
- ignores: ignores,
+ kernelSrc: kernelSrc,
+ kernelObj: kernelObj,
+ kernelObject: kernelObject,
+ symbols: symbols,
+ ignores: ignores,
}
return ctx, nil, nil
}
@@ -45,9 +68,65 @@ func (ctx *openbsd) Parse(output []byte) *Report {
}
func (ctx *openbsd) Symbolize(rep *Report) error {
+ symb := symbolizer.NewSymbolizer()
+ defer symb.Close()
+ var symbolized []byte
+ s := bufio.NewScanner(bytes.NewReader(rep.Report))
+ prefix := rep.reportPrefixLen
+ for s.Scan() {
+ line := append([]byte{}, s.Bytes()...)
+ line = append(line, '\n')
+ newLine := ctx.symbolizeLine(symb.Symbolize, line)
+ if prefix > len(symbolized) {
+ prefix += len(newLine) - len(line)
+ }
+ symbolized = append(symbolized, newLine...)
+ }
+ rep.Report = symbolized
+ rep.reportPrefixLen = prefix
return nil
}
+func (ctx *openbsd) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error),
+ line []byte) []byte {
+ match := openbsdSymbolizeRe.FindSubmatchIndex(line)
+ if match == nil {
+ return line
+ }
+ fn := line[match[2]:match[3]]
+ off, err := strconv.ParseUint(string(line[match[4]:match[5]]), 16, 64)
+ if err != nil {
+ return line
+ }
+
+ symb := ctx.symbols[string(fn)]
+ if len(symb) == 0 {
+ return line
+ }
+ fnStart := (0xffffffff << 32) | symb[0].Addr
+
+ frames, err := symbFunc(ctx.kernelObject, fnStart+off)
+ if err != nil || len(frames) == 0 {
+ return line
+ }
+ var symbolized []byte
+ for _, frame := range frames {
+ file := frame.File
+ file = strings.TrimPrefix(file, ctx.kernelSrc)
+ file = strings.TrimPrefix(file, "/")
+ info := fmt.Sprintf(" %v:%v", file, frame.Line)
+ modified := append([]byte{}, line...)
+ modified = replace(modified, match[5], match[5], []byte(info))
+ if frame.Inline {
+ end := match[5] + len(info)
+ modified = replace(modified, end, end, []byte(" [inline]"))
+ modified = replace(modified, match[5], match[5], []byte(" "+frame.Func))
+ }
+ symbolized = append(symbolized, modified...)
+ }
+ return symbolized
+}
+
func (ctx *openbsd) shortenReport(report []byte) []byte {
out := new(bytes.Buffer)
for s := bufio.NewScanner(bytes.NewReader(report)); s.Scan(); {
diff --git a/pkg/report/openbsd_test.go b/pkg/report/openbsd_test.go
new file mode 100644
index 000000000..f4adaac57
--- /dev/null
+++ b/pkg/report/openbsd_test.go
@@ -0,0 +1,89 @@
+// Copyright 2018 syzkaller project authors. All rights reserved.
+// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
+
+package report
+
+import (
+ "fmt"
+ "testing"
+
+ "github.com/google/syzkaller/pkg/symbolizer"
+)
+
+func TestOpenbsdSymbolizeLine(t *testing.T) {
+ tests := []struct {
+ line string
+ result string
+ }{
+ // Normal symbolization.
+ {
+ "closef(ffffffff,ffffffff) at closef+0xaf\n",
+ "closef(ffffffff,ffffffff) at closef+0xaf kern_descrip.c:1241\n",
+ },
+ // Inlined frames.
+ {
+ "sleep_finish_all(ffffffff,32) at sleep_finish_all+0x22\n",
+ "sleep_finish_all(ffffffff,32) at sleep_finish_all+0x22 sleep_finish_timeout kern_synch.c:336 [inline]\n" +
+ "sleep_finish_all(ffffffff,32) at sleep_finish_all+0x22 kern_synch.c:157\n",
+ },
+ // Missing symbol.
+ {
+ "foo(ffffffff,ffffffff) at foo+0x1e",
+ "foo(ffffffff,ffffffff) at foo+0x1e",
+ },
+ }
+ symbols := map[string][]symbolizer.Symbol{
+ "closef": {
+ {Addr: 0x815088a0, Size: 0x12f},
+ },
+ "sleep_finish_all": {
+ {Addr: 0x81237520, Size: 0x173},
+ },
+ }
+ symb := func(bin string, pc uint64) ([]symbolizer.Frame, error) {
+ if bin != "bsd.gdb" {
+ return nil, fmt.Errorf("unknown pc 0x%x", pc)
+ }
+
+ switch pc & 0xffffffff {
+ case 0x8150894f:
+ return []symbolizer.Frame{
+ {
+ File: "/usr/src/kern_descrip.c",
+ Line: 1241,
+ Func: "closef",
+ },
+ }, nil
+ case 0x81237542:
+ return []symbolizer.Frame{
+ {
+ Func: "sleep_finish_timeout",
+ File: "/usr/src/kern_synch.c",
+ Line: 336,
+ Inline: true,
+ },
+ {
+ Func: "sleep_finish_all",
+ File: "/usr/src/kern_synch.c",
+ Line: 157,
+ },
+ }, nil
+ default:
+ return nil, fmt.Errorf("unknown pc 0x%x", pc)
+ }
+ }
+ obsd := openbsd{
+ kernelSrc: "/usr/src",
+ kernelObj: "/usr/src/sys/arch/amd64/compile/SYZKALLER/obj",
+ kernelObject: "bsd.gdb",
+ symbols: symbols,
+ }
+ for i, test := range tests {
+ t.Run(fmt.Sprint(i), func(t *testing.T) {
+ result := obsd.symbolizeLine(symb, []byte(test.line))
+ if test.result != string(result) {
+ t.Errorf("want %q\n\t get %q", test.result, string(result))
+ }
+ })
+ }
+}