diff options
| author | Dmitry Vyukov <dvyukov@google.com> | 2017-12-15 11:25:19 +0100 |
|---|---|---|
| committer | Dmitry Vyukov <dvyukov@google.com> | 2017-12-17 11:39:14 +0100 |
| commit | 431d3c90b1a4a31a6156ad1cd5fc692af3b1a314 (patch) | |
| tree | fbea978cb14e1daac37e8c9625a18ea18d6c2355 /pkg/csource/build.go | |
| parent | 9004acd9cc20a77e5227326a1ad4a0bcbc03316d (diff) | |
pkg/csource: refactor
csource.go is too large and messy.
Move Build/Format into buid.go.
Move generation of common header into common.go.
Split generation of common header into smaller managable functions.
Diffstat (limited to 'pkg/csource/build.go')
| -rw-r--r-- | pkg/csource/build.go | 86 |
1 files changed, 86 insertions, 0 deletions
diff --git a/pkg/csource/build.go b/pkg/csource/build.go new file mode 100644 index 000000000..a059dcaf8 --- /dev/null +++ b/pkg/csource/build.go @@ -0,0 +1,86 @@ +// Copyright 2017 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 csource + +import ( + "bytes" + "errors" + "fmt" + "io/ioutil" + "os" + "os/exec" + + "github.com/google/syzkaller/pkg/osutil" + "github.com/google/syzkaller/prog" + "github.com/google/syzkaller/sys/targets" +) + +// Build builds a C/C++ program from source src and returns name of the resulting binary. +// lang can be "c" or "c++". +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() + sysTarget := targets.List[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 := osutil.Command(compiler, append(flags, "-static")...).CombinedOutput() + if err != nil { + // Some distributions don't have static libraries. + out, err = osutil.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\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) + cmd := osutil.Command("clang-format", "-assume-filename=/src.c", "-style", style) + cmd.Stdin = bytes.NewReader(src) + cmd.Stdout = stdout + cmd.Stderr = stderr + if err := cmd.Run(); err != nil { + return src, fmt.Errorf("failed to format source: %v\n%v", err, stderr.String()) + } + return stdout.Bytes(), nil +} + +// Something acceptable for kernel developers and email-friendly. +var style = `{ +BasedOnStyle: LLVM, +IndentWidth: 2, +UseTab: Never, +BreakBeforeBraces: Linux, +IndentCaseLabels: false, +DerivePointerAlignment: false, +PointerAlignment: Left, +AlignTrailingComments: true, +AllowShortBlocksOnASingleLine: false, +AllowShortCaseLabelsOnASingleLine: false, +AllowShortFunctionsOnASingleLine: false, +AllowShortIfStatementsOnASingleLine: false, +AllowShortLoopsOnASingleLine: false, +ColumnLimit: 72, +}` |
