diff options
| author | Anton Lindqvist <anton@basename.se> | 2018-12-08 11:03:31 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2018-12-08 18:59:10 +0100 |
| commit | 33508266251f6db13ef34741e36b1dce2c9e1b49 (patch) | |
| tree | 1ad2b075084b644277307831b2f0e39564c2279b /pkg | |
| parent | 977de94f014bc4c0ebd2acc2c0177d196f6cd730 (diff) | |
pkg/report: add initial symbolize suppport to OpenBSD
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/report/openbsd.go | 91 | ||||
| -rw-r--r-- | pkg/report/openbsd_test.go | 89 |
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)) + } + }) + } +} |
