diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-09-14 21:27:56 +0200 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-09-15 16:02:37 +0200 |
| commit | 19f9bc13d374058b83b2712f119bb42559b35c0c (patch) | |
| tree | 2e2744f8f1e3036736e3535ae776ff1409bf5368 /pkg | |
| parent | 52a33fd516102a98d3753bf69417235b655a68dc (diff) | |
pkg/csource: support archs other than x86_64
Diffstat (limited to 'pkg')
| -rw-r--r-- | pkg/csource/csource.go | 68 | ||||
| -rw-r--r-- | pkg/csource/csource_test.go | 24 | ||||
| -rw-r--r-- | pkg/ipc/ipc_test.go | 21 | ||||
| -rw-r--r-- | pkg/repro/repro.go | 2 |
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 } |
