// Copyright 2015 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 prog import ( "bytes" "strconv" ) // LogEntry describes one program in execution log. type LogEntry struct { P *Prog Proc int // index of parallel proc Start int // start offset in log End int // end offset in log Fault bool // program was executed with fault injection in FaultCall/FaultNth FaultCall int FaultNth int } func (target *Target) ParseLog(data []byte) []*LogEntry { var entries []*LogEntry ent := &LogEntry{} var cur []byte for pos := 0; pos < len(data); { nl := bytes.IndexByte(data[pos:], '\n') if nl == -1 { nl = len(data) } else { nl += pos } line := data[pos : nl+1] pos0 := pos pos = nl + 1 if proc, ok := extractInt(line, "executing program "); ok { if ent.P != nil && len(ent.P.Calls) != 0 { ent.End = pos0 entries = append(entries, ent) } ent = &LogEntry{ Proc: proc, Start: pos0, } if faultCall, ok := extractInt(line, "fault-call:"); ok { ent.Fault = true ent.FaultCall = faultCall ent.FaultNth, _ = extractInt(line, "fault-nth:") } cur = nil continue } if ent == nil { continue } tmp := append(cur, line...) p, err := target.Deserialize(tmp) if err != nil { continue } cur = tmp ent.P = p } if ent.P != nil && len(ent.P.Calls) != 0 { ent.End = len(data) entries = append(entries, ent) } return entries } func extractInt(line []byte, prefix string) (int, bool) { pos := bytes.Index(line, []byte(prefix)) if pos == -1 { return 0, false } pos += len(prefix) end := pos for end != len(line) && line[end] >= '0' && line[end] <= '9' { end++ } v, _ := strconv.Atoi(string(line[pos:end])) return v, true }