diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2016-09-06 19:34:55 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2016-09-06 19:34:55 +0200 |
| commit | 6b42c2d6da4c939bff9dbdbd15d186b3bdf28d9f (patch) | |
| tree | ba6907cd03d96a5d8a447145051e604c775a4266 | |
| parent | 1b7a8aa8489b3c3cf6b36da4a141d6d30832c03c (diff) | |
manager: show unique coverage
Add an option to view unique coverage per syscall (i.e. not covered
by any other calls) and unique coverage per-program (not covered by
any other program).
| -rw-r--r-- | syz-manager/html.go | 82 |
1 files changed, 67 insertions, 15 deletions
diff --git a/syz-manager/html.go b/syz-manager/html.go index ae8a6e088..66eb37010 100644 --- a/syz-manager/html.go +++ b/syz-manager/html.go @@ -76,9 +76,16 @@ func (mgr *Manager) httpInfo(w http.ResponseWriter, r *http.Request) { sort.Sort(UIStatArray(data.Stats)) var cov cover.Cover + totalUnique := mgr.uniqueCover(true) for c, cc := range calls { cov = cover.Union(cov, cc.cov) - data.Calls = append(data.Calls, UICallType{c, cc.count, len(cc.cov)}) + unique := cover.Intersection(cc.cov, totalUnique) + data.Calls = append(data.Calls, UICallType{ + Name: c, + Inputs: cc.count, + Cover: len(cc.cov), + UniqueCover: len(unique), + }) } sort.Sort(UICallTypeArray(data.Calls)) data.CoverSize = len(cov) @@ -94,6 +101,7 @@ func (mgr *Manager) httpCorpus(w http.ResponseWriter, r *http.Request) { var data []UIInput call := r.FormValue("call") + totalUnique := mgr.uniqueCover(false) for i, inp := range mgr.corpus { if call != inp.Call { continue @@ -102,11 +110,13 @@ func (mgr *Manager) httpCorpus(w http.ResponseWriter, r *http.Request) { if err != nil { http.Error(w, fmt.Sprintf("failed to deserialize program: %v", err), http.StatusInternalServerError) } + unique := cover.Intersection(inp.Cover, totalUnique) data = append(data, UIInput{ - Short: p.String(), - Full: string(inp.Prog), - Cover: len(inp.Cover), - N: i, + Short: p.String(), + Full: string(inp.Prog), + Cover: len(inp.Cover), + UniqueCover: len(unique), + N: i, }) } sort.Sort(UIInputArray(data)) @@ -122,15 +132,21 @@ func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) { var cov cover.Cover call := r.FormValue("call") + unique := r.FormValue("unique") != "" && call != "" + perCall := false if n, err := strconv.Atoi(call); err == nil && n < len(mgr.corpus) { cov = mgr.corpus[n].Cover } else { + perCall = true for _, inp := range mgr.corpus { if call == "" || call == inp.Call { cov = cover.Union(cov, cover.Cover(inp.Cover)) } } } + if unique { + cov = cover.Intersection(cov, mgr.uniqueCover(perCall)) + } if err := generateCoverHtml(w, mgr.cfg.Vmlinux, cov); err != nil { http.Error(w, fmt.Sprintf("failed to generate coverage profile: %v", err), http.StatusInternalServerError) @@ -138,6 +154,33 @@ func (mgr *Manager) httpCover(w http.ResponseWriter, r *http.Request) { runtime.GC() } +func (mgr *Manager) uniqueCover(perCall bool) cover.Cover { + totalCover := make(map[uint32]int) + callCover := make(map[string]map[uint32]bool) + for _, inp := range mgr.corpus { + if perCall && callCover[inp.Call] == nil { + callCover[inp.Call] = make(map[uint32]bool) + } + for _, pc := range inp.Cover { + if perCall { + if callCover[inp.Call][pc] { + continue + } + callCover[inp.Call][pc] = true + } + totalCover[pc]++ + } + } + var cov cover.Cover + for pc, count := range totalCover { + if count == 1 { + cov = append(cov, pc) + } + } + cover.Canonicalize(cov) + return cov +} + func (mgr *Manager) httpPrio(w http.ResponseWriter, r *http.Request) { mgr.mu.Lock() defer mgr.mu.Unlock() @@ -184,17 +227,19 @@ type UIStat struct { } type UICallType struct { - Name string - Inputs int - Cover int + Name string + Inputs int + Cover int + UniqueCover int } type UIInput struct { - Short string - Full string - Calls int - Cover int - N int + Short string + Full string + Calls int + Cover int + UniqueCover int + N int } type UICallTypeArray []UICallType @@ -234,7 +279,11 @@ Stats: <br> {{end}} <br> {{range $c := $.Calls}} - {{$c.Name}} <a href='/corpus?call={{$c.Name}}'>inputs:{{$c.Inputs}}</a> <a href='/cover?call={{$c.Name}}'>cover:{{$c.Cover}}</a> <a href='/prio?call={{$c.Name}}'>prio</a> <br> + {{$c.Name}} + <a href='/corpus?call={{$c.Name}}'>inputs:{{$c.Inputs}}</a> + <a href='/cover?call={{$c.Name}}'>cover:{{$c.Cover}}</a> + <a href='/cover?call={{$c.Name}}&unique=1'>unique:{{$c.UniqueCover}}</a> + <a href='/prio?call={{$c.Name}}'>prio</a> <br> {{end}} </body></html> `)) @@ -247,7 +296,10 @@ var corpusTemplate = template.Must(template.New("").Parse(` </head> <body> {{range $c := $}} - <span title="{{$c.Full}}">{{$c.Short}}</span> <a href='/cover?call={{$c.N}}'>cover:{{$c.Cover}}</a> <br> + <span title="{{$c.Full}}">{{$c.Short}}</span> + <a href='/cover?call={{$c.N}}'>cover:{{$c.Cover}}</a> + <a href='/cover?call={{$c.N}}&unique=1'>unique:{{$c.UniqueCover}}</a> + <br> {{end}} </body></html> `)) |
