diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2020-06-06 09:15:20 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2020-06-07 10:41:01 +0200 |
| commit | cdf1aa4dc338ddd37917942e7d6b992f4e079a00 (patch) | |
| tree | ca0f1aec1472d7871b6b2995f70359cfbd8a07af /pkg/report/bsd.go | |
| parent | 21b79583f15c7626926fc9f4fb528147a59ea3c5 (diff) | |
pkg/report: deduplicate code across netbsd and openbsd
Diffstat (limited to 'pkg/report/bsd.go')
| -rw-r--r-- | pkg/report/bsd.go | 136 |
1 files changed, 136 insertions, 0 deletions
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 +} |
