diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2015-12-23 13:38:31 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2015-12-23 13:38:31 +0100 |
| commit | e253cbc79fc20b65ce9dd965c6fe3adddac817ca (patch) | |
| tree | 3a64c5a18d8b0a020c3cee24abbfe32fc468fc86 /prog | |
| parent | 071ad4e91f95f115236a639e934181c7e596f337 (diff) | |
csource: new package
Move C source generation into a separate package.
Prog is too bloated already.
Diffstat (limited to 'prog')
| -rw-r--r-- | prog/encodingc.go | 117 | ||||
| -rw-r--r-- | prog/encodingexec.go | 42 | ||||
| -rw-r--r-- | prog/prog_test.go | 8 |
3 files changed, 23 insertions, 144 deletions
diff --git a/prog/encodingc.go b/prog/encodingc.go deleted file mode 100644 index c22180ce5..000000000 --- a/prog/encodingc.go +++ /dev/null @@ -1,117 +0,0 @@ -// 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" - "fmt" - "io" - "unsafe" - - "github.com/google/syzkaller/sys" -) - -func (p *Prog) WriteCSource() []byte { - exec := p.SerializeForExec() - buf := new(bytes.Buffer) - writeCSource(buf, exec) - return buf.Bytes() -} - -func writeCSource(w io.Writer, exec []byte) { - fmt.Fprintf(w, `// autogenerated by syzkaller (http://github.com/google/syzkaller) -#include <syscall.h> -#include <string.h> -#include <stdint.h> - -int main() -{ -`) - read := func() uintptr { - if len(exec) < 8 { - panic("exec program overflow") - } - v := *(*uint64)(unsafe.Pointer(&exec[0])) - exec = exec[8:] - return uintptr(v) - } - resultRef := func() string { - arg := read() - res := fmt.Sprintf("r%v", arg) - if opDiv := read(); opDiv != 0 { - res = fmt.Sprintf("%v/%v", res, opDiv) - } - if opAdd := read(); opAdd != 0 { - res = fmt.Sprintf("%v+%v", res, opAdd) - } - return res - } - lastCall := 0 - for n := 0; ; n++ { - switch instr := read(); instr { - case instrEOF: - fmt.Fprintf(w, "\treturn 0;\n}\n") - return - case instrCopyin: - addr := read() - typ := read() - size := read() - switch typ { - case execArgConst: - arg := read() - fmt.Fprintf(w, "\t*(uint%v_t*)0x%x = 0x%x;\n", size*8, addr, arg) - case execArgResult: - fmt.Fprintf(w, "\t*(uint%v_t*)0x%x = %v;\n", size*8, addr, resultRef()) - case execArgData: - data := exec[:size] - exec = exec[(size+7)/8*8:] - var esc []byte - for _, v := range data { - hex := func(v byte) byte { - if v < 10 { - return '0' + v - } - return 'a' + v - 10 - } - esc = append(esc, '\\', 'x', hex(v>>4), hex(v<<4>>4)) - } - fmt.Fprintf(w, "\tmemcpy((void*)0x%x, \"%s\", %v);\n", addr, esc, size) - default: - panic("bad argument type") - } - case instrCopyout: - addr := read() - size := read() - fmt.Fprintf(w, "\tlong r%v = -1;\n", n) - fmt.Fprintf(w, "\tif (r%v != -1)\n", lastCall) - fmt.Fprintf(w, "\t\tr%v = *(uint%v_t*)0x%x;\n", n, size*8, addr) - case instrSetPad, instrCheckPad: - read() // addr - read() // size - default: - // Normal syscall. - meta := sys.Calls[instr] - fmt.Fprintf(w, "\tlong r%v = syscall(SYS_%v", n, meta.CallName) - nargs := read() - for i := uintptr(0); i < nargs; i++ { - typ := read() - size := read() - _ = size - switch typ { - case execArgConst: - fmt.Fprintf(w, ", 0x%xul", read()) - case execArgResult: - fmt.Fprintf(w, ", %v", resultRef()) - default: - panic("unknown arg type") - } - } - for i := nargs; i < 6; i++ { - fmt.Fprintf(w, ", 0") - } - fmt.Fprintf(w, ");\n") - lastCall = n - } - } -} diff --git a/prog/encodingexec.go b/prog/encodingexec.go index f23d98c5d..7c75eccc9 100644 --- a/prog/encodingexec.go +++ b/prog/encodingexec.go @@ -6,18 +6,22 @@ package prog +import ( + "fmt" +) + const ( - instrEOF = ^uintptr(iota) - instrCopyin - instrCopyout - instrSetPad - instrCheckPad + ExecInstrEOF = ^uintptr(iota) + ExecInstrCopyin + ExecInstrCopyout + ExecInstrSetPad + ExecInstrCheckPad ) const ( - execArgConst = uintptr(iota) - execArgResult - execArgData + ExecArgConst = uintptr(iota) + ExecArgResult + ExecArgData ) const ( @@ -28,7 +32,7 @@ const ( func (p *Prog) SerializeForExec() []byte { if err := p.validate(); err != nil { - panic("serializing invalid program") + panic(fmt.Errorf("serializing invalid program: %v", err)) } var instrSeq uintptr w := &execContext{args: make(map[*Arg]*argInfo)} @@ -61,11 +65,11 @@ func (p *Prog) SerializeForExec() []byte { pad, padSize := arg1.IsPad() if (arg1.Dir == DirIn && !pad) || (arg1.Dir == DirOut && pad) || arg1.Dir == DirInOut { if pad { - w.write(instrSetPad) + w.write(ExecInstrSetPad) w.write(physicalAddr(arg) + w.args[arg1].Offset) w.write(padSize) } else { - w.write(instrCopyin) + w.write(ExecInstrCopyin) w.write(physicalAddr(arg) + w.args[arg1].Offset) w.writeArg(arg1) } @@ -89,7 +93,7 @@ func (p *Prog) SerializeForExec() []byte { if pad && arg.Dir != DirIn { instrSeq++ info := w.args[arg] - w.write(instrCheckPad) + w.write(ExecInstrCheckPad) w.write(physicalAddr(base) + info.Offset) w.write(padSize) return @@ -108,7 +112,7 @@ func (p *Prog) SerializeForExec() []byte { info := w.args[arg] info.Idx = instrSeq instrSeq++ - w.write(instrCopyout) + w.write(ExecInstrCopyout) w.write(physicalAddr(base) + info.Offset) w.write(arg.Size(arg.Type)) default: @@ -116,7 +120,7 @@ func (p *Prog) SerializeForExec() []byte { } }) } - w.write(instrEOF) + w.write(ExecInstrEOF) return w.buf } @@ -151,25 +155,25 @@ func (w *execContext) write(v uintptr) { func (w *execContext) writeArg(arg *Arg) { switch arg.Kind { case ArgConst: - w.write(execArgConst) + w.write(ExecArgConst) w.write(arg.Size(arg.Type)) w.write(arg.Val) case ArgResult: - w.write(execArgResult) + w.write(ExecArgResult) w.write(arg.Size(arg.Type)) w.write(w.args[arg.Res].Idx) w.write(arg.OpDiv) w.write(arg.OpAdd) case ArgPointer: - w.write(execArgConst) + w.write(ExecArgConst) w.write(arg.Size(arg.Type)) w.write(physicalAddr(arg)) case ArgPageSize: - w.write(execArgConst) + w.write(ExecArgConst) w.write(arg.Size(arg.Type)) w.write(arg.AddrPage * pageSize) case ArgData: - w.write(execArgData) + w.write(ExecArgData) w.write(uintptr(len(arg.Data))) for i := 0; i < len(arg.Data); i += 8 { var v uintptr diff --git a/prog/prog_test.go b/prog/prog_test.go index d308ba36b..7a4abbb3a 100644 --- a/prog/prog_test.go +++ b/prog/prog_test.go @@ -54,11 +54,3 @@ func TestSerializeForExec(t *testing.T) { p.SerializeForExec() } } - -func TestSerializeC(t *testing.T) { - rs, iters := initTest(t) - for i := 0; i < iters; i++ { - p := Generate(rs, 10, nil) - p.WriteCSource() - } -} |
