diff options
| -rw-r--r-- | .golangci.yml | 5 | ||||
| -rw-r--r-- | pkg/report/bsd.go | 136 | ||||
| -rw-r--r-- | pkg/report/bsd_test.go | 77 | ||||
| -rw-r--r-- | pkg/report/netbsd.go | 133 | ||||
| -rw-r--r-- | pkg/report/netbsd_test.go | 66 | ||||
| -rw-r--r-- | pkg/report/openbsd.go | 122 | ||||
| -rw-r--r-- | pkg/report/openbsd_test.go | 66 |
7 files changed, 226 insertions, 379 deletions
diff --git a/.golangci.yml b/.golangci.yml index baddf8c2c..010e10490 100644 --- a/.golangci.yml +++ b/.golangci.yml @@ -74,7 +74,6 @@ linters-settings: # TODO: consider reducing this value. min-complexity: 24 dupl: - # TODO: consider reducing this value. threshold: 60 goconst: min-len: 7 @@ -107,10 +106,6 @@ issues: text: "don't use ALL_CAPS in Go names|should not use ALL_CAPS in Go names" - path: (prog/.*) text: "methods on the same type should have the same receiver name" - # TODO: this is bad, need to fix and remove the suppression. - - path: (pkg/report/(net|open)bsd.*) - linters: - - dupl - path: (dashboard/app/.*_test\.go) linters: - dupl diff --git a/pkg/report/bsd.go b/pkg/report/bsd.go new file mode 100644 index 000000000..369ffcab9 --- /dev/null +++ b/pkg/report/bsd.go @@ -0,0 +1,136 @@ +// Copyright 2017 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 ( + "bufio" + "bytes" + "fmt" + "path/filepath" + "regexp" + "strconv" + "strings" + + "github.com/google/syzkaller/pkg/symbolizer" +) + +type bsd struct { + *config + oopses []*oops + symbolizeRes []*regexp.Regexp + kernelObject string + symbols map[string][]symbolizer.Symbol +} + +func ctorBSD(cfg *config, oopses []*oops, symbolizeRes []*regexp.Regexp) (Reporter, error) { + var symbols map[string][]symbolizer.Symbol + kernelObject := "" + if cfg.kernelObj != "" { + kernelObject = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) + var err error + symbols, err = symbolizer.ReadTextSymbols(kernelObject) + if err != nil { + return nil, err + } + } + ctx := &bsd{ + config: cfg, + oopses: oopses, + symbolizeRes: symbolizeRes, + kernelObject: kernelObject, + symbols: symbols, + } + return ctx, nil +} + +func (ctx *bsd) ContainsCrash(output []byte) bool { + return containsCrash(output, ctx.oopses, ctx.ignores) +} + +func (ctx *bsd) Parse(output []byte) *Report { + stripped := bytes.Replace(output, []byte{'\r', '\n'}, []byte{'\n'}, -1) + stripped = bytes.Replace(stripped, []byte{'\n', '\r'}, []byte{'\n'}, -1) + for len(stripped) != 0 && stripped[0] == '\r' { + stripped = stripped[1:] + } + rep := simpleLineParser(stripped, ctx.oopses, nil, ctx.ignores) + if rep == nil { + return nil + } + rep.Output = output + return rep +} + +func (ctx *bsd) 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 *bsd) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error), + line []byte) []byte { + var match []int + // Check whether the line corresponds to the any of the parts that require symbolization. + for _, re := range ctx.symbolizeRes { + match = re.FindSubmatchIndex(line) + if match != nil { + break + } + } + if match == nil { + return line + } + // First part of the matched regex contains the function name. + // Second part contains the offset. + fn := line[match[2]:match[3]] + off, err := strconv.ParseUint(string(line[match[4]:match[5]]), 16, 64) + if err != nil { + return line + } + + // Get the symbol from the list of symbols generated using the kernel object and addr2line. + symb := ctx.symbols[string(fn)] + if len(symb) == 0 { + return line + } + fnStart := (0xffffffff << 32) | symb[0].Addr + + // Retrieve the frames for the corresponding offset of the function. + frames, err := symbFunc(ctx.kernelObject, fnStart+off) + if err != nil || len(frames) == 0 { + return line + } + var symbolized []byte + // Go through each of the frames and add the corresponding file names and line numbers. + for _, frame := range frames { + file := frame.File + file = strings.TrimPrefix(file, ctx.kernelBuildSrc) + 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 { + // If frames are marked inline then show that in the report also. + 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 +} diff --git a/pkg/report/bsd_test.go b/pkg/report/bsd_test.go new file mode 100644 index 000000000..1fd721d3f --- /dev/null +++ b/pkg/report/bsd_test.go @@ -0,0 +1,77 @@ +// 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" +) + +type symbolizeLineTest struct { + line string + result string +} + +func testSymbolizeLine(t *testing.T, ctor fn, tests []symbolizeLineTest) { + 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{ + { + Func: "closef", + File: "/bsd/src/kern_descrip.c", + Line: 1241, + }, + }, nil + case 0x81237542: + return []symbolizer.Frame{ + { + Func: "sleep_finish_timeout", + File: "/bsd/src/kern_synch.c", + Line: 336, + Inline: true, + }, + { + Func: "sleep_finish_all", + File: "/bsd/src/kern_synch.c", + Line: 157, + }, + }, nil + default: + return nil, fmt.Errorf("unknown pc 0x%x", pc) + } + } + reporter, _, err := ctor(&config{ + kernelSrc: "/bsd/src2", + kernelBuildSrc: "/bsd/src", + }) + if err != nil { + t.Fatal(err) + } + bsd := reporter.(*bsd) + bsd.symbols = symbols + bsd.kernelObject = "bsd.gdb" + for i, test := range tests { + t.Run(fmt.Sprint(i), func(t *testing.T) { + result := bsd.symbolizeLine(symb, []byte(test.line)) + if test.result != string(result) { + t.Errorf("want %q\n\t get %q", test.result, string(result)) + } + }) + } +} diff --git a/pkg/report/netbsd.go b/pkg/report/netbsd.go index cb5fb1c56..9eea6c2b2 100644 --- a/pkg/report/netbsd.go +++ b/pkg/report/netbsd.go @@ -4,144 +4,19 @@ package report import ( - "bufio" - "bytes" - "fmt" - "path/filepath" "regexp" - "strconv" - "strings" - - "github.com/google/syzkaller/pkg/symbolizer" ) -type netbsd struct { - *config - kernelObject string - symbols map[string][]symbolizer.Symbol -} - -var ( - netbsdSymbolizeRe = []*regexp.Regexp{ +func ctorNetbsd(cfg *config) (Reporter, []string, error) { + symbolizeRes := []*regexp.Regexp{ // stack regexp.MustCompile(` at netbsd:([A-Za-z0-9_]+)\+0x([0-9a-f]+)`), // witness regexp.MustCompile(`#[0-9]+ +([A-Za-z0-9_]+)\+0x([0-9a-f]+)`), } -) - -func ctorNetbsd(cfg *config) (Reporter, []string, error) { - var symbols map[string][]symbolizer.Symbol cfg.ignores = append(cfg.ignores, regexp.MustCompile("event_init: unable to initialize")) // postfix output - kernelObject := "" - if cfg.kernelObj != "" { - kernelObject = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) - var err error - symbols, err = symbolizer.ReadTextSymbols(kernelObject) - if err != nil { - return nil, nil, err - } - } - ctx := &netbsd{ - config: cfg, - kernelObject: kernelObject, - symbols: symbols, - } - return ctx, nil, nil -} - -func (ctx *netbsd) ContainsCrash(output []byte) bool { - return containsCrash(output, netbsdOopses, ctx.ignores) -} - -func (ctx *netbsd) Parse(output []byte) *Report { - stripped := bytes.Replace(output, []byte{'\r', '\n'}, []byte{'\n'}, -1) - stripped = bytes.Replace(stripped, []byte{'\n', '\r'}, []byte{'\n'}, -1) - for len(stripped) != 0 && stripped[0] == '\r' { - stripped = stripped[1:] - } - rep := simpleLineParser(stripped, netbsdOopses, nil, ctx.ignores) - if rep == nil { - return nil - } - rep.Output = output - return rep -} - -func (ctx *netbsd) 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 *netbsd) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error), - line []byte) []byte { - var match []int - // Check whether the line corresponds to the any of the parts that - // require symbolization. - for _, re := range netbsdSymbolizeRe { - match = re.FindSubmatchIndex(line) - if match != nil { - break - } - } - if match == nil { - return line - } - // First part of the matched regex contains the function name - // Second part contains the offset - fn := line[match[2]:match[3]] - off, err := strconv.ParseUint(string(line[match[4]:match[5]]), 16, 64) - if err != nil { - return line - } - - // Get the symbol from the list of symbols generated using - // the kernel object and addr2line - symb := ctx.symbols[string(fn)] - if len(symb) == 0 { - return line - } - fnStart := (0xffffffff << 32) | symb[0].Addr - - // Retrieve the frames for the corresponding offset of the function - frames, err := symbFunc(ctx.kernelObject, fnStart+off) - if err != nil || len(frames) == 0 { - return line - } - var symbolized []byte - // Go through each of the frames and add the corresponding file names - // and line numbers. - for _, frame := range frames { - file := frame.File - file = strings.TrimPrefix(file, ctx.kernelBuildSrc) - 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 { - // If frames are marked inline then show that in the report also - 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 + ctx, err := ctorBSD(cfg, netbsdOopses, symbolizeRes) + return ctx, nil, err } // nolint: lll diff --git a/pkg/report/netbsd_test.go b/pkg/report/netbsd_test.go index 3fb93ceb9..24c144ac0 100644 --- a/pkg/report/netbsd_test.go +++ b/pkg/report/netbsd_test.go @@ -4,17 +4,11 @@ package report import ( - "fmt" "testing" - - "github.com/google/syzkaller/pkg/symbolizer" ) func TestNetbsdSymbolizeLine(t *testing.T) { - tests := []struct { - line string - result string - }{ + tests := []symbolizeLineTest{ // Normal symbolization. { "closef(ffffffff,ffffffff) at netbsd:closef+0xaf\n", @@ -41,61 +35,5 @@ func TestNetbsdSymbolizeLine(t *testing.T) { "#10 closef+0xaf kern_descrip.c:1241\n", }, } - 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 != "netbsd.gdb" { - return nil, fmt.Errorf("unknown pc 0x%x", pc) - } - - switch pc & 0xffffffff { - case 0x8150894f: - return []symbolizer.Frame{ - { - Func: "closef", - File: "/netbsd/src/kern_descrip.c", - Line: 1241, - }, - }, nil - case 0x81237542: - return []symbolizer.Frame{ - { - Func: "sleep_finish_timeout", - File: "/netbsd/src/kern_synch.c", - Line: 336, - Inline: true, - }, - { - Func: "sleep_finish_all", - File: "/netbsd/src/kern_synch.c", - Line: 157, - }, - }, nil - default: - return nil, fmt.Errorf("unknown pc 0x%x", pc) - } - } - nbsd := netbsd{ - config: &config{ - kernelSrc: "/netbsd/src2", - kernelBuildSrc: "/netbsd/src", - kernelObj: "/netbsd/src/obj/sys/arch/amd64/compile/GENERIC", - }, - kernelObject: "netbsd.gdb", - symbols: symbols, - } - for i, test := range tests { - t.Run(fmt.Sprint(i), func(t *testing.T) { - result := nbsd.symbolizeLine(symb, []byte(test.line)) - if test.result != string(result) { - t.Errorf("want %q\n\t get %q", test.result, string(result)) - } - }) - } + testSymbolizeLine(t, ctorNetbsd, tests) } diff --git a/pkg/report/openbsd.go b/pkg/report/openbsd.go index 8d29dba10..9373b607b 100644 --- a/pkg/report/openbsd.go +++ b/pkg/report/openbsd.go @@ -4,47 +4,19 @@ package report import ( - "bufio" - "bytes" - "fmt" - "path/filepath" "regexp" - "strconv" - "strings" - - "github.com/google/syzkaller/pkg/symbolizer" ) -type openbsd struct { - *config - kernelObject string - symbols map[string][]symbolizer.Symbol -} - -var ( - openbsdSymbolizeRe = []*regexp.Regexp{ +func ctorOpenbsd(cfg *config) (Reporter, []string, error) { + symbolizeRes := []*regexp.Regexp{ // stack regexp.MustCompile(` at ([A-Za-z0-9_]+)\+0x([0-9a-f]+)`), // witness regexp.MustCompile(`#[0-9]+ +([A-Za-z0-9_]+)\+0x([0-9a-f]+)`), } -) - -func ctorOpenbsd(cfg *config) (Reporter, []string, error) { - var symbols map[string][]symbolizer.Symbol - kernelObject := "" - if cfg.kernelObj != "" { - kernelObject = filepath.Join(cfg.kernelObj, cfg.target.KernelObject) - var err error - symbols, err = symbolizer.ReadTextSymbols(kernelObject) - if err != nil { - return nil, nil, err - } - } - ctx := &openbsd{ - config: cfg, - kernelObject: kernelObject, - symbols: symbols, + ctx, err := ctorBSD(cfg, openbsdOopses, symbolizeRes) + if err != nil { + return nil, nil, err } suppressions := []string{ "panic: fifo_badop called", @@ -52,90 +24,6 @@ func ctorOpenbsd(cfg *config) (Reporter, []string, error) { return ctx, suppressions, nil } -func (ctx *openbsd) ContainsCrash(output []byte) bool { - return containsCrash(output, openbsdOopses, ctx.ignores) -} - -func (ctx *openbsd) Parse(output []byte) *Report { - stripped := bytes.Replace(output, []byte{'\r', '\n'}, []byte{'\n'}, -1) - stripped = bytes.Replace(stripped, []byte{'\n', '\r'}, []byte{'\n'}, -1) - for len(stripped) != 0 && stripped[0] == '\r' { - stripped = stripped[1:] - } - rep := simpleLineParser(stripped, openbsdOopses, nil, ctx.ignores) - if rep == nil { - return nil - } - rep.Output = output - return rep -} - -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 { - var match []int - for _, re := range openbsdSymbolizeRe { - match = re.FindSubmatchIndex(line) - if match != nil { - break - } - } - 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.kernelBuildSrc) - 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 -} - var openbsdOopses = append([]*oops{ { []byte("cleaned vnode"), diff --git a/pkg/report/openbsd_test.go b/pkg/report/openbsd_test.go index af9b93b7a..ec96c4ef3 100644 --- a/pkg/report/openbsd_test.go +++ b/pkg/report/openbsd_test.go @@ -4,17 +4,11 @@ package report import ( - "fmt" "testing" - - "github.com/google/syzkaller/pkg/symbolizer" ) func TestOpenbsdSymbolizeLine(t *testing.T) { - tests := []struct { - line string - result string - }{ + tests := []symbolizeLineTest{ // Normal symbolization. { "closef(ffffffff,ffffffff) at closef+0xaf\n", @@ -41,61 +35,5 @@ func TestOpenbsdSymbolizeLine(t *testing.T) { "#10 closef+0xaf kern_descrip.c:1241\n", }, } - 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{ - config: &config{ - kernelSrc: "/usr/src2", - kernelBuildSrc: "/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)) - } - }) - } + testSymbolizeLine(t, ctorOpenbsd, tests) } |
