aboutsummaryrefslogtreecommitdiffstats
path: root/pkg
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-09-14 21:27:56 +0200
committerDmitry Vyukov <dvyukov@google.com>2017-09-15 16:02:37 +0200
commit19f9bc13d374058b83b2712f119bb42559b35c0c (patch)
tree2e2744f8f1e3036736e3535ae776ff1409bf5368 /pkg
parent52a33fd516102a98d3753bf69417235b655a68dc (diff)
pkg/csource: support archs other than x86_64
Diffstat (limited to 'pkg')
-rw-r--r--pkg/csource/csource.go68
-rw-r--r--pkg/csource/csource_test.go24
-rw-r--r--pkg/ipc/ipc_test.go21
-rw-r--r--pkg/repro/repro.go2
4 files changed, 82 insertions, 33 deletions
diff --git a/pkg/csource/csource.go b/pkg/csource/csource.go
index 8b7c84ad3..10059dd9b 100644
--- a/pkg/csource/csource.go
+++ b/pkg/csource/csource.go
@@ -20,7 +20,7 @@ import (
"unsafe"
"github.com/google/syzkaller/prog"
- _ "github.com/google/syzkaller/sys"
+ "github.com/google/syzkaller/sys"
)
type Options struct {
@@ -83,24 +83,34 @@ func Write(p *prog.Prog, opts Options) ([]byte, error) {
for _, c := range p.Calls {
handled[c.Meta.CallName] = c.Meta.NR
}
- for name, nr := range handled {
- // Only generate defines for new syscalls (added after commit 8a1ab3155c2ac on 2012-10-04).
- // TODO: the syscall number 313 implies that we're dealing with linux/amd64.
- if nr >= 313 && !strings.HasPrefix(name, "syz_") {
- fmt.Fprintf(w, "#ifndef __NR_%v\n", name)
- fmt.Fprintf(w, "#define __NR_%v %v\n", name, nr)
- fmt.Fprintf(w, "#endif\n")
- }
- }
- fmt.Fprintf(w, "\n")
-
- hdr, err := preprocessCommonHeader(opts, handled, prog.RequiresBitmasks(p), prog.RequiresChecksums(p))
+ hdr, err := preprocessCommonHeader(p.Target, opts, handled, prog.RequiresBitmasks(p), prog.RequiresChecksums(p))
if err != nil {
return nil, err
}
fmt.Fprint(w, hdr)
fmt.Fprint(w, "\n")
+ for name, nr := range handled {
+ if strings.HasPrefix(name, "syz_") {
+ continue
+ }
+ if p.Target.OS == "linux" && p.Target.Arch == "amd64" && nr < 313 {
+ // Only generate defines for new syscalls (added after commit 8a1ab3155c2ac on 2012-10-04).
+ continue
+ }
+ fmt.Fprintf(w, "#ifndef __NR_%v\n", name)
+ fmt.Fprintf(w, "#define __NR_%v %v\n", name, nr)
+ fmt.Fprintf(w, "#endif\n")
+ }
+ if p.Target.OS == "linux" && p.Target.PtrSize == 4 {
+ // This is a dirty hack.
+ // On 32-bit linux mmap translated to old_mmap syscall which has a different signature.
+ // mmap2 has the right signature. executor translates mmap to mmap2, do the same here.
+ fmt.Fprintf(w, "#undef __NR_mmap\n")
+ fmt.Fprintf(w, "#define __NR_mmap __NR_mmap2\n")
+ }
+ fmt.Fprintf(w, "\n")
+
calls, nvar := generateCalls(p.Target, exec, opts)
fmt.Fprintf(w, "long r[%v];\n", nvar)
@@ -420,7 +430,7 @@ loop:
return calls, n
}
-func preprocessCommonHeader(opts Options, handled map[string]uint64, useBitmasks, useChecksums bool) (string, error) {
+func preprocessCommonHeader(target *prog.Target, opts Options, handled map[string]uint64, useBitmasks, useChecksums bool) (string, error) {
var defines []string
if useBitmasks {
defines = append(defines, "SYZ_USE_BITMASKS")
@@ -470,8 +480,9 @@ func preprocessCommonHeader(opts Options, handled map[string]uint64, useBitmasks
for name, _ := range handled {
defines = append(defines, "__NR_"+name)
}
- // TODO: need to know target arch + do cross-compilation
- defines = append(defines, "__x86_64__")
+
+ sysTarget := sys.Targets[target.OS][target.Arch]
+ defines = append(defines, sysTarget.CArch...)
cmd := exec.Command("cpp", "-nostdinc", "-undef", "-fdirectives-only", "-dDI", "-E", "-P", "-")
for _, def := range defines {
@@ -512,25 +523,42 @@ func preprocessCommonHeader(opts Options, handled map[string]uint64, useBitmasks
// Build builds a C/C++ program from source src and returns name of the resulting binary.
// lang can be "c" or "c++".
-func Build(lang, src string) (string, error) {
+func Build(target *prog.Target, lang, src string) (string, error) {
bin, err := ioutil.TempFile("", "syzkaller")
if err != nil {
return "", fmt.Errorf("failed to create temp file: %v", err)
}
bin.Close()
- out, err := exec.Command("gcc", "-x", lang, "-Wall", "-Werror", src, "-o", bin.Name(), "-pthread", "-static", "-O1", "-g").CombinedOutput()
+ sysTarget := sys.Targets[target.OS][target.Arch]
+ compiler := sysTarget.CCompilerPrefix + "gcc"
+ if _, err := exec.LookPath(compiler); err != nil {
+ return "", NoCompilerErr
+ }
+ flags := []string{
+ "-x", lang, "-Wall", "-Werror", "-O1", "-g", "-o", bin.Name(),
+ src, "-pthread",
+ }
+ flags = append(flags, sysTarget.CrossCFlags...)
+ if sysTarget.PtrSize == 4 {
+ // We do generate uint64's for syscall arguments that overflow longs on 32-bit archs.
+ flags = append(flags, "-Wno-overflow")
+ }
+ out, err := exec.Command(compiler, append(flags, "-static")...).CombinedOutput()
if err != nil {
// Some distributions don't have static libraries.
- out, err = exec.Command("gcc", "-x", lang, "-Wall", "-Werror", src, "-o", bin.Name(), "-pthread", "-O1", "-g").CombinedOutput()
+ out, err = exec.Command(compiler, flags...).CombinedOutput()
}
if err != nil {
os.Remove(bin.Name())
data, _ := ioutil.ReadFile(src)
- return "", fmt.Errorf("failed to build program:\n%s\n%s", data, out)
+ return "", fmt.Errorf("failed to build program:\n%s\n%s\ncompiler invocation: %v %v\n",
+ data, out, compiler, flags)
}
return bin.Name(), nil
}
+var NoCompilerErr = errors.New("no target compiler")
+
// Format reformats C source using clang-format.
func Format(src []byte) ([]byte, error) {
stdout, stderr := new(bytes.Buffer), new(bytes.Buffer)
diff --git a/pkg/csource/csource_test.go b/pkg/csource/csource_test.go
index c192566e3..2ac048da2 100644
--- a/pkg/csource/csource_test.go
+++ b/pkg/csource/csource_test.go
@@ -89,7 +89,7 @@ func allOptionsPermutations() []Options {
}
func TestOne(t *testing.T) {
- target, rs, _ := initTest(t)
+ t.Parallel()
opts := Options{
Threaded: true,
Collide: true,
@@ -99,8 +99,21 @@ func TestOne(t *testing.T) {
Repro: true,
UseTmpDir: true,
}
- p := target.GenerateAllSyzProg(rs)
- testOne(t, p, opts)
+ for _, target := range prog.AllTargets() {
+ target := target
+ t.Run(target.OS+"/"+target.Arch, func(t *testing.T) {
+ if target.OS == "linux" && target.Arch == "arm" {
+ // This currently fails (at least with my arm-linux-gnueabihf-gcc-4.8) with:
+ // Assembler messages:
+ // Error: alignment too large: 15 assumed
+ t.Skip("broken")
+ }
+ t.Parallel()
+ rs := rand.NewSource(0)
+ p := target.GenerateAllSyzProg(rs)
+ testOne(t, p, opts)
+ })
+ }
}
func TestOptions(t *testing.T) {
@@ -142,7 +155,10 @@ func testOne(t *testing.T, p *prog.Prog, opts Options) {
t.Fatalf("%v", err)
}
defer os.Remove(srcf)
- bin, err := Build("c", srcf)
+ bin, err := Build(p.Target, "c", srcf)
+ if err == NoCompilerErr {
+ t.Skip(err)
+ }
if err != nil {
t.Logf("program:\n%s\n", p.Serialize())
t.Fatalf("%v", err)
diff --git a/pkg/ipc/ipc_test.go b/pkg/ipc/ipc_test.go
index 263e94032..d52579553 100644
--- a/pkg/ipc/ipc_test.go
+++ b/pkg/ipc/ipc_test.go
@@ -19,21 +19,21 @@ import (
const timeout = 10 * time.Second
-func buildExecutor(t *testing.T) string {
- return buildProgram(t, filepath.FromSlash("../../executor/executor.cc"))
+func buildExecutor(t *testing.T, target *prog.Target) string {
+ return buildProgram(t, target, filepath.FromSlash("../../executor/executor.cc"))
}
-func buildSource(t *testing.T, src []byte) string {
+func buildSource(t *testing.T, target *prog.Target, src []byte) string {
tmp, err := osutil.WriteTempFile(src)
if err != nil {
t.Fatalf("%v", err)
}
defer os.Remove(tmp)
- return buildProgram(t, tmp)
+ return buildProgram(t, target, tmp)
}
-func buildProgram(t *testing.T, src string) string {
- bin, err := csource.Build("c++", src)
+func buildProgram(t *testing.T, target *prog.Target, src string) string {
+ bin, err := csource.Build(target, "c++", src)
if err != nil {
t.Fatalf("%v", err)
}
@@ -53,7 +53,12 @@ func initTest(t *testing.T) (rand.Source, int) {
}
func TestEmptyProg(t *testing.T) {
- bin := buildExecutor(t)
+ target, err := prog.GetTarget("linux", runtime.GOARCH)
+ if err != nil {
+ t.Fatal(err)
+ }
+
+ bin := buildExecutor(t, target)
defer os.Remove(bin)
cfg := Config{
@@ -88,7 +93,7 @@ func TestExecute(t *testing.T) {
t.Fatal(err)
}
- bin := buildExecutor(t)
+ bin := buildExecutor(t, target)
defer os.Remove(bin)
for _, flag := range flags {
diff --git a/pkg/repro/repro.go b/pkg/repro/repro.go
index 4787b0262..21d35677f 100644
--- a/pkg/repro/repro.go
+++ b/pkg/repro/repro.go
@@ -558,7 +558,7 @@ func (ctx *context) testCProg(p *prog.Prog, duration time.Duration, opts csource
if err != nil {
return false, err
}
- bin, err := csource.Build("c", srcf)
+ bin, err := csource.Build(p.Target, "c", srcf)
if err != nil {
return false, err
}