aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJoey Jiao <quic_jiangenj@quicinc.com>2024-07-04 11:18:06 +0800
committerAlexander Potapenko <glider@google.com>2024-07-23 12:07:55 +0000
commit063d1761a6208b44ddd25c19e8d6a90acb886731 (patch)
tree0d74e17a7d556a7897460a5ffc58e544c6e11bd5
parent44cd723acfeeb472c42cc2fa6d1279ec4406d07d (diff)
pkg/report: support to symbolize line with module+offset
-rw-r--r--pkg/mgrconfig/load.go3
-rw-r--r--pkg/report/linux.go39
-rw-r--r--pkg/report/linux_test.go83
-rw-r--r--pkg/report/report.go13
-rw-r--r--pkg/rpcserver/rpcserver.go7
5 files changed, 120 insertions, 25 deletions
diff --git a/pkg/mgrconfig/load.go b/pkg/mgrconfig/load.go
index 05ba38a98..eb20b6b68 100644
--- a/pkg/mgrconfig/load.go
+++ b/pkg/mgrconfig/load.go
@@ -13,6 +13,7 @@ import (
"github.com/google/syzkaller/pkg/config"
"github.com/google/syzkaller/pkg/osutil"
+ "github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/prog"
_ "github.com/google/syzkaller/sys" // most mgrconfig users want targets too
"github.com/google/syzkaller/sys/targets"
@@ -40,6 +41,8 @@ type Derived struct {
// In this mode syz-manager does not start any VMs, but instead a user is supposed
// to start syz-executor process in a VM manually.
VMLess bool
+
+ LocalModules []*vminfo.KernelModule
}
func LoadData(data []byte) (*Config, error) {
diff --git a/pkg/report/linux.go b/pkg/report/linux.go
index 596c834ce..816c40fa7 100644
--- a/pkg/report/linux.go
+++ b/pkg/report/linux.go
@@ -16,13 +16,14 @@ import (
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/pkg/symbolizer"
"github.com/google/syzkaller/pkg/vcs"
+ "github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
type linux struct {
*config
vmlinux string
- symbols map[string][]symbolizer.Symbol
+ symbols map[string]map[string][]symbolizer.Symbol
consoleOutputRe *regexp.Regexp
taskContext *regexp.Regexp
cpuContext *regexp.Regexp
@@ -36,16 +37,26 @@ type linux struct {
}
func ctorLinux(cfg *config) (reporterImpl, []string, error) {
- var symbols map[string][]symbolizer.Symbol
+ symbols := make(map[string]map[string][]symbolizer.Symbol)
vmlinux := ""
if cfg.kernelObj != "" {
vmlinux = filepath.Join(cfg.kernelObj, cfg.target.KernelObject)
var err error
symb := symbolizer.NewSymbolizer(cfg.target)
- symbols, err = symb.ReadTextSymbols(vmlinux)
+ symbols[""], err = symb.ReadTextSymbols(vmlinux)
if err != nil {
return nil, nil, err
}
+ for _, mod := range cfg.kernelModules {
+ if mod.Name == "" {
+ continue
+ }
+ ss, err := symb.ReadTextSymbols(mod.Path)
+ if err != nil {
+ continue
+ }
+ symbols[mod.Name] = ss
+ }
}
ctx := &linux{
config: cfg,
@@ -405,7 +416,7 @@ func (ctx *linux) symbolize(rep *Report) error {
prefix := rep.reportPrefixLen
for _, line := range bytes.SplitAfter(rep.Report, []byte("\n")) {
line := bytes.Clone(line)
- newLine := symbolizeLine(symbFunc, ctx.symbols, ctx.vmlinux, ctx.kernelBuildSrc, line)
+ newLine := symbolizeLine(symbFunc, ctx.symbols, ctx.config.kernelModules, ctx.kernelBuildSrc, ctx, line)
if prefix > len(symbolized) {
prefix += len(newLine) - len(line)
}
@@ -426,7 +437,8 @@ func (ctx *linux) symbolize(rep *Report) error {
}
func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, error),
- symbols map[string][]symbolizer.Symbol, vmlinux, strip string, line []byte) []byte {
+ symbols map[string]map[string][]symbolizer.Symbol, modules []*vminfo.KernelModule, strip string,
+ ctx *linux, line []byte) []byte {
match := linuxSymbolizeRe.FindSubmatchIndex(line)
if match == nil {
return line
@@ -440,7 +452,11 @@ func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, err
if err != nil {
return line
}
- symb := symbols[string(fn)]
+ modName := ""
+ if match[10] != -1 && match[11] != -1 {
+ modName = string(line[match[10]:match[11]])
+ }
+ symb := symbols[modName][string(fn)]
if len(symb) == 0 {
return line
}
@@ -456,7 +472,14 @@ func symbolizeLine(symbFunc func(bin string, pc uint64) ([]symbolizer.Frame, err
// But RIP lines contain the exact faulting PC.
pc--
}
- frames, err := symbFunc(vmlinux, pc)
+ var bin string
+ for _, mod := range modules {
+ if mod.Name == modName {
+ bin = mod.Path
+ break
+ }
+ }
+ frames, err := symbFunc(bin, pc)
if err != nil || len(frames) == 0 {
return line
}
@@ -1023,7 +1046,7 @@ var linuxStallAnchorFrames = []*regexp.Regexp{
// nolint: lll
var (
- linuxSymbolizeRe = regexp.MustCompile(`(?:\[\<(?:(?:0x)?[0-9a-f]+)\>\])?[ \t]+\(?(?:[0-9]+:)?([a-zA-Z0-9_.]+)\+0x([0-9a-f]+)/0x([0-9a-f]+)\)?`)
+ linuxSymbolizeRe = regexp.MustCompile(`(?:\[\<(?:(?:0x)?[0-9a-f]+)\>\])?[ \t]+\(?(?:[0-9]+:)?([a-zA-Z0-9_.]+)\+0x([0-9a-f]+)/0x([0-9a-f]+)( ?\[([a-zA-Z0-9_.]+)\])?\)?`)
linuxRipFrame = compile(`(?:IP|NIP|pc |PC is at):? (?:(?:[0-9]+:)?(?:{{PC}} +){0,2}{{FUNC}}|(?:[0-9]+:)?0x[0-9a-f]+|(?:[0-9]+:)?{{PC}} +\[< *\(null\)>\] +\(null\)|[0-9]+: +\(null\))`)
linuxCallTrace = compile(`(?:Call (?:T|t)race:)|(?:Backtrace:)`)
linuxCodeRe = regexp.MustCompile(`(?m)^\s*Code\:\s+((?:[A-Fa-f0-9\(\)\<\>]{2,8}\s*)*)\s*$`)
diff --git a/pkg/report/linux_test.go b/pkg/report/linux_test.go
index 258efb271..756576e98 100644
--- a/pkg/report/linux_test.go
+++ b/pkg/report/linux_test.go
@@ -16,6 +16,7 @@ import (
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/osutil"
"github.com/google/syzkaller/pkg/symbolizer"
+ "github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
@@ -145,21 +146,61 @@ func TestLinuxSymbolizeLine(t *testing.T) {
"[<ffffffff82d1b1d9>] baz+0x101/0x200\n",
"[<ffffffff82d1b1d9>] baz+0x101/0x200 baz.c:100\n",
},
- }
- symbols := map[string][]symbolizer.Symbol{
- "foo": {
- {Addr: 0x1000000, Size: 0x190},
+ // Frame format with module+offset.
+ {
+ "[ 50.419727][ T3822] baz+0x101/0x200 [beep]\n",
+ "[ 50.419727][ T3822] baz+0x101/0x200 baz.c:100 [beep]\n",
+ },
+ // Frame format with module+offset for invalid module.
+ {
+ "[ 50.419727][ T3822] baz+0x101/0x200 [invalid_module]\n",
+ "[ 50.419727][ T3822] baz+0x101/0x200 [invalid_module]\n",
},
- "do_ipv6_setsockopt.isra.7.part.3": {
- {Addr: 0x2000000, Size: 0x2830},
+ // Frame format with module+offset for missing symbol.
+ {
+ "[ 50.419727][ T3822] missing_symbol+0x101/0x200 [beep]\n",
+ "[ 50.419727][ T3822] missing_symbol+0x101/0x200 [beep]\n",
},
- "baz": {
- {Addr: 0x3000000, Size: 0x100},
- {Addr: 0x4000000, Size: 0x200},
- {Addr: 0x5000000, Size: 0x300},
+ // Frame format with module+offset for invalid offset.
+ {
+ "[ 50.419727][ T3822] baz+0x300/0x200 [beep]\n",
+ "[ 50.419727][ T3822] baz+0x300/0x200 [beep]\n",
+ },
+ }
+ symbols := map[string]map[string][]symbolizer.Symbol{
+ "": {
+ "foo": {
+ {Addr: 0x1000000, Size: 0x190},
+ },
+ "do_ipv6_setsockopt.isra.7.part.3": {
+ {Addr: 0x2000000, Size: 0x2830},
+ },
+ "baz": {
+ {Addr: 0x3000000, Size: 0x100},
+ {Addr: 0x4000000, Size: 0x200},
+ {Addr: 0x5000000, Size: 0x300},
+ },
+ },
+ "beep": {
+ "baz": {
+ {Addr: 0x4000000, Size: 0x200},
+ },
},
}
symb := func(bin string, pc uint64) ([]symbolizer.Frame, error) {
+ if bin == "beep" {
+ switch pc {
+ case 0x4000100:
+ return []symbolizer.Frame{
+ {
+ File: "/linux/baz.c",
+ Line: 100,
+ },
+ }, nil
+ default:
+ return nil, fmt.Errorf("unknown pc 0x%x", pc)
+ }
+ }
if bin != "vmlinux" {
return nil, fmt.Errorf("unknown pc 0x%x", pc)
}
@@ -228,9 +269,29 @@ func TestLinuxSymbolizeLine(t *testing.T) {
return nil, fmt.Errorf("unknown pc 0x%x", pc)
}
}
+ modules := []*vminfo.KernelModule{
+ {
+ Name: "",
+ Path: "vmlinux",
+ },
+ {
+ Name: "beep",
+ Path: "beep",
+ },
+ }
+
+ cfg := &config{
+ kernelObj: "/linux",
+ kernelModules: modules,
+ }
+ ctx := &linux{
+ config: cfg,
+ vmlinux: "vmlinux",
+ symbols: symbols,
+ }
for i, test := range tests {
t.Run(fmt.Sprint(i), func(t *testing.T) {
- result := symbolizeLine(symb, symbols, "vmlinux", "/linux", []byte(test.line))
+ result := symbolizeLine(symb, symbols, modules, "/linux", ctx, []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/report.go b/pkg/report/report.go
index b211a140e..97b2e6aed 100644
--- a/pkg/report/report.go
+++ b/pkg/report/report.go
@@ -11,9 +11,11 @@ import (
"regexp"
"strings"
+ "github.com/google/syzkaller/pkg/cover/backend"
"github.com/google/syzkaller/pkg/mgrconfig"
"github.com/google/syzkaller/pkg/report/crash"
"github.com/google/syzkaller/pkg/vcs"
+ "github.com/google/syzkaller/pkg/vminfo"
"github.com/google/syzkaller/sys/targets"
)
@@ -82,6 +84,15 @@ const unspecifiedType = crash.Type("UNSPECIFIED")
// NewReporter creates reporter for the specified OS/Type.
func NewReporter(cfg *mgrconfig.Config) (*Reporter, error) {
+ var localModules []*vminfo.KernelModule
+ if cfg.KernelObj != "" {
+ var err error
+ localModules, err = backend.DiscoverModules(cfg.SysTarget, cfg.KernelObj, cfg.ModuleObj)
+ if err != nil {
+ return nil, err
+ }
+ cfg.LocalModules = localModules
+ }
typ := cfg.TargetOS
if cfg.Type == targets.GVisor || cfg.Type == targets.Starnix {
typ = cfg.Type
@@ -105,6 +116,7 @@ func NewReporter(cfg *mgrconfig.Config) (*Reporter, error) {
kernelBuildSrc: cfg.KernelBuildSrc,
kernelObj: cfg.KernelObj,
ignores: ignores,
+ kernelModules: localModules,
}
rep, suppressions, err := ctor(config)
if err != nil {
@@ -156,6 +168,7 @@ type config struct {
kernelBuildSrc string
kernelObj string
ignores []*regexp.Regexp
+ kernelModules []*vminfo.KernelModule
}
type fn func(cfg *config) (reporterImpl, []string, error)
diff --git a/pkg/rpcserver/rpcserver.go b/pkg/rpcserver/rpcserver.go
index 57abafdc9..0d50695f6 100644
--- a/pkg/rpcserver/rpcserver.go
+++ b/pkg/rpcserver/rpcserver.go
@@ -86,7 +86,6 @@ type Server struct {
}
func New(cfg *mgrconfig.Config, mgr Manager, debug bool) (*Server, error) {
- var modules []*vminfo.KernelModule
var pcBase uint64
if cfg.KernelObj != "" {
var err error
@@ -94,10 +93,6 @@ func New(cfg *mgrconfig.Config, mgr Manager, debug bool) (*Server, error) {
if err != nil {
return nil, err
}
- modules, err = backend.DiscoverModules(cfg.SysTarget, cfg.KernelObj, cfg.ModuleObj)
- if err != nil {
- return nil, err
- }
}
sandbox, err := flatrpc.SandboxToFlags(cfg.Sandbox)
if err != nil {
@@ -128,7 +123,7 @@ func New(cfg *mgrconfig.Config, mgr Manager, debug bool) (*Server, error) {
Procs: cfg.Procs,
Slowdown: cfg.Timeouts.Slowdown,
pcBase: pcBase,
- localModules: modules,
+ localModules: cfg.LocalModules,
}, mgr)
}