diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2024-11-27 17:23:09 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2024-12-11 15:22:17 +0000 |
| commit | 299ee674e6c124a35f1cf258df4f0f3c6e1db1f3 (patch) | |
| tree | 416b515e959a1d0a64a9516b1524a062ae63ba7d /pkg | |
| parent | ff949d2512c5ac33d0407d26d80f1df77b2de0e7 (diff) | |
executor: query globs in the test program context
We query globs for 2 reasons:
1. Expand glob types in syscall descriptions.
2. Dynamic file probing for automatic descriptions generation.
In both of these contexts are are interested in files
that will be present during test program execution
(rather than normal unsandboxed execution).
For example, some files may not be accessible to test programs
after pivot root. On the other hand, we create and link
some additional files for the test program that don't
normally exist.
Add a new request type for querying of globs that are
executed in the test program context.
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/flatrpc/conn_test.go | 2 | ||||
| -rw-r--r-- | pkg/flatrpc/flatrpc.fbs | 17 | ||||
| -rw-r--r-- | pkg/flatrpc/flatrpc.go | 207 | ||||
| -rw-r--r-- | pkg/flatrpc/flatrpc.h | 174 | ||||
| -rw-r--r-- | pkg/fuzzer/queue/queue.go | 67 | ||||
| -rw-r--r-- | pkg/fuzzer/queue/queue_test.go | 7 | ||||
| -rw-r--r-- | pkg/ifaceprobe/ifaceprobe.go | 179 | ||||
| -rw-r--r-- | pkg/rpcserver/local.go | 3 | ||||
| -rw-r--r-- | pkg/rpcserver/mocks/Manager.go | 10 | ||||
| -rw-r--r-- | pkg/rpcserver/rpcserver.go | 25 | ||||
| -rw-r--r-- | pkg/rpcserver/runner.go | 31 | ||||
| -rw-r--r-- | pkg/runtest/run.go | 5 | ||||
| -rw-r--r-- | pkg/vminfo/syscalls.go | 36 | ||||
| -rw-r--r-- | pkg/vminfo/vminfo.go | 3 | ||||
| -rw-r--r-- | pkg/vminfo/vminfo_test.go | 27 |
15 files changed, 450 insertions, 343 deletions
diff --git a/pkg/flatrpc/conn_test.go b/pkg/flatrpc/conn_test.go index 3ab83996e..132fd1cdd 100644 --- a/pkg/flatrpc/conn_test.go +++ b/pkg/flatrpc/conn_test.go @@ -28,7 +28,6 @@ func TestConn(t *testing.T) { RaceFrames: []string{"bar", "baz"}, Features: FeatureCoverage | FeatureLeak, Files: []string{"file1"}, - Globs: []string{"glob1"}, } executorMsg := &ExecutorMessage{ Msg: &ExecutorMessages{ @@ -102,7 +101,6 @@ func BenchmarkConn(b *testing.B) { RaceFrames: []string{"bar", "baz"}, Features: FeatureCoverage | FeatureLeak, Files: []string{"file1"}, - Globs: []string{"glob1"}, } done := make(chan bool) diff --git a/pkg/flatrpc/flatrpc.fbs b/pkg/flatrpc/flatrpc.fbs index 0bd32b743..6d2307d6a 100644 --- a/pkg/flatrpc/flatrpc.fbs +++ b/pkg/flatrpc/flatrpc.fbs @@ -57,14 +57,12 @@ table ConnectReplyRaw { features :Feature; // Fuzzer reads these files inside of the VM and returns contents in InfoRequest.files. files :[string]; - globs :[string]; } table InfoRequestRaw { error :string; features :[FeatureInfoRaw]; files :[FileInfoRaw]; - globs :[GlobInfoRaw]; } table InfoReplyRaw { @@ -112,10 +110,16 @@ table ExecutorMessageRaw { msg :ExecutorMessagesRaw; } +enum RequestType : uint64 { + // Normal test program request (data contains serialized prog.Prog). + Program, + // Binary test program (data contains compiled executable binary). + Binary, + // Request for file glob expansion (data contains the glob pattern). + Glob, +} + enum RequestFlag : uint64 (bit_flags) { - // If set, prog_data contains compiled executable binary - // that needs to be written to disk and executed. - IsBinary, // If set, collect program output and return in output field. ReturnOutput, // If set, don't fail on program failures, instead return the error in error field. @@ -163,9 +167,10 @@ struct ExecOptsRaw { // Request to execute a test program. table ExecRequestRaw { id :int64; + type :RequestType; // Bitmask of procs to avoid when executing this request, if possible. avoid :uint64; - prog_data :[uint8]; + data :[uint8]; exec_opts :ExecOptsRaw; flags :RequestFlag; // Return all signal for these calls. diff --git a/pkg/flatrpc/flatrpc.go b/pkg/flatrpc/flatrpc.go index 8445cde2d..fd5b4f614 100644 --- a/pkg/flatrpc/flatrpc.go +++ b/pkg/flatrpc/flatrpc.go @@ -257,22 +257,46 @@ func (rcv ExecutorMessagesRaw) UnPack(table flatbuffers.Table) *ExecutorMessages return nil } +type RequestType uint64 + +const ( + RequestTypeProgram RequestType = 0 + RequestTypeBinary RequestType = 1 + RequestTypeGlob RequestType = 2 +) + +var EnumNamesRequestType = map[RequestType]string{ + RequestTypeProgram: "Program", + RequestTypeBinary: "Binary", + RequestTypeGlob: "Glob", +} + +var EnumValuesRequestType = map[string]RequestType{ + "Program": RequestTypeProgram, + "Binary": RequestTypeBinary, + "Glob": RequestTypeGlob, +} + +func (v RequestType) String() string { + if s, ok := EnumNamesRequestType[v]; ok { + return s + } + return "RequestType(" + strconv.FormatInt(int64(v), 10) + ")" +} + type RequestFlag uint64 const ( - RequestFlagIsBinary RequestFlag = 1 - RequestFlagReturnOutput RequestFlag = 2 - RequestFlagReturnError RequestFlag = 4 + RequestFlagReturnOutput RequestFlag = 1 + RequestFlagReturnError RequestFlag = 2 ) var EnumNamesRequestFlag = map[RequestFlag]string{ - RequestFlagIsBinary: "IsBinary", RequestFlagReturnOutput: "ReturnOutput", RequestFlagReturnError: "ReturnError", } var EnumValuesRequestFlag = map[string]RequestFlag{ - "IsBinary": RequestFlagIsBinary, "ReturnOutput": RequestFlagReturnOutput, "ReturnError": RequestFlagReturnError, } @@ -594,7 +618,6 @@ type ConnectReplyRawT struct { RaceFrames []string `json:"race_frames"` Features Feature `json:"features"` Files []string `json:"files"` - Globs []string `json:"globs"` } func (t *ConnectReplyRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { @@ -640,19 +663,6 @@ func (t *ConnectReplyRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffse } filesOffset = builder.EndVector(filesLength) } - globsOffset := flatbuffers.UOffsetT(0) - if t.Globs != nil { - globsLength := len(t.Globs) - globsOffsets := make([]flatbuffers.UOffsetT, globsLength) - for j := 0; j < globsLength; j++ { - globsOffsets[j] = builder.CreateString(t.Globs[j]) - } - ConnectReplyRawStartGlobsVector(builder, globsLength) - for j := globsLength - 1; j >= 0; j-- { - builder.PrependUOffsetT(globsOffsets[j]) - } - globsOffset = builder.EndVector(globsLength) - } ConnectReplyRawStart(builder) ConnectReplyRawAddDebug(builder, t.Debug) ConnectReplyRawAddCover(builder, t.Cover) @@ -666,7 +676,6 @@ func (t *ConnectReplyRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffse ConnectReplyRawAddRaceFrames(builder, raceFramesOffset) ConnectReplyRawAddFeatures(builder, t.Features) ConnectReplyRawAddFiles(builder, filesOffset) - ConnectReplyRawAddGlobs(builder, globsOffset) return ConnectReplyRawEnd(builder) } @@ -695,11 +704,6 @@ func (rcv *ConnectReplyRaw) UnPackTo(t *ConnectReplyRawT) { for j := 0; j < filesLength; j++ { t.Files[j] = string(rcv.Files(j)) } - globsLength := rcv.GlobsLength() - t.Globs = make([]string, globsLength) - for j := 0; j < globsLength; j++ { - t.Globs[j] = string(rcv.Globs(j)) - } } func (rcv *ConnectReplyRaw) UnPack() *ConnectReplyRawT { @@ -897,25 +901,8 @@ func (rcv *ConnectReplyRaw) FilesLength() int { return 0 } -func (rcv *ConnectReplyRaw) Globs(j int) []byte { - o := flatbuffers.UOffsetT(rcv._tab.Offset(28)) - if o != 0 { - a := rcv._tab.Vector(o) - return rcv._tab.ByteVector(a + flatbuffers.UOffsetT(j*4)) - } - return nil -} - -func (rcv *ConnectReplyRaw) GlobsLength() int { - o := flatbuffers.UOffsetT(rcv._tab.Offset(28)) - if o != 0 { - return rcv._tab.VectorLen(o) - } - return 0 -} - func ConnectReplyRawStart(builder *flatbuffers.Builder) { - builder.StartObject(13) + builder.StartObject(12) } func ConnectReplyRawAddDebug(builder *flatbuffers.Builder, debug bool) { builder.PrependBoolSlot(0, debug, false) @@ -962,12 +949,6 @@ func ConnectReplyRawAddFiles(builder *flatbuffers.Builder, files flatbuffers.UOf func ConnectReplyRawStartFilesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(4, numElems, 4) } -func ConnectReplyRawAddGlobs(builder *flatbuffers.Builder, globs flatbuffers.UOffsetT) { - builder.PrependUOffsetTSlot(12, flatbuffers.UOffsetT(globs), 0) -} -func ConnectReplyRawStartGlobsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { - return builder.StartVector(4, numElems, 4) -} func ConnectReplyRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } @@ -976,7 +957,6 @@ type InfoRequestRawT struct { Error string `json:"error"` Features []*FeatureInfoRawT `json:"features"` Files []*FileInfoRawT `json:"files"` - Globs []*GlobInfoRawT `json:"globs"` } func (t *InfoRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffsetT { @@ -1010,24 +990,10 @@ func (t *InfoRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffset } filesOffset = builder.EndVector(filesLength) } - globsOffset := flatbuffers.UOffsetT(0) - if t.Globs != nil { - globsLength := len(t.Globs) - globsOffsets := make([]flatbuffers.UOffsetT, globsLength) - for j := 0; j < globsLength; j++ { - globsOffsets[j] = t.Globs[j].Pack(builder) - } - InfoRequestRawStartGlobsVector(builder, globsLength) - for j := globsLength - 1; j >= 0; j-- { - builder.PrependUOffsetT(globsOffsets[j]) - } - globsOffset = builder.EndVector(globsLength) - } InfoRequestRawStart(builder) InfoRequestRawAddError(builder, errorOffset) InfoRequestRawAddFeatures(builder, featuresOffset) InfoRequestRawAddFiles(builder, filesOffset) - InfoRequestRawAddGlobs(builder, globsOffset) return InfoRequestRawEnd(builder) } @@ -1047,13 +1013,6 @@ func (rcv *InfoRequestRaw) UnPackTo(t *InfoRequestRawT) { rcv.Files(&x, j) t.Files[j] = x.UnPack() } - globsLength := rcv.GlobsLength() - t.Globs = make([]*GlobInfoRawT, globsLength) - for j := 0; j < globsLength; j++ { - x := GlobInfoRaw{} - rcv.Globs(&x, j) - t.Globs[j] = x.UnPack() - } } func (rcv *InfoRequestRaw) UnPack() *InfoRequestRawT { @@ -1140,28 +1099,8 @@ func (rcv *InfoRequestRaw) FilesLength() int { return 0 } -func (rcv *InfoRequestRaw) Globs(obj *GlobInfoRaw, j int) bool { - o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) - if o != 0 { - x := rcv._tab.Vector(o) - x += flatbuffers.UOffsetT(j) * 4 - x = rcv._tab.Indirect(x) - obj.Init(rcv._tab.Bytes, x) - return true - } - return false -} - -func (rcv *InfoRequestRaw) GlobsLength() int { - o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) - if o != 0 { - return rcv._tab.VectorLen(o) - } - return 0 -} - func InfoRequestRawStart(builder *flatbuffers.Builder) { - builder.StartObject(4) + builder.StartObject(3) } func InfoRequestRawAddError(builder *flatbuffers.Builder, error flatbuffers.UOffsetT) { builder.PrependUOffsetTSlot(0, flatbuffers.UOffsetT(error), 0) @@ -1178,12 +1117,6 @@ func InfoRequestRawAddFiles(builder *flatbuffers.Builder, files flatbuffers.UOff func InfoRequestRawStartFilesVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(4, numElems, 4) } -func InfoRequestRawAddGlobs(builder *flatbuffers.Builder, globs flatbuffers.UOffsetT) { - builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(globs), 0) -} -func InfoRequestRawStartGlobsVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { - return builder.StartVector(4, numElems, 4) -} func InfoRequestRawEnd(builder *flatbuffers.Builder) flatbuffers.UOffsetT { return builder.EndObject() } @@ -1929,8 +1862,9 @@ func CreateExecOptsRaw(builder *flatbuffers.Builder, envFlags ExecEnv, execFlags type ExecRequestRawT struct { Id int64 `json:"id"` + Type RequestType `json:"type"` Avoid uint64 `json:"avoid"` - ProgData []byte `json:"prog_data"` + Data []byte `json:"data"` ExecOpts *ExecOptsRawT `json:"exec_opts"` Flags RequestFlag `json:"flags"` AllSignal []int32 `json:"all_signal"` @@ -1940,9 +1874,9 @@ func (t *ExecRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffset if t == nil { return 0 } - progDataOffset := flatbuffers.UOffsetT(0) - if t.ProgData != nil { - progDataOffset = builder.CreateByteString(t.ProgData) + dataOffset := flatbuffers.UOffsetT(0) + if t.Data != nil { + dataOffset = builder.CreateByteString(t.Data) } allSignalOffset := flatbuffers.UOffsetT(0) if t.AllSignal != nil { @@ -1955,8 +1889,9 @@ func (t *ExecRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffset } ExecRequestRawStart(builder) ExecRequestRawAddId(builder, t.Id) + ExecRequestRawAddType(builder, t.Type) ExecRequestRawAddAvoid(builder, t.Avoid) - ExecRequestRawAddProgData(builder, progDataOffset) + ExecRequestRawAddData(builder, dataOffset) execOptsOffset := t.ExecOpts.Pack(builder) ExecRequestRawAddExecOpts(builder, execOptsOffset) ExecRequestRawAddFlags(builder, t.Flags) @@ -1966,8 +1901,9 @@ func (t *ExecRequestRawT) Pack(builder *flatbuffers.Builder) flatbuffers.UOffset func (rcv *ExecRequestRaw) UnPackTo(t *ExecRequestRawT) { t.Id = rcv.Id() + t.Type = rcv.Type() t.Avoid = rcv.Avoid() - t.ProgData = rcv.ProgDataBytes() + t.Data = rcv.DataBytes() t.ExecOpts = rcv.ExecOpts(nil).UnPack() t.Flags = rcv.Flags() allSignalLength := rcv.AllSignalLength() @@ -2025,20 +1961,32 @@ func (rcv *ExecRequestRaw) MutateId(n int64) bool { return rcv._tab.MutateInt64Slot(4, n) } -func (rcv *ExecRequestRaw) Avoid() uint64 { +func (rcv *ExecRequestRaw) Type() RequestType { o := flatbuffers.UOffsetT(rcv._tab.Offset(6)) if o != 0 { + return RequestType(rcv._tab.GetUint64(o + rcv._tab.Pos)) + } + return 0 +} + +func (rcv *ExecRequestRaw) MutateType(n RequestType) bool { + return rcv._tab.MutateUint64Slot(6, uint64(n)) +} + +func (rcv *ExecRequestRaw) Avoid() uint64 { + o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) + if o != 0 { return rcv._tab.GetUint64(o + rcv._tab.Pos) } return 0 } func (rcv *ExecRequestRaw) MutateAvoid(n uint64) bool { - return rcv._tab.MutateUint64Slot(6, n) + return rcv._tab.MutateUint64Slot(8, n) } -func (rcv *ExecRequestRaw) ProgData(j int) byte { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) +func (rcv *ExecRequestRaw) Data(j int) byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { a := rcv._tab.Vector(o) return rcv._tab.GetByte(a + flatbuffers.UOffsetT(j*1)) @@ -2046,24 +1994,24 @@ func (rcv *ExecRequestRaw) ProgData(j int) byte { return 0 } -func (rcv *ExecRequestRaw) ProgDataLength() int { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) +func (rcv *ExecRequestRaw) DataLength() int { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { return rcv._tab.VectorLen(o) } return 0 } -func (rcv *ExecRequestRaw) ProgDataBytes() []byte { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) +func (rcv *ExecRequestRaw) DataBytes() []byte { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { return rcv._tab.ByteVector(o + rcv._tab.Pos) } return nil } -func (rcv *ExecRequestRaw) MutateProgData(j int, n byte) bool { - o := flatbuffers.UOffsetT(rcv._tab.Offset(8)) +func (rcv *ExecRequestRaw) MutateData(j int, n byte) bool { + o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) if o != 0 { a := rcv._tab.Vector(o) return rcv._tab.MutateByte(a+flatbuffers.UOffsetT(j*1), n) @@ -2072,7 +2020,7 @@ func (rcv *ExecRequestRaw) MutateProgData(j int, n byte) bool { } func (rcv *ExecRequestRaw) ExecOpts(obj *ExecOptsRaw) *ExecOptsRaw { - o := flatbuffers.UOffsetT(rcv._tab.Offset(10)) + o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) if o != 0 { x := o + rcv._tab.Pos if obj == nil { @@ -2085,7 +2033,7 @@ func (rcv *ExecRequestRaw) ExecOpts(obj *ExecOptsRaw) *ExecOptsRaw { } func (rcv *ExecRequestRaw) Flags() RequestFlag { - o := flatbuffers.UOffsetT(rcv._tab.Offset(12)) + o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) if o != 0 { return RequestFlag(rcv._tab.GetUint64(o + rcv._tab.Pos)) } @@ -2093,11 +2041,11 @@ func (rcv *ExecRequestRaw) Flags() RequestFlag { } func (rcv *ExecRequestRaw) MutateFlags(n RequestFlag) bool { - return rcv._tab.MutateUint64Slot(12, uint64(n)) + return rcv._tab.MutateUint64Slot(14, uint64(n)) } func (rcv *ExecRequestRaw) AllSignal(j int) int32 { - o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) if o != 0 { a := rcv._tab.Vector(o) return rcv._tab.GetInt32(a + flatbuffers.UOffsetT(j*4)) @@ -2106,7 +2054,7 @@ func (rcv *ExecRequestRaw) AllSignal(j int) int32 { } func (rcv *ExecRequestRaw) AllSignalLength() int { - o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) if o != 0 { return rcv._tab.VectorLen(o) } @@ -2114,7 +2062,7 @@ func (rcv *ExecRequestRaw) AllSignalLength() int { } func (rcv *ExecRequestRaw) MutateAllSignal(j int, n int32) bool { - o := flatbuffers.UOffsetT(rcv._tab.Offset(14)) + o := flatbuffers.UOffsetT(rcv._tab.Offset(16)) if o != 0 { a := rcv._tab.Vector(o) return rcv._tab.MutateInt32(a+flatbuffers.UOffsetT(j*4), n) @@ -2123,28 +2071,31 @@ func (rcv *ExecRequestRaw) MutateAllSignal(j int, n int32) bool { } func ExecRequestRawStart(builder *flatbuffers.Builder) { - builder.StartObject(6) + builder.StartObject(7) } func ExecRequestRawAddId(builder *flatbuffers.Builder, id int64) { builder.PrependInt64Slot(0, id, 0) } +func ExecRequestRawAddType(builder *flatbuffers.Builder, type_ RequestType) { + builder.PrependUint64Slot(1, uint64(type_), 0) +} func ExecRequestRawAddAvoid(builder *flatbuffers.Builder, avoid uint64) { - builder.PrependUint64Slot(1, avoid, 0) + builder.PrependUint64Slot(2, avoid, 0) } -func ExecRequestRawAddProgData(builder *flatbuffers.Builder, progData flatbuffers.UOffsetT) { - builder.PrependUOffsetTSlot(2, flatbuffers.UOffsetT(progData), 0) +func ExecRequestRawAddData(builder *flatbuffers.Builder, data flatbuffers.UOffsetT) { + builder.PrependUOffsetTSlot(3, flatbuffers.UOffsetT(data), 0) } -func ExecRequestRawStartProgDataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { +func ExecRequestRawStartDataVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(1, numElems, 1) } func ExecRequestRawAddExecOpts(builder *flatbuffers.Builder, execOpts flatbuffers.UOffsetT) { - builder.PrependStructSlot(3, flatbuffers.UOffsetT(execOpts), 0) + builder.PrependStructSlot(4, flatbuffers.UOffsetT(execOpts), 0) } func ExecRequestRawAddFlags(builder *flatbuffers.Builder, flags RequestFlag) { - builder.PrependUint64Slot(4, uint64(flags), 0) + builder.PrependUint64Slot(5, uint64(flags), 0) } func ExecRequestRawAddAllSignal(builder *flatbuffers.Builder, allSignal flatbuffers.UOffsetT) { - builder.PrependUOffsetTSlot(5, flatbuffers.UOffsetT(allSignal), 0) + builder.PrependUOffsetTSlot(6, flatbuffers.UOffsetT(allSignal), 0) } func ExecRequestRawStartAllSignalVector(builder *flatbuffers.Builder, numElems int) flatbuffers.UOffsetT { return builder.StartVector(4, numElems, 4) diff --git a/pkg/flatrpc/flatrpc.h b/pkg/flatrpc/flatrpc.h index 94e1c15f6..12d905c12 100644 --- a/pkg/flatrpc/flatrpc.h +++ b/pkg/flatrpc/flatrpc.h @@ -486,18 +486,49 @@ struct ExecutorMessagesRawUnion { bool VerifyExecutorMessagesRaw(flatbuffers::Verifier &verifier, const void *obj, ExecutorMessagesRaw type); bool VerifyExecutorMessagesRawVector(flatbuffers::Verifier &verifier, const flatbuffers::Vector<flatbuffers::Offset<void>> *values, const flatbuffers::Vector<ExecutorMessagesRaw> *types); +enum class RequestType : uint64_t { + Program = 0, + Binary = 1ULL, + Glob = 2ULL, + MIN = Program, + MAX = Glob +}; + +inline const RequestType (&EnumValuesRequestType())[3] { + static const RequestType values[] = { + RequestType::Program, + RequestType::Binary, + RequestType::Glob + }; + return values; +} + +inline const char * const *EnumNamesRequestType() { + static const char * const names[4] = { + "Program", + "Binary", + "Glob", + nullptr + }; + return names; +} + +inline const char *EnumNameRequestType(RequestType e) { + if (flatbuffers::IsOutRange(e, RequestType::Program, RequestType::Glob)) return ""; + const size_t index = static_cast<size_t>(e); + return EnumNamesRequestType()[index]; +} + enum class RequestFlag : uint64_t { - IsBinary = 1ULL, - ReturnOutput = 2ULL, - ReturnError = 4ULL, + ReturnOutput = 1ULL, + ReturnError = 2ULL, NONE = 0, - ANY = 7ULL + ANY = 3ULL }; FLATBUFFERS_DEFINE_BITMASK_OPERATORS(RequestFlag, uint64_t) -inline const RequestFlag (&EnumValuesRequestFlag())[3] { +inline const RequestFlag (&EnumValuesRequestFlag())[2] { static const RequestFlag values[] = { - RequestFlag::IsBinary, RequestFlag::ReturnOutput, RequestFlag::ReturnError }; @@ -505,10 +536,8 @@ inline const RequestFlag (&EnumValuesRequestFlag())[3] { } inline const char * const *EnumNamesRequestFlag() { - static const char * const names[5] = { - "IsBinary", + static const char * const names[3] = { "ReturnOutput", - "", "ReturnError", nullptr }; @@ -516,8 +545,8 @@ inline const char * const *EnumNamesRequestFlag() { } inline const char *EnumNameRequestFlag(RequestFlag e) { - if (flatbuffers::IsOutRange(e, RequestFlag::IsBinary, RequestFlag::ReturnError)) return ""; - const size_t index = static_cast<size_t>(e) - static_cast<size_t>(RequestFlag::IsBinary); + if (flatbuffers::IsOutRange(e, RequestFlag::ReturnOutput, RequestFlag::ReturnError)) return ""; + const size_t index = static_cast<size_t>(e) - static_cast<size_t>(RequestFlag::ReturnOutput); return EnumNamesRequestFlag()[index]; } @@ -936,7 +965,6 @@ struct ConnectReplyRawT : public flatbuffers::NativeTable { std::vector<std::string> race_frames{}; rpc::Feature features = static_cast<rpc::Feature>(0); std::vector<std::string> files{}; - std::vector<std::string> globs{}; }; struct ConnectReplyRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { @@ -954,8 +982,7 @@ struct ConnectReplyRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VT_LEAK_FRAMES = 20, VT_RACE_FRAMES = 22, VT_FEATURES = 24, - VT_FILES = 26, - VT_GLOBS = 28 + VT_FILES = 26 }; bool debug() const { return GetField<uint8_t>(VT_DEBUG, 0) != 0; @@ -993,9 +1020,6 @@ struct ConnectReplyRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *files() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_FILES); } - const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *globs() const { - return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>> *>(VT_GLOBS); - } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField<uint8_t>(verifier, VT_DEBUG, 1) && @@ -1016,9 +1040,6 @@ struct ConnectReplyRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyOffset(verifier, VT_FILES) && verifier.VerifyVector(files()) && verifier.VerifyVectorOfStrings(files()) && - VerifyOffset(verifier, VT_GLOBS) && - verifier.VerifyVector(globs()) && - verifier.VerifyVectorOfStrings(globs()) && verifier.EndTable(); } ConnectReplyRawT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -1066,9 +1087,6 @@ struct ConnectReplyRawBuilder { void add_files(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> files) { fbb_.AddOffset(ConnectReplyRaw::VT_FILES, files); } - void add_globs(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> globs) { - fbb_.AddOffset(ConnectReplyRaw::VT_GLOBS, globs); - } explicit ConnectReplyRawBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -1093,11 +1111,9 @@ inline flatbuffers::Offset<ConnectReplyRaw> CreateConnectReplyRaw( flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> leak_frames = 0, flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> race_frames = 0, rpc::Feature features = static_cast<rpc::Feature>(0), - flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> files = 0, - flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> globs = 0) { + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<flatbuffers::String>>> files = 0) { ConnectReplyRawBuilder builder_(_fbb); builder_.add_features(features); - builder_.add_globs(globs); builder_.add_files(files); builder_.add_race_frames(race_frames); builder_.add_leak_frames(leak_frames); @@ -1125,12 +1141,10 @@ inline flatbuffers::Offset<ConnectReplyRaw> CreateConnectReplyRawDirect( const std::vector<flatbuffers::Offset<flatbuffers::String>> *leak_frames = nullptr, const std::vector<flatbuffers::Offset<flatbuffers::String>> *race_frames = nullptr, rpc::Feature features = static_cast<rpc::Feature>(0), - const std::vector<flatbuffers::Offset<flatbuffers::String>> *files = nullptr, - const std::vector<flatbuffers::Offset<flatbuffers::String>> *globs = nullptr) { + const std::vector<flatbuffers::Offset<flatbuffers::String>> *files = nullptr) { auto leak_frames__ = leak_frames ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*leak_frames) : 0; auto race_frames__ = race_frames ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*race_frames) : 0; auto files__ = files ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*files) : 0; - auto globs__ = globs ? _fbb.CreateVector<flatbuffers::Offset<flatbuffers::String>>(*globs) : 0; return rpc::CreateConnectReplyRaw( _fbb, debug, @@ -1144,8 +1158,7 @@ inline flatbuffers::Offset<ConnectReplyRaw> CreateConnectReplyRawDirect( leak_frames__, race_frames__, features, - files__, - globs__); + files__); } flatbuffers::Offset<ConnectReplyRaw> CreateConnectReplyRaw(flatbuffers::FlatBufferBuilder &_fbb, const ConnectReplyRawT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -1155,7 +1168,6 @@ struct InfoRequestRawT : public flatbuffers::NativeTable { std::string error{}; std::vector<std::unique_ptr<rpc::FeatureInfoRawT>> features{}; std::vector<std::unique_ptr<rpc::FileInfoRawT>> files{}; - std::vector<std::unique_ptr<rpc::GlobInfoRawT>> globs{}; InfoRequestRawT() = default; InfoRequestRawT(const InfoRequestRawT &o); InfoRequestRawT(InfoRequestRawT&&) FLATBUFFERS_NOEXCEPT = default; @@ -1168,8 +1180,7 @@ struct InfoRequestRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_ERROR = 4, VT_FEATURES = 6, - VT_FILES = 8, - VT_GLOBS = 10 + VT_FILES = 8 }; const flatbuffers::String *error() const { return GetPointer<const flatbuffers::String *>(VT_ERROR); @@ -1180,9 +1191,6 @@ struct InfoRequestRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { const flatbuffers::Vector<flatbuffers::Offset<rpc::FileInfoRaw>> *files() const { return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<rpc::FileInfoRaw>> *>(VT_FILES); } - const flatbuffers::Vector<flatbuffers::Offset<rpc::GlobInfoRaw>> *globs() const { - return GetPointer<const flatbuffers::Vector<flatbuffers::Offset<rpc::GlobInfoRaw>> *>(VT_GLOBS); - } bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyOffset(verifier, VT_ERROR) && @@ -1193,9 +1201,6 @@ struct InfoRequestRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { VerifyOffset(verifier, VT_FILES) && verifier.VerifyVector(files()) && verifier.VerifyVectorOfTables(files()) && - VerifyOffset(verifier, VT_GLOBS) && - verifier.VerifyVector(globs()) && - verifier.VerifyVectorOfTables(globs()) && verifier.EndTable(); } InfoRequestRawT *UnPack(const flatbuffers::resolver_function_t *_resolver = nullptr) const; @@ -1216,9 +1221,6 @@ struct InfoRequestRawBuilder { void add_files(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<rpc::FileInfoRaw>>> files) { fbb_.AddOffset(InfoRequestRaw::VT_FILES, files); } - void add_globs(flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<rpc::GlobInfoRaw>>> globs) { - fbb_.AddOffset(InfoRequestRaw::VT_GLOBS, globs); - } explicit InfoRequestRawBuilder(flatbuffers::FlatBufferBuilder &_fbb) : fbb_(_fbb) { start_ = fbb_.StartTable(); @@ -1234,10 +1236,8 @@ inline flatbuffers::Offset<InfoRequestRaw> CreateInfoRequestRaw( flatbuffers::FlatBufferBuilder &_fbb, flatbuffers::Offset<flatbuffers::String> error = 0, flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<rpc::FeatureInfoRaw>>> features = 0, - flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<rpc::FileInfoRaw>>> files = 0, - flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<rpc::GlobInfoRaw>>> globs = 0) { + flatbuffers::Offset<flatbuffers::Vector<flatbuffers::Offset<rpc::FileInfoRaw>>> files = 0) { InfoRequestRawBuilder builder_(_fbb); - builder_.add_globs(globs); builder_.add_files(files); builder_.add_features(features); builder_.add_error(error); @@ -1248,18 +1248,15 @@ inline flatbuffers::Offset<InfoRequestRaw> CreateInfoRequestRawDirect( flatbuffers::FlatBufferBuilder &_fbb, const char *error = nullptr, const std::vector<flatbuffers::Offset<rpc::FeatureInfoRaw>> *features = nullptr, - const std::vector<flatbuffers::Offset<rpc::FileInfoRaw>> *files = nullptr, - const std::vector<flatbuffers::Offset<rpc::GlobInfoRaw>> *globs = nullptr) { + const std::vector<flatbuffers::Offset<rpc::FileInfoRaw>> *files = nullptr) { auto error__ = error ? _fbb.CreateString(error) : 0; auto features__ = features ? _fbb.CreateVector<flatbuffers::Offset<rpc::FeatureInfoRaw>>(*features) : 0; auto files__ = files ? _fbb.CreateVector<flatbuffers::Offset<rpc::FileInfoRaw>>(*files) : 0; - auto globs__ = globs ? _fbb.CreateVector<flatbuffers::Offset<rpc::GlobInfoRaw>>(*globs) : 0; return rpc::CreateInfoRequestRaw( _fbb, error__, features__, - files__, - globs__); + files__); } flatbuffers::Offset<InfoRequestRaw> CreateInfoRequestRaw(flatbuffers::FlatBufferBuilder &_fbb, const InfoRequestRawT *_o, const flatbuffers::rehasher_function_t *_rehasher = nullptr); @@ -1777,8 +1774,9 @@ flatbuffers::Offset<ExecutorMessageRaw> CreateExecutorMessageRaw(flatbuffers::Fl struct ExecRequestRawT : public flatbuffers::NativeTable { typedef ExecRequestRaw TableType; int64_t id = 0; + rpc::RequestType type = rpc::RequestType::Program; uint64_t avoid = 0; - std::vector<uint8_t> prog_data{}; + std::vector<uint8_t> data{}; std::unique_ptr<rpc::ExecOptsRaw> exec_opts{}; rpc::RequestFlag flags = static_cast<rpc::RequestFlag>(0); std::vector<int32_t> all_signal{}; @@ -1793,20 +1791,24 @@ struct ExecRequestRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { typedef ExecRequestRawBuilder Builder; enum FlatBuffersVTableOffset FLATBUFFERS_VTABLE_UNDERLYING_TYPE { VT_ID = 4, - VT_AVOID = 6, - VT_PROG_DATA = 8, - VT_EXEC_OPTS = 10, - VT_FLAGS = 12, - VT_ALL_SIGNAL = 14 + VT_TYPE = 6, + VT_AVOID = 8, + VT_DATA = 10, + VT_EXEC_OPTS = 12, + VT_FLAGS = 14, + VT_ALL_SIGNAL = 16 }; int64_t id() const { return GetField<int64_t>(VT_ID, 0); } + rpc::RequestType type() const { + return static_cast<rpc::RequestType>(GetField<uint64_t>(VT_TYPE, 0)); + } uint64_t avoid() const { return GetField<uint64_t>(VT_AVOID, 0); } - const flatbuffers::Vector<uint8_t> *prog_data() const { - return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_PROG_DATA); + const flatbuffers::Vector<uint8_t> *data() const { + return GetPointer<const flatbuffers::Vector<uint8_t> *>(VT_DATA); } const rpc::ExecOptsRaw *exec_opts() const { return GetStruct<const rpc::ExecOptsRaw *>(VT_EXEC_OPTS); @@ -1820,9 +1822,10 @@ struct ExecRequestRaw FLATBUFFERS_FINAL_CLASS : private flatbuffers::Table { bool Verify(flatbuffers::Verifier &verifier) const { return VerifyTableStart(verifier) && VerifyField<int64_t>(verifier, VT_ID, 8) && + VerifyField<uint64_t>(verifier, VT_TYPE, 8) && VerifyField<uint64_t>(verifier, VT_AVOID, 8) && - VerifyOffset(verifier, VT_PROG_DATA) && - verifier.VerifyVector(prog_data()) && + VerifyOffset(verifier, VT_DATA) && + verifier.VerifyVector(data()) && VerifyField<rpc::ExecOptsRaw>(verifier, VT_EXEC_OPTS, 8) && VerifyField<uint64_t>(verifier, VT_FLAGS, 8) && VerifyOffset(verifier, VT_ALL_SIGNAL) && @@ -1841,11 +1844,14 @@ struct ExecRequestRawBuilder { void add_id(int64_t id) { fbb_.AddElement<int64_t>(ExecRequestRaw::VT_ID, id, 0); } + void add_type(rpc::RequestType type) { + fbb_.AddElement<uint64_t>(ExecRequestRaw::VT_TYPE, static_cast<uint64_t>(type), 0); + } void add_avoid(uint64_t avoid) { fbb_.AddElement<uint64_t>(ExecRequestRaw::VT_AVOID, avoid, 0); } - void add_prog_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> prog_data) { - fbb_.AddOffset(ExecRequestRaw::VT_PROG_DATA, prog_data); + void add_data(flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data) { + fbb_.AddOffset(ExecRequestRaw::VT_DATA, data); } void add_exec_opts(const rpc::ExecOptsRaw *exec_opts) { fbb_.AddStruct(ExecRequestRaw::VT_EXEC_OPTS, exec_opts); @@ -1870,36 +1876,40 @@ struct ExecRequestRawBuilder { inline flatbuffers::Offset<ExecRequestRaw> CreateExecRequestRaw( flatbuffers::FlatBufferBuilder &_fbb, int64_t id = 0, + rpc::RequestType type = rpc::RequestType::Program, uint64_t avoid = 0, - flatbuffers::Offset<flatbuffers::Vector<uint8_t>> prog_data = 0, + flatbuffers::Offset<flatbuffers::Vector<uint8_t>> data = 0, const rpc::ExecOptsRaw *exec_opts = nullptr, rpc::RequestFlag flags = static_cast<rpc::RequestFlag>(0), flatbuffers::Offset<flatbuffers::Vector<int32_t>> all_signal = 0) { ExecRequestRawBuilder builder_(_fbb); builder_.add_flags(flags); builder_.add_avoid(avoid); + builder_.add_type(type); builder_.add_id(id); builder_.add_all_signal(all_signal); builder_.add_exec_opts(exec_opts); - builder_.add_prog_data(prog_data); + builder_.add_data(data); return builder_.Finish(); } inline flatbuffers::Offset<ExecRequestRaw> CreateExecRequestRawDirect( flatbuffers::FlatBufferBuilder &_fbb, int64_t id = 0, + rpc::RequestType type = rpc::RequestType::Program, uint64_t avoid = 0, - const std::vector<uint8_t> *prog_data = nullptr, + const std::vector<uint8_t> *data = nullptr, const rpc::ExecOptsRaw *exec_opts = nullptr, rpc::RequestFlag flags = static_cast<rpc::RequestFlag>(0), const std::vector<int32_t> *all_signal = nullptr) { - auto prog_data__ = prog_data ? _fbb.CreateVector<uint8_t>(*prog_data) : 0; + auto data__ = data ? _fbb.CreateVector<uint8_t>(*data) : 0; auto all_signal__ = all_signal ? _fbb.CreateVector<int32_t>(*all_signal) : 0; return rpc::CreateExecRequestRaw( _fbb, id, + type, avoid, - prog_data__, + data__, exec_opts, flags, all_signal__); @@ -2942,7 +2952,6 @@ inline void ConnectReplyRaw::UnPackTo(ConnectReplyRawT *_o, const flatbuffers::r { auto _e = race_frames(); if (_e) { _o->race_frames.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->race_frames[_i] = _e->Get(_i)->str(); } } } { auto _e = features(); _o->features = _e; } { auto _e = files(); if (_e) { _o->files.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->files[_i] = _e->Get(_i)->str(); } } } - { auto _e = globs(); if (_e) { _o->globs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->globs[_i] = _e->Get(_i)->str(); } } } } inline flatbuffers::Offset<ConnectReplyRaw> ConnectReplyRaw::Pack(flatbuffers::FlatBufferBuilder &_fbb, const ConnectReplyRawT* _o, const flatbuffers::rehasher_function_t *_rehasher) { @@ -2965,7 +2974,6 @@ inline flatbuffers::Offset<ConnectReplyRaw> CreateConnectReplyRaw(flatbuffers::F auto _race_frames = _o->race_frames.size() ? _fbb.CreateVectorOfStrings(_o->race_frames) : 0; auto _features = _o->features; auto _files = _o->files.size() ? _fbb.CreateVectorOfStrings(_o->files) : 0; - auto _globs = _o->globs.size() ? _fbb.CreateVectorOfStrings(_o->globs) : 0; return rpc::CreateConnectReplyRaw( _fbb, _debug, @@ -2979,8 +2987,7 @@ inline flatbuffers::Offset<ConnectReplyRaw> CreateConnectReplyRaw(flatbuffers::F _leak_frames, _race_frames, _features, - _files, - _globs); + _files); } inline InfoRequestRawT::InfoRequestRawT(const InfoRequestRawT &o) @@ -2989,15 +2996,12 @@ inline InfoRequestRawT::InfoRequestRawT(const InfoRequestRawT &o) for (const auto &features_ : o.features) { features.emplace_back((features_) ? new rpc::FeatureInfoRawT(*features_) : nullptr); } files.reserve(o.files.size()); for (const auto &files_ : o.files) { files.emplace_back((files_) ? new rpc::FileInfoRawT(*files_) : nullptr); } - globs.reserve(o.globs.size()); - for (const auto &globs_ : o.globs) { globs.emplace_back((globs_) ? new rpc::GlobInfoRawT(*globs_) : nullptr); } } inline InfoRequestRawT &InfoRequestRawT::operator=(InfoRequestRawT o) FLATBUFFERS_NOEXCEPT { std::swap(error, o.error); std::swap(features, o.features); std::swap(files, o.files); - std::swap(globs, o.globs); return *this; } @@ -3013,7 +3017,6 @@ inline void InfoRequestRaw::UnPackTo(InfoRequestRawT *_o, const flatbuffers::res { auto _e = error(); if (_e) _o->error = _e->str(); } { auto _e = features(); if (_e) { _o->features.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->features[_i] = std::unique_ptr<rpc::FeatureInfoRawT>(_e->Get(_i)->UnPack(_resolver)); } } } { auto _e = files(); if (_e) { _o->files.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->files[_i] = std::unique_ptr<rpc::FileInfoRawT>(_e->Get(_i)->UnPack(_resolver)); } } } - { auto _e = globs(); if (_e) { _o->globs.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->globs[_i] = std::unique_ptr<rpc::GlobInfoRawT>(_e->Get(_i)->UnPack(_resolver)); } } } } inline flatbuffers::Offset<InfoRequestRaw> InfoRequestRaw::Pack(flatbuffers::FlatBufferBuilder &_fbb, const InfoRequestRawT* _o, const flatbuffers::rehasher_function_t *_rehasher) { @@ -3027,13 +3030,11 @@ inline flatbuffers::Offset<InfoRequestRaw> CreateInfoRequestRaw(flatbuffers::Fla auto _error = _o->error.empty() ? 0 : _fbb.CreateString(_o->error); auto _features = _o->features.size() ? _fbb.CreateVector<flatbuffers::Offset<rpc::FeatureInfoRaw>> (_o->features.size(), [](size_t i, _VectorArgs *__va) { return CreateFeatureInfoRaw(*__va->__fbb, __va->__o->features[i].get(), __va->__rehasher); }, &_va ) : 0; auto _files = _o->files.size() ? _fbb.CreateVector<flatbuffers::Offset<rpc::FileInfoRaw>> (_o->files.size(), [](size_t i, _VectorArgs *__va) { return CreateFileInfoRaw(*__va->__fbb, __va->__o->files[i].get(), __va->__rehasher); }, &_va ) : 0; - auto _globs = _o->globs.size() ? _fbb.CreateVector<flatbuffers::Offset<rpc::GlobInfoRaw>> (_o->globs.size(), [](size_t i, _VectorArgs *__va) { return CreateGlobInfoRaw(*__va->__fbb, __va->__o->globs[i].get(), __va->__rehasher); }, &_va ) : 0; return rpc::CreateInfoRequestRaw( _fbb, _error, _features, - _files, - _globs); + _files); } inline InfoReplyRawT *InfoReplyRaw::UnPack(const flatbuffers::resolver_function_t *_resolver) const { @@ -3218,8 +3219,9 @@ inline flatbuffers::Offset<ExecutorMessageRaw> CreateExecutorMessageRaw(flatbuff inline ExecRequestRawT::ExecRequestRawT(const ExecRequestRawT &o) : id(o.id), + type(o.type), avoid(o.avoid), - prog_data(o.prog_data), + data(o.data), exec_opts((o.exec_opts) ? new rpc::ExecOptsRaw(*o.exec_opts) : nullptr), flags(o.flags), all_signal(o.all_signal) { @@ -3227,8 +3229,9 @@ inline ExecRequestRawT::ExecRequestRawT(const ExecRequestRawT &o) inline ExecRequestRawT &ExecRequestRawT::operator=(ExecRequestRawT o) FLATBUFFERS_NOEXCEPT { std::swap(id, o.id); + std::swap(type, o.type); std::swap(avoid, o.avoid); - std::swap(prog_data, o.prog_data); + std::swap(data, o.data); std::swap(exec_opts, o.exec_opts); std::swap(flags, o.flags); std::swap(all_signal, o.all_signal); @@ -3245,8 +3248,9 @@ inline void ExecRequestRaw::UnPackTo(ExecRequestRawT *_o, const flatbuffers::res (void)_o; (void)_resolver; { auto _e = id(); _o->id = _e; } + { auto _e = type(); _o->type = _e; } { auto _e = avoid(); _o->avoid = _e; } - { auto _e = prog_data(); if (_e) { _o->prog_data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->prog_data.begin()); } } + { auto _e = data(); if (_e) { _o->data.resize(_e->size()); std::copy(_e->begin(), _e->end(), _o->data.begin()); } } { auto _e = exec_opts(); if (_e) _o->exec_opts = std::unique_ptr<rpc::ExecOptsRaw>(new rpc::ExecOptsRaw(*_e)); } { auto _e = flags(); _o->flags = _e; } { auto _e = all_signal(); if (_e) { _o->all_signal.resize(_e->size()); for (flatbuffers::uoffset_t _i = 0; _i < _e->size(); _i++) { _o->all_signal[_i] = _e->Get(_i); } } } @@ -3261,16 +3265,18 @@ inline flatbuffers::Offset<ExecRequestRaw> CreateExecRequestRaw(flatbuffers::Fla (void)_o; struct _VectorArgs { flatbuffers::FlatBufferBuilder *__fbb; const ExecRequestRawT* __o; const flatbuffers::rehasher_function_t *__rehasher; } _va = { &_fbb, _o, _rehasher}; (void)_va; auto _id = _o->id; + auto _type = _o->type; auto _avoid = _o->avoid; - auto _prog_data = _o->prog_data.size() ? _fbb.CreateVector(_o->prog_data) : 0; + auto _data = _o->data.size() ? _fbb.CreateVector(_o->data) : 0; auto _exec_opts = _o->exec_opts ? _o->exec_opts.get() : nullptr; auto _flags = _o->flags; auto _all_signal = _o->all_signal.size() ? _fbb.CreateVector(_o->all_signal) : 0; return rpc::CreateExecRequestRaw( _fbb, _id, + _type, _avoid, - _prog_data, + _data, _exec_opts, _flags, _all_signal); diff --git a/pkg/fuzzer/queue/queue.go b/pkg/fuzzer/queue/queue.go index 1d25cbc8a..05d9cfbed 100644 --- a/pkg/fuzzer/queue/queue.go +++ b/pkg/fuzzer/queue/queue.go @@ -9,6 +9,7 @@ import ( "encoding/gob" "fmt" "math/rand" + "strings" "sync" "sync/atomic" @@ -20,8 +21,15 @@ import ( ) type Request struct { - Prog *prog.Prog - ExecOpts flatrpc.ExecOpts + // Type of the request. + // RequestTypeProgram executes Prog, and is used by most requests (also the default zero value). + // RequestTypeBinary executes binary with file name stored in Data. + // RequestTypeGlob expands glob pattern stored in Data. + Type flatrpc.RequestType + ExecOpts flatrpc.ExecOpts + Prog *prog.Prog // for RequestTypeProgram + BinaryFile string // for RequestTypeBinary + GlobPattern string // for RequestTypeGlob // If specified, the resulting signal for call SignalFilterCall // will include subset of it even if it's not new. @@ -36,9 +44,6 @@ type Request struct { // This stat will be incremented on request completion. Stat *stat.Val - // Options needed by runtest. - BinaryFile string // If set, it's executed instead of Prog. - // Important requests will be retried even from crashed VMs. Important bool @@ -123,20 +128,51 @@ func (r *Request) Validate() error { if (collectComps) && (collectSignal || collectCover) { return fmt.Errorf("hint collection is mutually exclusive with signal/coverage") } - sandboxes := flatrpc.ExecEnvSandboxNone | flatrpc.ExecEnvSandboxSetuid | - flatrpc.ExecEnvSandboxNamespace | flatrpc.ExecEnvSandboxAndroid - if r.BinaryFile == "" && r.ExecOpts.EnvFlags&sandboxes == 0 { - return fmt.Errorf("no sandboxes set") + switch r.Type { + case flatrpc.RequestTypeProgram: + if r.Prog == nil { + return fmt.Errorf("program is not set") + } + sandboxes := flatrpc.ExecEnvSandboxNone | flatrpc.ExecEnvSandboxSetuid | + flatrpc.ExecEnvSandboxNamespace | flatrpc.ExecEnvSandboxAndroid + if r.ExecOpts.EnvFlags&sandboxes == 0 { + return fmt.Errorf("no sandboxes set") + } + case flatrpc.RequestTypeBinary: + if r.BinaryFile == "" { + return fmt.Errorf("binary file name is not set") + } + case flatrpc.RequestTypeGlob: + if r.GlobPattern == "" { + return fmt.Errorf("glob pattern is not set") + } + default: + return fmt.Errorf("unknown request type") } return nil } func (r *Request) hash() hash.Sig { buf := new(bytes.Buffer) - if err := gob.NewEncoder(buf).Encode(r.ExecOpts); err != nil { + enc := gob.NewEncoder(buf) + if err := enc.Encode(r.Type); err != nil { + panic(err) + } + if err := enc.Encode(r.ExecOpts); err != nil { panic(err) } - return hash.Hash(r.Prog.Serialize(), buf.Bytes()) + var data []byte + switch r.Type { + case flatrpc.RequestTypeProgram: + data = r.Prog.Serialize() + case flatrpc.RequestTypeBinary: + data = []byte(r.BinaryFile) + case flatrpc.RequestTypeGlob: + data = []byte(r.GlobPattern) + default: + panic("unknown request type") + } + return hash.Hash(data, buf.Bytes()) } func (r *Request) initChannel() { @@ -172,6 +208,15 @@ func (r *Result) Stop() bool { } } +// Globs returns result of RequestTypeGlob. +func (r *Result) GlobFiles() []string { + out := strings.Trim(string(r.Output), "\000") + if out == "" { + return nil + } + return strings.Split(out, "\000") +} + type Status int const ( diff --git a/pkg/fuzzer/queue/queue_test.go b/pkg/fuzzer/queue/queue_test.go index 5b6a03ed0..d1909e50c 100644 --- a/pkg/fuzzer/queue/queue_test.go +++ b/pkg/fuzzer/queue/queue_test.go @@ -43,3 +43,10 @@ func TestPrioQueue(t *testing.T) { assert.Equal(t, req4, pq.Next()) assert.Equal(t, req3, pq.Next()) } + +func TestGlobFiles(t *testing.T) { + r := &Result{} + assert.Equal(t, r.GlobFiles(), []string(nil)) + r.Output = []byte{'a', 'b', 0, 'c', 0} + assert.Equal(t, r.GlobFiles(), []string{"ab", "c"}) +} diff --git a/pkg/ifaceprobe/ifaceprobe.go b/pkg/ifaceprobe/ifaceprobe.go index f3ab8ba4a..b2b3569df 100644 --- a/pkg/ifaceprobe/ifaceprobe.go +++ b/pkg/ifaceprobe/ifaceprobe.go @@ -12,7 +12,9 @@ import ( "path/filepath" "slices" "strings" + "sync" + "github.com/google/syzkaller/pkg/csource" "github.com/google/syzkaller/pkg/flatrpc" "github.com/google/syzkaller/pkg/fuzzer/queue" "github.com/google/syzkaller/pkg/log" @@ -38,71 +40,62 @@ type PCInfo struct { File string } -// Globs returns a list of glob's that should be requested from the target machine. -// Result of querying these globs should be later passed to Run in info. -func Globs() []string { - var globs []string - for _, path := range []string{"/dev", "/sys", "/proc"} { - // Our globs currently do not support recursion (#4906), - // so we append N "/*" parts manully. Some of the paths can be very deep, e.g. try: - // sudo find /sys -ls 2>/dev/null | sed "s#[^/]##g" | sort | uniq -c - for i := 1; i < 15; i++ { - globs = append(globs, path+strings.Repeat("/*", i)) - } - } - return globs -} - -// Run finishes dynamic analysis and returns dynamic info. +// Run does dynamic analysis and returns dynamic info. // As it runs it will submit some test program requests to the exec queue. -// Info is used to extract results of glob querying, see Globs function. -func Run(ctx context.Context, cfg *mgrconfig.Config, exec queue.Executor, info *flatrpc.InfoRequest) (*Info, error) { +func Run(ctx context.Context, cfg *mgrconfig.Config, features flatrpc.Feature, exec queue.Executor) (*Info, error) { return (&prober{ - ctx: ctx, - cfg: cfg, - exec: exec, - info: info, + ctx: ctx, + cfg: cfg, + features: features, + exec: exec, + done: make(chan *fileDesc, 100), + errc: make(chan error, 1), }).run() } type prober struct { - ctx context.Context - cfg *mgrconfig.Config - exec queue.Executor - info *flatrpc.InfoRequest + ctx context.Context + cfg *mgrconfig.Config + features flatrpc.Feature + exec queue.Executor + wg sync.WaitGroup + done chan *fileDesc + errc chan error +} + +type fileDesc struct { + file string + results []*queue.Result } func (pr *prober) run() (*Info, error) { symb := symbolizer.NewSymbolizer(pr.cfg.SysTarget) defer symb.Close() - files := extractFiles(pr.info) - var reqs [][]*queue.Request - for _, file := range extractFiles(pr.info) { - reqs1, err := pr.submitFile(file) - if err != nil { - return nil, err - } - reqs = append(reqs, reqs1) + for _, glob := range globList() { + pr.submitGlob(glob) } + go func() { + pr.wg.Wait() + close(pr.done) + }() + info := &Info{} dedup := make(map[uint64]bool) kernelObj := filepath.Join(pr.cfg.KernelObj, pr.cfg.SysTarget.KernelObject) sourceBase := filepath.Clean(pr.cfg.KernelSrc) + string(filepath.Separator) - for i, file := range files { + i := 0 + for desc := range pr.done { + i++ if i%500 == 0 { - log.Logf(0, "processing file %v/%v", i, len(files)) + log.Logf(0, "done file %v", i) } fi := FileInfo{ - Name: file, + Name: desc.file, } fileDedup := make(map[uint64]bool) - for _, req := range reqs[i] { - res := req.Wait(pr.ctx) - if res.Status != queue.Success { - return nil, fmt.Errorf("failed to execute prog: %w (%v)", res.Err, res.Status) - } + for _, res := range desc.results { cover := append(res.Info.Calls[0].Cover, res.Info.Calls[1].Cover...) for _, pc := range cover { if fileDedup[pc] { @@ -133,13 +126,59 @@ func (pr *prober) run() (*Info, error) { slices.Sort(fi.Cover) info.Files = append(info.Files, fi) } + slices.SortFunc(info.Files, func(a, b FileInfo) int { + return strings.Compare(a.Name, b.Name) + }) slices.SortFunc(info.PCs, func(a, b PCInfo) int { return int(a.PC - b.PC) }) - return info, nil + select { + case err := <-pr.errc: + return nil, err + default: + return info, nil + } +} + +func (pr *prober) noteError(err error) { + select { + case pr.errc <- err: + default: + } } -func (pr *prober) submitFile(file string) ([]*queue.Request, error) { +func (pr *prober) submitGlob(glob string) { + pr.wg.Add(1) + req := &queue.Request{ + Type: flatrpc.RequestTypeGlob, + GlobPattern: glob, + ExecOpts: flatrpc.ExecOpts{ + EnvFlags: flatrpc.ExecEnvSandboxNone | csource.FeaturesToFlags(pr.features, nil), + }, + Important: true, + } + req.OnDone(pr.onGlobDone) + pr.exec.Submit(req) +} + +func (pr *prober) onGlobDone(req *queue.Request, res *queue.Result) bool { + defer pr.wg.Done() + if res.Status != queue.Success { + pr.noteError(fmt.Errorf("failed to execute glob: %w (%v)\n%s\n%s", + res.Err, res.Status, req.GlobPattern, res.Output)) + } + files := res.GlobFiles() + log.Logf(0, "glob %v expanded to %v files", req.GlobPattern, len(files)) + for _, file := range files { + if extractFileFilter(file) { + pr.submitFile(file) + } + } + return true +} + +func (pr *prober) submitFile(file string) { + pr.wg.Add(1) var fops = []struct { mode string call string @@ -151,18 +190,22 @@ func (pr *prober) submitFile(file string) ([]*queue.Request, error) { {mode: "O_RDONLY", call: "mmap(0x0, 0x1000, 0x1, 0x2, r0, 0)"}, {mode: "O_WRONLY", call: "mmap(0x0, 0x1000, 0x2, 0x2, r0, 0)"}, } + desc := &fileDesc{ + file: file, + } var reqs []*queue.Request for _, desc := range fops { text := fmt.Sprintf("r0 = openat(0x%x, &AUTO='%s', 0x%x, 0x0)\n%v", pr.constVal("AT_FDCWD"), file, pr.constVal(desc.mode), desc.call) p, err := pr.cfg.Target.Deserialize([]byte(text), prog.StrictUnsafe) if err != nil { - return nil, fmt.Errorf("failed to deserialize: %w\n%v", err, text) + panic(fmt.Sprintf("failed to deserialize: %v\n%v", err, text)) } req := &queue.Request{ Prog: p, ExecOpts: flatrpc.ExecOpts{ - EnvFlags: flatrpc.ExecEnvSandboxNone | flatrpc.ExecEnvSignal, + EnvFlags: flatrpc.ExecEnvSandboxNone | flatrpc.ExecEnvSignal | + csource.FeaturesToFlags(pr.features, nil), ExecFlags: flatrpc.ExecFlagCollectCover, }, Important: true, @@ -170,7 +213,19 @@ func (pr *prober) submitFile(file string) ([]*queue.Request, error) { reqs = append(reqs, req) pr.exec.Submit(req) } - return reqs, nil + go func() { + defer pr.wg.Done() + for _, req := range reqs { + res := req.Wait(pr.ctx) + if res.Status != queue.Success { + pr.noteError(fmt.Errorf("failed to execute prog: %w (%v)\n%s\n%s", + res.Err, res.Status, req.Prog.Serialize(), res.Output)) + continue + } + desc.results = append(desc.results, res) + } + pr.done <- desc + }() } func (pr *prober) constVal(name string) uint64 { @@ -181,23 +236,27 @@ func (pr *prober) constVal(name string) uint64 { return val } -func extractFiles(info *flatrpc.InfoRequestRawT) []string { - var files []string - dedup := make(map[string]bool) - for _, glob := range info.Globs { - for _, file := range glob.Files { - if dedup[file] || !extractFileFilter(file) { - continue - } - dedup[file] = true - files = append(files, file) +// globList returns a list of glob's we are interested in. +func globList() []string { + var globs []string + // /selinux is mounted by executor, we probably should mount it at the standard /sys/fs/selinux, + // but this is where it is now. + // Also query the test cwd, executor creates some links in there. + for _, path := range []string{"/dev", "/sys", "/proc", "/selinux", "."} { + // Our globs currently do not support recursion (#4906), + // so we append N "/*" parts manully. Some of the paths can be very deep, e.g. try: + // sudo find /sys -ls 2>/dev/null | sed "s#[^/]##g" | sort | uniq -c + for i := 1; i < 15; i++ { + globs = append(globs, path+strings.Repeat("/*", i)) } } - return files + return globs } func extractFileFilter(file string) bool { - if strings.HasPrefix(file, "/dev/") { + if strings.HasPrefix(file, "/dev/") || + strings.HasPrefix(file, "/selinux/") || + strings.HasPrefix(file, "./") { return true } if proc := "/proc/"; strings.HasPrefix(file, proc) { @@ -234,5 +293,5 @@ func extractFileFilter(file string) bool { } return true } - return false + panic(fmt.Sprintf("unhandled file %q", file)) } diff --git a/pkg/rpcserver/local.go b/pkg/rpcserver/local.go index c8052138a..5faa8334b 100644 --- a/pkg/rpcserver/local.go +++ b/pkg/rpcserver/local.go @@ -112,8 +112,7 @@ type local struct { setupDone chan bool } -func (ctx *local) MachineChecked(info *flatrpc.InfoRequest, features flatrpc.Feature, - syscalls map[*prog.Syscall]bool) queue.Source { +func (ctx *local) MachineChecked(features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source { <-ctx.setupDone ctx.serv.TriagedCorpus() return ctx.cfg.MachineChecked(features, syscalls) diff --git a/pkg/rpcserver/mocks/Manager.go b/pkg/rpcserver/mocks/Manager.go index 0c14c8c9f..810b5028f 100644 --- a/pkg/rpcserver/mocks/Manager.go +++ b/pkg/rpcserver/mocks/Manager.go @@ -72,17 +72,17 @@ func (_m *Manager) CoverageFilter(modules []*vminfo.KernelModule) []uint64 { return r0 } -// MachineChecked provides a mock function with given fields: info, features, syscalls -func (_m *Manager) MachineChecked(info *flatrpc.InfoRequestRawT, features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source { - ret := _m.Called(info, features, syscalls) +// MachineChecked provides a mock function with given fields: features, syscalls +func (_m *Manager) MachineChecked(features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source { + ret := _m.Called(features, syscalls) if len(ret) == 0 { panic("no return value specified for MachineChecked") } var r0 queue.Source - if rf, ok := ret.Get(0).(func(*flatrpc.InfoRequestRawT, flatrpc.Feature, map[*prog.Syscall]bool) queue.Source); ok { - r0 = rf(info, features, syscalls) + if rf, ok := ret.Get(0).(func(flatrpc.Feature, map[*prog.Syscall]bool) queue.Source); ok { + r0 = rf(features, syscalls) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(queue.Source) diff --git a/pkg/rpcserver/rpcserver.go b/pkg/rpcserver/rpcserver.go index c064e6938..9d259b733 100644 --- a/pkg/rpcserver/rpcserver.go +++ b/pkg/rpcserver/rpcserver.go @@ -48,26 +48,22 @@ type Config struct { DebugTimeouts bool Procs int Slowdown int - // Extra globs that will be requested during machine checking, - // and will be passed to MachineChecked callback. - CheckGlobs []string - pcBase uint64 - localModules []*vminfo.KernelModule + pcBase uint64 + localModules []*vminfo.KernelModule } type RemoteConfig struct { *mgrconfig.Config - Manager Manager - Stats Stats - CheckGlobs []string - Debug bool + Manager Manager + Stats Stats + Debug bool } //go:generate ../../tools/mockery.sh --name Manager --output ./mocks type Manager interface { MaxSignal() signal.Signal BugFrames() (leaks []string, races []string) - MachineChecked(info *flatrpc.InfoRequest, features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source + MachineChecked(features flatrpc.Feature, syscalls map[*prog.Syscall]bool) queue.Source CoverageFilter(modules []*vminfo.KernelModule) []uint64 } @@ -181,7 +177,6 @@ func New(cfg *RemoteConfig) (Server, error) { Slowdown: cfg.Timeouts.Slowdown, pcBase: pcBase, localModules: cfg.LocalModules, - CheckGlobs: cfg.CheckGlobs, }, cfg.Manager), nil } @@ -280,7 +275,6 @@ func (serv *server) handleRunnerConn(runner *Runner, conn *flatrpc.Conn) error { opts.Features = serv.setupFeatures } else { opts.Files = append(opts.Files, serv.checker.CheckFiles()...) - opts.Globs = append(serv.target.RequiredGlobs(), serv.cfg.CheckGlobs...) opts.Features = serv.cfg.Features } @@ -321,11 +315,6 @@ func (serv *server) handleMachineInfo(infoReq *flatrpc.InfoRequestRawT) (handsha serv.StatModules.Add(len(modules)) serv.canonicalModules = cover.NewCanonicalizer(modules, serv.cfg.Cover) serv.coverFilter = serv.mgr.CoverageFilter(modules) - globs := make(map[string][]string) - for _, glob := range infoReq.Globs { - globs[glob.Name] = glob.Files - } - serv.target.UpdateGlobs(globs) // Flatbuffers don't do deep copy of byte slices, // so clone manually since we pass it a goroutine. for _, file := range infoReq.Files { @@ -395,7 +384,7 @@ func (serv *server) runCheck(info *flatrpc.InfoRequest) error { } enabledFeatures := features.Enabled() serv.setupFeatures = features.NeedSetup() - newSource := serv.mgr.MachineChecked(info, enabledFeatures, enabledCalls) + newSource := serv.mgr.MachineChecked(enabledFeatures, enabledCalls) serv.baseSource.Store(newSource) serv.checkDone.Store(true) return nil diff --git a/pkg/rpcserver/runner.go b/pkg/rpcserver/runner.go index 29e79bad5..9ac1a6866 100644 --- a/pkg/rpcserver/runner.go +++ b/pkg/rpcserver/runner.go @@ -69,7 +69,6 @@ type handshakeConfig struct { LeakFrames []string RaceFrames []string Files []string - Globs []string Features flatrpc.Feature // Callback() is called in the middle of the handshake process. @@ -102,7 +101,6 @@ func (runner *Runner) Handshake(conn *flatrpc.Conn, cfg *handshakeConfig) error LeakFrames: cfg.LeakFrames, RaceFrames: cfg.RaceFrames, Files: cfg.Files, - Globs: cfg.Globs, Features: cfg.Features, } if err := flatrpc.Send(conn, connectReply); err != nil { @@ -292,7 +290,8 @@ func (runner *Runner) sendRequest(req *queue.Request) error { opts.EnvFlags |= flatrpc.ExecEnvDebug } var data []byte - if req.BinaryFile == "" { + switch req.Type { + case flatrpc.RequestTypeProgram: progData, err := req.Prog.SerializeForExec() if err != nil { // It's bad if we systematically fail to serialize programs, @@ -303,8 +302,7 @@ func (runner *Runner) sendRequest(req *queue.Request) error { return nil } data = progData - } else { - flags |= flatrpc.RequestFlagIsBinary + case flatrpc.RequestTypeBinary: fileData, err := os.ReadFile(req.BinaryFile) if err != nil { req.Done(&queue.Result{ @@ -314,6 +312,11 @@ func (runner *Runner) sendRequest(req *queue.Request) error { return nil } data = fileData + case flatrpc.RequestTypeGlob: + data = append([]byte(req.GlobPattern), 0) + flags |= flatrpc.RequestFlagReturnOutput + default: + panic("unhandled request type") } var avoid uint64 for _, id := range req.Avoid { @@ -326,8 +329,9 @@ func (runner *Runner) sendRequest(req *queue.Request) error { Type: flatrpc.HostMessagesRawExecRequest, Value: &flatrpc.ExecRequest{ Id: id, + Type: req.Type, Avoid: avoid, - ProgData: data, + Data: data, Flags: flags, ExecOpts: &opts, AllSignal: allSignal, @@ -361,7 +365,18 @@ func (runner *Runner) handleExecutingMessage(msg *flatrpc.ExecutingMessage) erro } else { runner.stats.statExecRetries.Add(1) } - runner.lastExec.Note(int(msg.Id), proc, req.Prog.Serialize(), osutil.MonotonicNano()) + var data []byte + switch req.Type { + case flatrpc.RequestTypeProgram: + data = req.Prog.Serialize() + case flatrpc.RequestTypeBinary: + data = []byte(fmt.Sprintf("executing binary %v\n", req.BinaryFile)) + case flatrpc.RequestTypeGlob: + data = []byte(fmt.Sprintf("expanding glob: %v\n", req.GlobPattern)) + default: + panic(fmt.Sprintf("unhandled request type %v", req.Type)) + } + runner.lastExec.Note(int(msg.Id), proc, data, osutil.MonotonicNano()) select { case runner.injectExec <- true: default: @@ -385,7 +400,7 @@ func (runner *Runner) handleExecResult(msg *flatrpc.ExecResult) error { } delete(runner.requests, msg.Id) delete(runner.executing, msg.Id) - if msg.Info != nil { + if req.Type == flatrpc.RequestTypeProgram && msg.Info != nil { for len(msg.Info.Calls) < len(req.Prog.Calls) { msg.Info.Calls = append(msg.Info.Calls, &flatrpc.CallInfo{ Error: 999, diff --git a/pkg/runtest/run.go b/pkg/runtest/run.go index ca3ed3b4b..d9f0aa25a 100644 --- a/pkg/runtest/run.go +++ b/pkg/runtest/run.go @@ -113,7 +113,7 @@ func (ctx *Context) Run(waitCtx context.Context) error { if !verbose || ctx.Verbose { ctx.log("%-38v: %v", req.name, result) } - if req.Request != nil && req.Request.BinaryFile != "" { + if req.Request != nil && req.Type == flatrpc.RequestTypeBinary && req.BinaryFile != "" { os.Remove(req.BinaryFile) } } @@ -400,6 +400,7 @@ func (ctx *Context) createTest(req *runRequest) { req.Request.Done(&queue.Result{}) return } + req.Type = flatrpc.RequestTypeBinary req.BinaryFile = bin ctx.submit(req) }() @@ -493,7 +494,7 @@ func checkResult(req *runRequest) error { return fmt.Errorf("non-successful result status (%v)", req.result.Status) } infos := []*flatrpc.ProgInfo{req.result.Info} - isC := req.BinaryFile != "" + isC := req.Type == flatrpc.RequestTypeBinary if isC { var err error if infos, err = parseBinOutput(req); err != nil { diff --git a/pkg/vminfo/syscalls.go b/pkg/vminfo/syscalls.go index 21ae6edd1..9793cfee8 100644 --- a/pkg/vminfo/syscalls.go +++ b/pkg/vminfo/syscalls.go @@ -57,7 +57,8 @@ func newCheckContext(ctx context.Context, cfg *Config, impl checker, executor qu } } -func (ctx *checkContext) start(fileInfos []*flatrpc.FileInfo) { +func (ctx *checkContext) do(fileInfos []*flatrpc.FileInfo, featureInfos []*flatrpc.FeatureInfo) ( + map[*prog.Syscall]bool, map[*prog.Syscall]string, Features, error) { sysTarget := targets.Get(ctx.cfg.Target.OS, ctx.cfg.Target.Arch) ctx.fs = createVirtualFilesystem(fileInfos) for _, id := range ctx.cfg.Syscalls { @@ -91,10 +92,37 @@ func (ctx *checkContext) start(fileInfos []*flatrpc.FileInfo) { }() } ctx.startFeaturesCheck() -} -func (ctx *checkContext) wait(featureInfos []*flatrpc.FeatureInfo) ( - map[*prog.Syscall]bool, map[*prog.Syscall]string, Features, error) { + var globReqs []*queue.Request + for _, glob := range ctx.target.RequiredGlobs() { + req := &queue.Request{ + Type: flatrpc.RequestTypeGlob, + GlobPattern: glob, + ExecOpts: flatrpc.ExecOpts{ + EnvFlags: ctx.cfg.Sandbox, + SandboxArg: ctx.cfg.SandboxArg, + }, + Important: true, + } + ctx.executor.Submit(req) + globReqs = append(globReqs, req) + } + + // Up to this point we submit all requests (start submitting goroutines), + // so that all requests execute in parallel. After this point we wait + // for request completion and handle results. + + globs := make(map[string][]string) + for _, req := range globReqs { + res := req.Wait(ctx.ctx) + if res.Status != queue.Success { + return nil, nil, nil, fmt.Errorf("failed to execute glob: %w (%v)\n%s\n%s", + res.Err, res.Status, req.GlobPattern, res.Output) + } + globs[req.GlobPattern] = res.GlobFiles() + } + ctx.target.UpdateGlobs(globs) + enabled := make(map[*prog.Syscall]bool) disabled := make(map[*prog.Syscall]string) for i := 0; i < ctx.pendingSyscalls; i++ { diff --git a/pkg/vminfo/vminfo.go b/pkg/vminfo/vminfo.go index d2a728585..dee1924b5 100644 --- a/pkg/vminfo/vminfo.go +++ b/pkg/vminfo/vminfo.go @@ -103,8 +103,7 @@ func (checker *Checker) Run(files []*flatrpc.FileInfo, featureInfos []*flatrpc.F map[*prog.Syscall]bool, map[*prog.Syscall]string, Features, error) { ctx := checker.checkContext checker.checkContext = nil - ctx.start(files) - return ctx.wait(featureInfos) + return ctx.do(files, featureInfos) } // Implementation of the queue.Source interface. diff --git a/pkg/vminfo/vminfo_test.go b/pkg/vminfo/vminfo_test.go index 398cf93e2..4bdccc09e 100644 --- a/pkg/vminfo/vminfo_test.go +++ b/pkg/vminfo/vminfo_test.go @@ -104,18 +104,23 @@ func createSuccessfulResults(source queue.Source, stop chan struct{}) { // Currently we have 641 (when we failed to properly dedup syscall tests, it was 4349). panic("too many test programs") } - info := &flatrpc.ProgInfo{} - for range req.Prog.Calls { - info.Calls = append(info.Calls, &flatrpc.CallInfo{ - Cover: []uint64{1}, - Signal: []uint64{1}, - Comps: []*flatrpc.Comparison{{Op1: 1, Op2: 2}}, - }) - } - req.Done(&queue.Result{ + res := &queue.Result{ Status: queue.Success, - Info: info, - }) + } + switch req.Type { + case flatrpc.RequestTypeProgram: + res.Info = &flatrpc.ProgInfo{} + for range req.Prog.Calls { + res.Info.Calls = append(res.Info.Calls, &flatrpc.CallInfo{ + Cover: []uint64{1}, + Signal: []uint64{1}, + Comps: []*flatrpc.Comparison{{Op1: 1, Op2: 2}}, + }) + } + case flatrpc.RequestTypeGlob: + res.Output = []byte("/some/file\n") + } + req.Done(res) } } |
