aboutsummaryrefslogtreecommitdiffstats
path: root/pkg/csource/build.go
diff options
context:
space:
mode:
authorDmitry Vyukov <dvyukov@google.com>2017-12-15 11:25:19 +0100
committerDmitry Vyukov <dvyukov@google.com>2017-12-17 11:39:14 +0100
commit431d3c90b1a4a31a6156ad1cd5fc692af3b1a314 (patch)
treefbea978cb14e1daac37e8c9625a18ea18d6c2355 /pkg/csource/build.go
parent9004acd9cc20a77e5227326a1ad4a0bcbc03316d (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.go86
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,
+}`