| // 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 ( |
| "bufio" |
| "bytes" |
| "fmt" |
| "path/filepath" |
| "regexp" |
| "strconv" |
| "strings" |
| |
| "github.com/google/syzkaller/pkg/symbolizer" |
| ) |
| |
| type akaros struct { |
| ignores []*regexp.Regexp |
| objfile string |
| } |
| |
| func ctorAkaros(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) { |
| ctx := &akaros{ |
| ignores: ignores, |
| objfile: filepath.Join(kernelObj, "akaros-kernel-64b"), |
| } |
| return ctx, nil, nil |
| } |
| |
| func (ctx *akaros) ContainsCrash(output []byte) bool { |
| return containsCrash(output, akarosOopses, ctx.ignores) |
| } |
| |
| func (ctx *akaros) Parse(output []byte) *Report { |
| rep := simpleLineParser(output, akarosOopses, akarosStackParams, ctx.ignores) |
| if rep == nil { |
| return nil |
| } |
| rep.Report = ctx.minimizeReport(rep.Report) |
| return rep |
| } |
| |
| func (ctx *akaros) Symbolize(rep *Report) error { |
| symb := symbolizer.NewSymbolizer() |
| defer symb.Close() |
| var symbolized []byte |
| s := bufio.NewScanner(bytes.NewReader(rep.Report)) |
| for s.Scan() { |
| line := bytes.Trim(s.Bytes(), "\r") |
| line = ctx.symbolizeLine(symb.Symbolize, ctx.objfile, line) |
| symbolized = append(symbolized, line...) |
| symbolized = append(symbolized, '\n') |
| } |
| rep.Report = symbolized |
| return nil |
| } |
| |
| func (ctx *akaros) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error), |
| objfile string, line []byte) []byte { |
| match := akarosSymbolizeRe.FindSubmatchIndex(line) |
| if match == nil { |
| return line |
| } |
| addr, err := strconv.ParseUint(string(line[match[2]:match[3]]), 0, 64) |
| if err != nil { |
| return line |
| } |
| frames, err := symbFunc(objfile, addr-1) |
| if err != nil || len(frames) == 0 { |
| return line |
| } |
| var symbolized []byte |
| for i, frame := range frames { |
| if i != 0 { |
| symbolized = append(symbolized, '\n') |
| } |
| file := frame.File |
| if pos := strings.LastIndex(file, "/kern/"); pos != -1 { |
| file = file[pos+6:] |
| } |
| modified := append([]byte{}, line...) |
| modified = append(modified, fmt.Sprintf(" at %v:%v", file, frame.Line)...) |
| if frame.Inline { |
| modified = replace(modified, match[4], match[5], []byte(frame.Func)) |
| modified = replace(modified, match[2], match[3], []byte(" [inline] ")) |
| } |
| symbolized = append(symbolized, modified...) |
| } |
| return symbolized |
| } |
| |
| func (ctx *akaros) minimizeReport(report []byte) []byte { |
| out := new(bytes.Buffer) |
| for s := bufio.NewScanner(bytes.NewReader(report)); s.Scan(); { |
| line := bytes.Trim(s.Bytes(), "\r") |
| if len(line) == 0 || |
| bytes.Contains(line, []byte("Entering Nanwan's Dungeon")) || |
| bytes.Contains(line, []byte("Type 'help' for a list of commands")) { |
| continue |
| } |
| out.Write(line) |
| out.WriteByte('\n') |
| } |
| return out.Bytes() |
| } |
| |
| var ( |
| akarosSymbolizeRe = compile(`^#[0-9]+ \[\<(0x[0-9a-f]+)\>\] in ([a-zA-Z0-9_]+)`) |
| akarosBacktraceRe = compile(`(?:Stack Backtrace|Backtrace of kernel context) on Core [0-9]+:`) |
| ) |
| |
| var akarosStackParams = &stackParams{ |
| stackStartRes: []*regexp.Regexp{ |
| akarosBacktraceRe, |
| }, |
| frameRes: []*regexp.Regexp{ |
| compile(`^#[0-9]+ {{PC}} in ([a-zA-Z0-9_]+)`), |
| }, |
| skipPatterns: []string{ |
| "backtrace", |
| "mon_backtrace", |
| "monitor", |
| "_panic", |
| "_warn", |
| }, |
| } |
| |
| var akarosOopses = []*oops{ |
| { |
| []byte("kernel panic"), |
| []oopsFormat{ |
| { |
| title: compile("kernel panic at {{SRC}}, from core [0-9]+: assertion failed: (.*)"), |
| fmt: "assertion failed: %[2]v", |
| stack: &stackFmt{ |
| parts: []*regexp.Regexp{ |
| akarosBacktraceRe, |
| parseStackTrace, |
| }, |
| }, |
| }, |
| { |
| title: compile("kernel panic at {{SRC}}, from core [0-9]+: (.*)"), |
| fmt: "kernel panic: %[2]v", |
| stack: &stackFmt{ |
| parts: []*regexp.Regexp{ |
| akarosBacktraceRe, |
| parseStackTrace, |
| }, |
| }, |
| }, |
| { |
| title: compile("kernel panic"), |
| fmt: "kernel panic", |
| noStackTrace: true, |
| corrupted: true, |
| }, |
| }, |
| []*regexp.Regexp{}, |
| }, |
| { |
| []byte("kernel warning"), |
| []oopsFormat{ |
| { |
| title: compile("kernel warning at {{SRC}}, from core [0-9]+"), |
| fmt: "kernel warning in %[2]v", |
| stack: &stackFmt{ |
| parts: []*regexp.Regexp{ |
| akarosBacktraceRe, |
| parseStackTrace, |
| }, |
| }, |
| }, |
| { |
| title: compile("kernel warning"), |
| fmt: "kernel warning", |
| noStackTrace: true, |
| corrupted: true, |
| }, |
| }, |
| []*regexp.Regexp{}, |
| }, |
| } |