• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2018 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4package report
5
6import (
7	"bufio"
8	"bytes"
9	"fmt"
10	"path/filepath"
11	"regexp"
12	"strconv"
13	"strings"
14
15	"github.com/google/syzkaller/pkg/symbolizer"
16)
17
18type akaros struct {
19	ignores []*regexp.Regexp
20	objfile string
21}
22
23func ctorAkaros(kernelSrc, kernelObj string, ignores []*regexp.Regexp) (Reporter, []string, error) {
24	ctx := &akaros{
25		ignores: ignores,
26		objfile: filepath.Join(kernelObj, "akaros-kernel-64b"),
27	}
28	return ctx, nil, nil
29}
30
31func (ctx *akaros) ContainsCrash(output []byte) bool {
32	return containsCrash(output, akarosOopses, ctx.ignores)
33}
34
35func (ctx *akaros) Parse(output []byte) *Report {
36	rep := simpleLineParser(output, akarosOopses, akarosStackParams, ctx.ignores)
37	if rep == nil {
38		return nil
39	}
40	rep.Report = ctx.minimizeReport(rep.Report)
41	return rep
42}
43
44func (ctx *akaros) Symbolize(rep *Report) error {
45	symb := symbolizer.NewSymbolizer()
46	defer symb.Close()
47	var symbolized []byte
48	s := bufio.NewScanner(bytes.NewReader(rep.Report))
49	for s.Scan() {
50		line := bytes.Trim(s.Bytes(), "\r")
51		line = ctx.symbolizeLine(symb.Symbolize, ctx.objfile, line)
52		symbolized = append(symbolized, line...)
53		symbolized = append(symbolized, '\n')
54	}
55	rep.Report = symbolized
56	return nil
57}
58
59func (ctx *akaros) symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error),
60	objfile string, line []byte) []byte {
61	match := akarosSymbolizeRe.FindSubmatchIndex(line)
62	if match == nil {
63		return line
64	}
65	addr, err := strconv.ParseUint(string(line[match[2]:match[3]]), 0, 64)
66	if err != nil {
67		return line
68	}
69	frames, err := symbFunc(objfile, addr-1)
70	if err != nil || len(frames) == 0 {
71		return line
72	}
73	var symbolized []byte
74	for i, frame := range frames {
75		if i != 0 {
76			symbolized = append(symbolized, '\n')
77		}
78		file := frame.File
79		if pos := strings.LastIndex(file, "/kern/"); pos != -1 {
80			file = file[pos+6:]
81		}
82		modified := append([]byte{}, line...)
83		modified = append(modified, fmt.Sprintf(" at %v:%v", file, frame.Line)...)
84		if frame.Inline {
85			modified = replace(modified, match[4], match[5], []byte(frame.Func))
86			modified = replace(modified, match[2], match[3], []byte("     [inline]     "))
87		}
88		symbolized = append(symbolized, modified...)
89	}
90	return symbolized
91}
92
93func (ctx *akaros) minimizeReport(report []byte) []byte {
94	out := new(bytes.Buffer)
95	for s := bufio.NewScanner(bytes.NewReader(report)); s.Scan(); {
96		line := bytes.Trim(s.Bytes(), "\r")
97		if len(line) == 0 ||
98			bytes.Contains(line, []byte("Entering Nanwan's Dungeon")) ||
99			bytes.Contains(line, []byte("Type 'help' for a list of commands")) {
100			continue
101		}
102		out.Write(line)
103		out.WriteByte('\n')
104	}
105	return out.Bytes()
106}
107
108var (
109	akarosSymbolizeRe = compile(`^#[0-9]+ \[\<(0x[0-9a-f]+)\>\] in ([a-zA-Z0-9_]+)`)
110	akarosBacktraceRe = compile(`(?:Stack Backtrace|Backtrace of kernel context) on Core [0-9]+:`)
111)
112
113var akarosStackParams = &stackParams{
114	stackStartRes: []*regexp.Regexp{
115		akarosBacktraceRe,
116	},
117	frameRes: []*regexp.Regexp{
118		compile(`^#[0-9]+ {{PC}} in ([a-zA-Z0-9_]+)`),
119	},
120	skipPatterns: []string{
121		"backtrace",
122		"mon_backtrace",
123		"monitor",
124		"_panic",
125		"_warn",
126	},
127}
128
129var akarosOopses = []*oops{
130	{
131		[]byte("kernel panic"),
132		[]oopsFormat{
133			{
134				title: compile("kernel panic at {{SRC}}, from core [0-9]+: assertion failed: (.*)"),
135				fmt:   "assertion failed: %[2]v",
136				stack: &stackFmt{
137					parts: []*regexp.Regexp{
138						akarosBacktraceRe,
139						parseStackTrace,
140					},
141				},
142			},
143			{
144				title: compile("kernel panic at {{SRC}}, from core [0-9]+: (.*)"),
145				fmt:   "kernel panic: %[2]v",
146				stack: &stackFmt{
147					parts: []*regexp.Regexp{
148						akarosBacktraceRe,
149						parseStackTrace,
150					},
151				},
152			},
153			{
154				title:        compile("kernel panic"),
155				fmt:          "kernel panic",
156				noStackTrace: true,
157				corrupted:    true,
158			},
159		},
160		[]*regexp.Regexp{},
161	},
162	{
163		[]byte("kernel warning"),
164		[]oopsFormat{
165			{
166				title: compile("kernel warning at {{SRC}}, from core [0-9]+"),
167				fmt:   "kernel warning in %[2]v",
168				stack: &stackFmt{
169					parts: []*regexp.Regexp{
170						akarosBacktraceRe,
171						parseStackTrace,
172					},
173				},
174			},
175			{
176				title:        compile("kernel warning"),
177				fmt:          "kernel warning",
178				noStackTrace: true,
179				corrupted:    true,
180			},
181		},
182		[]*regexp.Regexp{},
183	},
184}
185