tools/syz-execprog: use more precise addresses when collecting coverage
Make two improvements to addresses obtained from kcov:
- call backend.PreviousInstructionPC() so that they point to the
__sanitizer_cov_trace_pc calls;
- read the top 32 bits of the kernel addresses from /proc/kallsyms
instead of using the hardcoded 0xffffffff value
diff --git a/tools/syz-execprog/execprog.go b/tools/syz-execprog/execprog.go
index 70d0eee..4d5e3d0 100644
--- a/tools/syz-execprog/execprog.go
+++ b/tools/syz-execprog/execprog.go
@@ -11,10 +11,12 @@
"fmt"
"os"
"runtime"
+ "strconv"
"sync"
"time"
"github.com/google/syzkaller/pkg/cover"
+ "github.com/google/syzkaller/pkg/cover/backend"
"github.com/google/syzkaller/pkg/csource"
"github.com/google/syzkaller/pkg/db"
"github.com/google/syzkaller/pkg/host"
@@ -25,6 +27,7 @@
"github.com/google/syzkaller/pkg/tool"
"github.com/google/syzkaller/prog"
_ "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/sys/targets"
)
var (
@@ -72,6 +75,7 @@
if err != nil {
log.Fatalf("%v", err)
}
+
progs := loadPrograms(target, flag.Args())
if len(progs) == 0 {
return
@@ -102,13 +106,17 @@
}
}
}
+ sysTarget := targets.Get(*flagOS, *flagArch)
+ upperBase := getKernelUpperBase(sysTarget)
ctx := &Context{
- progs: progs,
- config: config,
- execOpts: execOpts,
- gate: ipc.NewGate(2**flagProcs, gateCallback),
- shutdown: make(chan struct{}),
- repeat: *flagRepeat,
+ progs: progs,
+ config: config,
+ execOpts: execOpts,
+ gate: ipc.NewGate(2**flagProcs, gateCallback),
+ shutdown: make(chan struct{}),
+ repeat: *flagRepeat,
+ target: sysTarget,
+ upperBase: upperBase,
}
var wg sync.WaitGroup
wg.Add(*flagProcs)
@@ -134,6 +142,8 @@
repeat int
pos int
lastPrint time.Time
+ target *targets.Target
+ upperBase uint32
}
func (ctx *Context) run(pid int) {
@@ -251,13 +261,39 @@
log.Logf(0, "ncomps=%v ncandidates=%v", ncomps, ncandidates)
}
+func getKernelUpperBase(target *targets.Target) uint32 {
+ defaultRet := uint32(0xffffffff)
+ if target.OS == targets.Linux {
+ // Read the first 8 bytes from /proc/kallsyms.
+ f, err := os.Open("/proc/kallsyms")
+ if err != nil {
+ log.Logf(1, "could not get kernel fixup address: %v", err)
+ return defaultRet
+ }
+ defer f.Close()
+ data := make([]byte, 8)
+ _, err = f.ReadAt(data, 0)
+ if err != nil {
+ log.Logf(1, "could not get kernel fixup address: %v", err)
+ return defaultRet
+ }
+ value, err := strconv.ParseUint(string(data), 16, 32)
+ if err != nil {
+ log.Logf(1, "could not get kernel fixup address: %v", err)
+ return defaultRet
+ }
+ return uint32(value)
+ }
+ return defaultRet
+}
+
func (ctx *Context) dumpCallCoverage(coverFile string, info *ipc.CallInfo) {
if len(info.Cover) == 0 {
return
}
buf := new(bytes.Buffer)
for _, pc := range info.Cover {
- fmt.Fprintf(buf, "0x%x\n", cover.RestorePC(pc, 0xffffffff))
+ fmt.Fprintf(buf, "0x%x\n", backend.PreviousInstructionPC(ctx.target, cover.RestorePC(pc, ctx.upperBase)))
}
err := osutil.WriteFile(coverFile, buf.Bytes())
if err != nil {