aboutsummaryrefslogtreecommitdiffstats
path: root/prog
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2015-12-23 13:38:31 +0100
committerDmitry Vyukov <dvyukov@google.com>2015-12-23 13:38:31 +0100
commite253cbc79fc20b65ce9dd965c6fe3adddac817ca (patch)
tree3a64c5a18d8b0a020c3cee24abbfe32fc468fc86 /prog
parent071ad4e91f95f115236a639e934181c7e596f337 (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.go117
-rw-r--r--prog/encodingexec.go42
-rw-r--r--prog/prog_test.go8
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()
- }
-}