From 6284466bc9b948ccf0bfbdb4c80475712d1883c0 Mon Sep 17 00:00:00 2001 From: Dmitry Vyukov Date: Mon, 26 Feb 2018 18:21:51 +0100 Subject: prog: properly squash bitfields --- executor/syscalls_test.h | 4 ++-- prog/any.go | 34 +++++++++++++++++++++++++++++----- prog/any_test.go | 4 ++-- sys/test/32.go | 14 ++++++++++++-- sys/test/64.go | 14 ++++++++++++-- sys/test/any.txt | 12 +++++++++++- 6 files changed, 68 insertions(+), 14 deletions(-) diff --git a/executor/syscalls_test.h b/executor/syscalls_test.h index db1591e1f..aa35c1fef 100644 --- a/executor/syscalls_test.h +++ b/executor/syscalls_test.h @@ -2,7 +2,7 @@ #if 0 #define GOARCH "32" -#define SYZ_REVISION "0d78e9b1f441c9ae33361f9778195af0a245ffdd" +#define SYZ_REVISION "10a1935b1f3ef8f206e29a3b6863de4cac10bd9e" #define SYZ_PAGE_SIZE 8192 #define SYZ_NUM_PAGES 2048 #define SYZ_DATA_OFFSET 536870912 @@ -104,7 +104,7 @@ call_t syscalls[] = { #if 0 #define GOARCH "64" -#define SYZ_REVISION "e361957ea430829459298bc20840e4edbd324930" +#define SYZ_REVISION "7c718fa299ed570a4acbd25a1fcf2448c4e2a2d4" #define SYZ_PAGE_SIZE 4096 #define SYZ_NUM_PAGES 4096 #define SYZ_DATA_OFFSET 536870912 diff --git a/prog/any.go b/prog/any.go index 32c2fdaa6..76e9723b5 100644 --- a/prog/any.go +++ b/prog/any.go @@ -209,7 +209,7 @@ func (target *Target) squashPtr(arg *PointerArg, preserveField bool) { } func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { - if a.Type().BitfieldMiddle() { + if a.Type().BitfieldLength() != 0 { panic("bitfield in squash") } var pad uint64 @@ -218,8 +218,7 @@ func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { if IsPad(arg.Type()) { pad = arg.Size() } else { - // Note: we need a constant value, but it depends on pid for proc. - v := arg.ValueForProc(0) + v := target.squashConst(arg) elem := target.ensureDataElem(elems) for i := uint64(0); i < arg.Size(); i++ { elem.data = append(elem.Data(), byte(v)) @@ -272,9 +271,23 @@ func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { pad = typ.AlignAttr - fieldsSize%typ.AlignAttr } } + var bitfield uint64 for _, fld := range arg.Inner { - if fld.Type().BitfieldMiddle() { - // TODO(dvyukov): handle bitfields + // Squash bitfields separately. + if bfLen := fld.Type().BitfieldLength(); bfLen != 0 { + bfOff := fld.Type().BitfieldOffset() + // Note: we can have a ResultArg here as well, + // but it is unsupported at the moment. + v := target.squashConst(fld.(*ConstArg)) + bitfield |= (v & ((1 << bfLen) - 1)) << bfOff + if !fld.Type().BitfieldMiddle() { + elem := target.ensureDataElem(elems) + for i := uint64(0); i < fld.Size(); i++ { + elem.data = append(elem.Data(), byte(bitfield)) + bitfield >>= 8 + } + bitfield = 0 + } continue } target.squashPtrImpl(fld, elems) @@ -288,6 +301,17 @@ func (target *Target) squashPtrImpl(a Arg, elems *[]Arg) { } } +func (target *Target) squashConst(arg *ConstArg) uint64 { + // Note: we need a constant value, but it depends on pid for proc. + v := arg.ValueForProc(0) + if _, ok := arg.Type().(*CsumType); ok { + // We can't compute value for the checksum here, + // but at least leave something recognizable by hints code. + v = 0xabcdef1234567890 + } + return v +} + func (target *Target) ensureDataElem(elems *[]Arg) *DataArg { if len(*elems) == 0 { res := MakeDataArg(target.anyBlob, nil) diff --git a/prog/any_test.go b/prog/any_test.go index 104f77f9d..dee9246ea 100644 --- a/prog/any_test.go +++ b/prog/any_test.go @@ -39,8 +39,8 @@ func TestSquash(t *testing.T) { squashed string }{ { - `foo$any0(&(0x7f0000000000)={0x11, 0x11223344, 0x2233, 0x1122334455667788, [{0x0, @res32=0x0, 0x0, @i8=0x44, "aabb"}, {0x0, @res64=0x1, 0x0, @i32=0x11223344, "1122334455667788"}]})`, - `foo$any0(&(0x7f0000000000)=ANY=[@ANYBLOB="1100000044332211223300000000000088776655443322110000000000000000", @ANYRES32=0x0, @ANYBLOB="00000000000000000000000044aabb000000000000000000", @ANYRES64=0x1, @ANYBLOB="0000000000000000443322111122334455667788"])`, + `foo$any0(&(0x7f0000000000)={0x11, 0x11223344, 0x2233, 0x1122334455667788, {0x1, 0x7, 0x1, 0x1, 0x1bc, 0x4}, [{0x0, @res32=0x0, 0x0, @i8=0x44, "aabb"}, {0x0, @res64=0x1, 0x0, @i32=0x11223344, "1122334455667788"}]})`, + `foo$any0(&(0x7f0000000000)=ANY=[@ANYBLOB="1100000044332211223300000000000088776655443322113d0079230000000000000000", @ANYRES32=0x0, @ANYBLOB="00000000000000000000000044aabb000000000000000000", @ANYRES64=0x1, @ANYBLOB="000000000000000044332211112233445566778800000000"])`, }, } for i, test := range tests { diff --git a/sys/test/32.go b/sys/test/32.go index ca7c3715e..8b3dc2892 100644 --- a/sys/test/32.go +++ b/sys/test/32.go @@ -23,7 +23,8 @@ var structDescs_32 = []*KeyedStruct{ &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16be", FldName: "f3", TypeSize: 2}, BigEndian: true}}, &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 6}}, IsPad: true}, &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int64", FldName: "f4", TypeSize: 8}}}, - &ArrayType{TypeCommon: TypeCommon{TypeName: "array", FldName: "f5", IsVarlen: true}, Type: &StructType{Key: StructKey{Name: "any1"}}}, + &StructType{Key: StructKey{Name: "anybitfields"}, FldName: "f5"}, + &ArrayType{TypeCommon: TypeCommon{TypeName: "array", FldName: "f6", IsVarlen: true}, Type: &StructType{Key: StructKey{Name: "any1"}}}, }, AlignAttr: 8}}, {Key: StructKey{Name: "any1"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "any1", IsVarlen: true}, Fields: []Type{ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "f1", TypeSize: 4, IsOptional: true}, Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", TypeSize: 1}}}}, @@ -32,6 +33,15 @@ var structDescs_32 = []*KeyedStruct{ &UnionType{Key: StructKey{Name: "anyunion1"}, FldName: "f4"}, &BufferType{TypeCommon: TypeCommon{TypeName: "array", FldName: "f5", IsVarlen: true}}, }, AlignAttr: 2}}, + {Key: StructKey{Name: "anybitfields"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "anybitfields", TypeSize: 4}, Fields: []Type{ + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f1", TypeSize: 1}, BitfieldLen: 2, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f2", TypeSize: 1}, BitfieldOff: 2, BitfieldLen: 3, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f3", TypeSize: 1}, BitfieldOff: 5, BitfieldLen: 1}}, + &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 1}}, IsPad: true}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f4", TypeSize: 2}, BitfieldLen: 1, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f5", TypeSize: 2}, BitfieldOff: 1, BitfieldLen: 10, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f6", TypeSize: 2}, BitfieldOff: 11, BitfieldLen: 3}}, + }}}, {Key: StructKey{Name: "anyunion0"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "anyunion0", TypeSize: 8}, Fields: []Type{ &ResourceType{TypeCommon: TypeCommon{TypeName: "anyres32", FldName: "res32", TypeSize: 4}}, &ResourceType{TypeCommon: TypeCommon{TypeName: "anyres64", FldName: "res64", TypeSize: 8}}, @@ -772,4 +782,4 @@ var consts_32 = []ConstValue{ {Name: "ONLY_32BITS_CONST", Value: 1}, } -const revision_32 = "0d78e9b1f441c9ae33361f9778195af0a245ffdd" +const revision_32 = "10a1935b1f3ef8f206e29a3b6863de4cac10bd9e" diff --git a/sys/test/64.go b/sys/test/64.go index 9407c1873..ed996452d 100644 --- a/sys/test/64.go +++ b/sys/test/64.go @@ -23,7 +23,8 @@ var structDescs_64 = []*KeyedStruct{ &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16be", FldName: "f3", TypeSize: 2}, BigEndian: true}}, &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 6}}, IsPad: true}, &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int64", FldName: "f4", TypeSize: 8}}}, - &ArrayType{TypeCommon: TypeCommon{TypeName: "array", FldName: "f5", IsVarlen: true}, Type: &StructType{Key: StructKey{Name: "any1"}}}, + &StructType{Key: StructKey{Name: "anybitfields"}, FldName: "f5"}, + &ArrayType{TypeCommon: TypeCommon{TypeName: "array", FldName: "f6", IsVarlen: true}, Type: &StructType{Key: StructKey{Name: "any1"}}}, }, AlignAttr: 8}}, {Key: StructKey{Name: "any1"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "any1", IsVarlen: true}, Fields: []Type{ &PtrType{TypeCommon: TypeCommon{TypeName: "ptr", FldName: "f1", TypeSize: 8, IsOptional: true}, Type: &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", TypeSize: 1}}}}, @@ -32,6 +33,15 @@ var structDescs_64 = []*KeyedStruct{ &UnionType{Key: StructKey{Name: "anyunion1"}, FldName: "f4"}, &BufferType{TypeCommon: TypeCommon{TypeName: "array", FldName: "f5", IsVarlen: true}}, }, AlignAttr: 2}}, + {Key: StructKey{Name: "anybitfields"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "anybitfields", TypeSize: 4}, Fields: []Type{ + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f1", TypeSize: 1}, BitfieldLen: 2, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f2", TypeSize: 1}, BitfieldOff: 2, BitfieldLen: 3, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int8", FldName: "f3", TypeSize: 1}, BitfieldOff: 5, BitfieldLen: 1}}, + &ConstType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "pad", TypeSize: 1}}, IsPad: true}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f4", TypeSize: 2}, BitfieldLen: 1, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f5", TypeSize: 2}, BitfieldOff: 1, BitfieldLen: 10, BitfieldMdl: true}}, + &IntType{IntTypeCommon: IntTypeCommon{TypeCommon: TypeCommon{TypeName: "int16", FldName: "f6", TypeSize: 2}, BitfieldOff: 11, BitfieldLen: 3}}, + }}}, {Key: StructKey{Name: "anyunion0"}, Desc: &StructDesc{TypeCommon: TypeCommon{TypeName: "anyunion0", TypeSize: 8}, Fields: []Type{ &ResourceType{TypeCommon: TypeCommon{TypeName: "anyres32", FldName: "res32", TypeSize: 4}}, &ResourceType{TypeCommon: TypeCommon{TypeName: "anyres64", FldName: "res64", TypeSize: 8}}, @@ -770,4 +780,4 @@ var consts_64 = []ConstValue{ {Name: "IPPROTO_UDP", Value: 17}, } -const revision_64 = "e361957ea430829459298bc20840e4edbd324930" +const revision_64 = "7c718fa299ed570a4acbd25a1fcf2448c4e2a2d4" diff --git a/sys/test/any.txt b/sys/test/any.txt index 6a4e285ac..b0a0d0162 100644 --- a/sys/test/any.txt +++ b/sys/test/any.txt @@ -13,7 +13,8 @@ any0 { f2 int32 f3 int16be f4 int64 - f5 array[any1] + f5 anybitfields + f6 array[any1] } [align_8] any1 { @@ -33,3 +34,12 @@ anyunion1 [ i8 int8 i32 int32 ] [varlen] + +anybitfields { + f1 int8:2 + f2 int8:3 + f3 int8:1 + f4 int16:1 + f5 int16:10 + f6 int16:3 +} -- cgit mrf-deployment