pkg/report: add initial symbolize suppport to OpenBSD

This commit is contained in:
Anton Lindqvist 2018-12-08 11:03:31 +01:00 committed by Dmitry Vyukov
parent 977de94f01
commit 3350826625
2 changed files with 174 additions and 6 deletions

View File

@ -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(); {

View File

@ -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))
}
})
}
}