• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Copyright 2017 syzkaller project authors. All rights reserved.
2// Use of this source code is governed by Apache 2 LICENSE that can be found in the LICENSE file.
3
4//go:generate go run gen.go
5
6package csource
7
8import (
9	"bytes"
10	"fmt"
11	"sort"
12	"strings"
13
14	"github.com/google/syzkaller/pkg/osutil"
15	"github.com/google/syzkaller/prog"
16	"github.com/google/syzkaller/sys/targets"
17)
18
19const (
20	linux = "linux"
21
22	sandboxNone      = "none"
23	sandboxSetuid    = "setuid"
24	sandboxNamespace = "namespace"
25)
26
27func createCommonHeader(p, mmapProg *prog.Prog, replacements map[string]string, opts Options) ([]byte, error) {
28	defines := defineList(p, mmapProg, opts)
29	cmd := osutil.Command("cpp", "-nostdinc", "-undef", "-fdirectives-only", "-dDI", "-E", "-P", "-")
30	for _, def := range defines {
31		cmd.Args = append(cmd.Args, "-D"+def)
32	}
33	cmd.Stdin = strings.NewReader(commonHeader)
34	stderr := new(bytes.Buffer)
35	stdout := new(bytes.Buffer)
36	cmd.Stderr = stderr
37	cmd.Stdout = stdout
38	if err := cmd.Run(); len(stdout.Bytes()) == 0 {
39		return nil, fmt.Errorf("cpp failed: %v\n%v\n%v", err, stdout.String(), stderr.String())
40	}
41
42	src, err := removeSystemDefines(stdout.Bytes(), defines)
43	if err != nil {
44		return nil, err
45	}
46
47	for from, to := range replacements {
48		src = bytes.Replace(src, []byte("[["+from+"]]"), []byte(to), -1)
49	}
50
51	for from, to := range map[string]string{
52		"uint64": "uint64_t",
53		"uint32": "uint32_t",
54		"uint16": "uint16_t",
55		"uint8":  "uint8_t",
56	} {
57		src = bytes.Replace(src, []byte(from), []byte(to), -1)
58	}
59
60	return src, nil
61}
62
63func defineList(p, mmapProg *prog.Prog, opts Options) (defines []string) {
64	sysTarget := targets.Get(p.Target.OS, p.Target.Arch)
65	bitmasks, csums := prog.RequiredFeatures(p)
66	enabled := map[string]bool{
67		"GOOS_" + p.Target.OS:           true,
68		"GOARCH_" + p.Target.Arch:       true,
69		"SYZ_USE_BITMASKS":              bitmasks,
70		"SYZ_USE_CHECKSUMS":             csums,
71		"SYZ_SANDBOX_NONE":              opts.Sandbox == sandboxNone,
72		"SYZ_SANDBOX_SETUID":            opts.Sandbox == sandboxSetuid,
73		"SYZ_SANDBOX_NAMESPACE":         opts.Sandbox == sandboxNamespace,
74		"SYZ_THREADED":                  opts.Threaded,
75		"SYZ_COLLIDE":                   opts.Collide,
76		"SYZ_REPEAT":                    opts.Repeat,
77		"SYZ_REPEAT_TIMES":              opts.RepeatTimes > 1,
78		"SYZ_PROCS":                     opts.Procs > 1,
79		"SYZ_FAULT_INJECTION":           opts.Fault,
80		"SYZ_TUN_ENABLE":                opts.EnableTun,
81		"SYZ_ENABLE_CGROUPS":            opts.EnableCgroups,
82		"SYZ_ENABLE_NETDEV":             opts.EnableNetdev,
83		"SYZ_RESET_NET_NAMESPACE":       opts.ResetNet,
84		"SYZ_USE_TMP_DIR":               opts.UseTmpDir,
85		"SYZ_HANDLE_SEGV":               opts.HandleSegv,
86		"SYZ_REPRO":                     opts.Repro,
87		"SYZ_TRACE":                     opts.Trace,
88		"SYZ_EXECUTOR_USES_SHMEM":       sysTarget.ExecutorUsesShmem,
89		"SYZ_EXECUTOR_USES_FORK_SERVER": sysTarget.ExecutorUsesForkServer,
90	}
91	for def, ok := range enabled {
92		if ok {
93			defines = append(defines, def)
94		}
95	}
96	for _, c := range p.Calls {
97		defines = append(defines, "__NR_"+c.Meta.CallName)
98	}
99	for _, c := range mmapProg.Calls {
100		defines = append(defines, "__NR_"+c.Meta.CallName)
101	}
102	sort.Strings(defines)
103	return
104}
105
106func removeSystemDefines(src []byte, defines []string) ([]byte, error) {
107	remove := map[string]string{
108		"__STDC__":        "1",
109		"__STDC_HOSTED__": "1",
110		"__STDC_UTF_16__": "1",
111		"__STDC_UTF_32__": "1",
112	}
113	for _, def := range defines {
114		eq := strings.IndexByte(def, '=')
115		if eq == -1 {
116			remove[def] = "1"
117		} else {
118			remove[def[:eq]] = def[eq+1:]
119		}
120	}
121	for def, val := range remove {
122		src = bytes.Replace(src, []byte("#define "+def+" "+val+"\n"), nil, -1)
123	}
124	// strip: #define __STDC_VERSION__ 201112L
125	for _, def := range []string{"__STDC_VERSION__"} {
126		pos := bytes.Index(src, []byte("#define "+def))
127		if pos == -1 {
128			continue
129		}
130		end := bytes.IndexByte(src[pos:], '\n')
131		if end == -1 {
132			continue
133		}
134		src = bytes.Replace(src, src[pos:end+1], nil, -1)
135	}
136	return src, nil
137}
138