• 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
4package targets
5
6import (
7	"os"
8	"os/exec"
9	"runtime"
10	"strings"
11	"sync"
12)
13
14type Target struct {
15	init sync.Once
16	osCommon
17	OS               string
18	Arch             string
19	VMArch           string // e.g. amd64 for 386, or arm64 for arm
20	PtrSize          uint64
21	PageSize         uint64
22	NumPages         uint64
23	DataOffset       uint64
24	CFlags           []string
25	CrossCFlags      []string
26	CCompilerPrefix  string
27	CCompiler        string
28	KernelArch       string
29	KernelHeaderArch string
30	// NeedSyscallDefine is used by csource package to decide when to emit __NR_* defines.
31	NeedSyscallDefine func(nr uint64) bool
32}
33
34type osCommon struct {
35	// Does the OS use syscall numbers (e.g. Linux) or has interface based on functions (e.g. fuchsia).
36	SyscallNumbers bool
37	// E.g. "__NR_" or "SYS_".
38	SyscallPrefix string
39	// ipc<->executor communication tuning.
40	// If ExecutorUsesShmem, programs and coverage are passed through shmem, otherwise via pipes.
41	ExecutorUsesShmem bool
42	// If ExecutorUsesForkServer, executor uses extended protocol with handshake.
43	ExecutorUsesForkServer bool
44	// Extension of executable files (notably, .exe for windows).
45	ExeExtension string
46}
47
48func Get(OS, arch string) *Target {
49	target := List[OS][arch]
50	if target == nil {
51		return nil
52	}
53	target.init.Do(func() {
54		checkStaticBuild(target)
55	})
56	return target
57}
58
59// nolint: lll
60var List = map[string]map[string]*Target{
61	"test": {
62		"64": {
63			PtrSize:     8,
64			PageSize:    4 << 10,
65			CFlags:      []string{"-m64"},
66			CrossCFlags: []string{"-m64", "-static"},
67			osCommon: osCommon{
68				SyscallNumbers:         true,
69				SyscallPrefix:          "SYS_",
70				ExecutorUsesShmem:      false,
71				ExecutorUsesForkServer: false,
72			},
73		},
74		"64_fork": {
75			PtrSize:     8,
76			PageSize:    8 << 10,
77			CFlags:      []string{"-m64"},
78			CrossCFlags: []string{"-m64", "-static"},
79			osCommon: osCommon{
80				SyscallNumbers:         true,
81				SyscallPrefix:          "SYS_",
82				ExecutorUsesShmem:      false,
83				ExecutorUsesForkServer: true,
84			},
85		},
86		"32_shmem": {
87			PtrSize:     4,
88			PageSize:    8 << 10,
89			CFlags:      []string{"-m32"},
90			CrossCFlags: []string{"-m32", "-static"},
91			osCommon: osCommon{
92				SyscallNumbers:         true,
93				SyscallPrefix:          "SYS_",
94				ExecutorUsesShmem:      true,
95				ExecutorUsesForkServer: false,
96			},
97		},
98		"32_fork_shmem": {
99			PtrSize:     4,
100			PageSize:    4 << 10,
101			CFlags:      []string{"-m32"},
102			CrossCFlags: []string{"-m32", "-static"},
103			osCommon: osCommon{
104				SyscallNumbers:         true,
105				SyscallPrefix:          "SYS_",
106				ExecutorUsesShmem:      true,
107				ExecutorUsesForkServer: true,
108			},
109		},
110	},
111	"linux": {
112		"amd64": {
113			PtrSize:          8,
114			PageSize:         4 << 10,
115			CFlags:           []string{"-m64"},
116			CrossCFlags:      []string{"-m64", "-static"},
117			CCompilerPrefix:  "x86_64-linux-gnu-",
118			KernelArch:       "x86_64",
119			KernelHeaderArch: "x86",
120			NeedSyscallDefine: func(nr uint64) bool {
121				// Only generate defines for new syscalls
122				// (added after commit 8a1ab3155c2ac on 2012-10-04).
123				return nr >= 313
124			},
125		},
126		"386": {
127			VMArch:           "amd64",
128			PtrSize:          4,
129			PageSize:         4 << 10,
130			CFlags:           []string{"-m32"},
131			CrossCFlags:      []string{"-m32", "-static"},
132			CCompilerPrefix:  "x86_64-linux-gnu-",
133			KernelArch:       "i386",
134			KernelHeaderArch: "x86",
135		},
136		"arm64": {
137			PtrSize:          8,
138			PageSize:         4 << 10,
139			CrossCFlags:      []string{"-static"},
140			CCompilerPrefix:  "aarch64-linux-gnu-",
141			KernelArch:       "arm64",
142			KernelHeaderArch: "arm64",
143		},
144		"arm": {
145			VMArch:           "arm64",
146			PtrSize:          4,
147			PageSize:         4 << 10,
148			CFlags:           []string{"-D__LINUX_ARM_ARCH__=6", "-m32", "-D__ARM_EABI__"},
149			CrossCFlags:      []string{"-D__LINUX_ARM_ARCH__=6", "-march=armv6t2", "-static"},
150			CCompilerPrefix:  "arm-linux-gnueabihf-",
151			KernelArch:       "arm",
152			KernelHeaderArch: "arm",
153		},
154		"ppc64le": {
155			PtrSize:          8,
156			PageSize:         4 << 10,
157			CFlags:           []string{"-D__powerpc64__"},
158			CrossCFlags:      []string{"-D__powerpc64__", "-static"},
159			CCompilerPrefix:  "powerpc64le-linux-gnu-",
160			KernelArch:       "powerpc",
161			KernelHeaderArch: "powerpc",
162		},
163	},
164	"freebsd": {
165		"amd64": {
166			PtrSize:     8,
167			PageSize:    4 << 10,
168			CFlags:      []string{"-m64"},
169			CrossCFlags: []string{"-m64", "-static"},
170		},
171	},
172	"netbsd": {
173		"amd64": {
174			PtrSize:     8,
175			PageSize:    4 << 10,
176			CFlags:      []string{"-m64"},
177			CrossCFlags: []string{"-m64", "-static"},
178		},
179	},
180	"fuchsia": {
181		"amd64": {
182			PtrSize:          8,
183			PageSize:         4 << 10,
184			KernelHeaderArch: "x64",
185			CCompiler:        os.ExpandEnv("${SOURCEDIR}/buildtools/linux-x64/clang/bin/clang++"),
186			CrossCFlags: []string{
187				"-Wno-deprecated",
188				"-Wno-error",
189				"--target=x86_64-fuchsia",
190				"-lfdio",
191				"-lzircon",
192				"-ldriver",
193				"--sysroot", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-x64/sysroot"),
194				"-L", os.ExpandEnv("${SOURCEDIR}/out/x64/x64-shared"),
195				"-L", os.ExpandEnv("${SOURCEDIR}/out/x64/sdks/zircon_sysroot/arch/x64/sysroot/lib"),
196				"-L", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-x64/system/ulib/driver"),
197			},
198		},
199		"arm64": {
200			PtrSize:          8,
201			PageSize:         4 << 10,
202			KernelHeaderArch: "arm64",
203			CCompiler:        os.ExpandEnv("${SOURCEDIR}/buildtools/linux-x64/clang/bin/clang++"),
204			CrossCFlags: []string{
205				"-Wno-deprecated",
206				"-Wno-error",
207				"--target=aarch64-fuchsia",
208				"-lfdio",
209				"-lzircon",
210				"-ldriver",
211				"--sysroot", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-arm64/sysroot"),
212				"-L", os.ExpandEnv("${SOURCEDIR}/out/arm64/arm64-shared"),
213				"-L", os.ExpandEnv("${SOURCEDIR}/out/arm64/sdks/zircon_sysroot/arch/arm64/sysroot/lib"),
214				"-L", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-arm64/system/ulib/driver"),
215			},
216		},
217	},
218	"windows": {
219		"amd64": {
220			PtrSize: 8,
221			// TODO(dvyukov): what should we do about 4k vs 64k?
222			PageSize: 4 << 10,
223		},
224	},
225	"akaros": {
226		"amd64": {
227			PtrSize:           8,
228			PageSize:          4 << 10,
229			KernelHeaderArch:  "x86",
230			NeedSyscallDefine: dontNeedSyscallDefine,
231			CCompiler:         os.ExpandEnv("${SOURCEDIR}/toolchain/x86_64-ucb-akaros-gcc/bin/x86_64-ucb-akaros-g++"),
232			CrossCFlags: []string{
233				"-static",
234			},
235		},
236	},
237}
238
239var oses = map[string]osCommon{
240	"linux": {
241		SyscallNumbers:         true,
242		SyscallPrefix:          "__NR_",
243		ExecutorUsesShmem:      true,
244		ExecutorUsesForkServer: true,
245	},
246	"freebsd": {
247		SyscallNumbers:         true,
248		SyscallPrefix:          "SYS_",
249		ExecutorUsesShmem:      true,
250		ExecutorUsesForkServer: true,
251	},
252	"netbsd": {
253		SyscallNumbers:         true,
254		SyscallPrefix:          "SYS_",
255		ExecutorUsesShmem:      true,
256		ExecutorUsesForkServer: true,
257	},
258	"fuchsia": {
259		SyscallNumbers:         false,
260		ExecutorUsesShmem:      false,
261		ExecutorUsesForkServer: false,
262	},
263	"windows": {
264		SyscallNumbers:         false,
265		ExecutorUsesShmem:      false,
266		ExecutorUsesForkServer: false,
267		ExeExtension:           ".exe",
268	},
269	"akaros": {
270		SyscallNumbers:         true,
271		SyscallPrefix:          "SYS_",
272		ExecutorUsesShmem:      false,
273		ExecutorUsesForkServer: true,
274	},
275}
276
277func init() {
278	for OS, archs := range List {
279		for arch, target := range archs {
280			initTarget(target, OS, arch)
281		}
282	}
283}
284
285func initTarget(target *Target, OS, arch string) {
286	if common, ok := oses[OS]; ok {
287		target.osCommon = common
288	}
289	target.OS = OS
290	target.Arch = arch
291	if target.NeedSyscallDefine == nil {
292		target.NeedSyscallDefine = needSyscallDefine
293	}
294	target.DataOffset = 512 << 20
295	target.NumPages = (16 << 20) / target.PageSize
296	if OS == runtime.GOOS && arch == runtime.GOARCH {
297		// Don't use cross-compiler for native compilation, there are cases when this does not work:
298		// https://github.com/google/syzkaller/pull/619
299		// https://github.com/google/syzkaller/issues/387
300		// https://github.com/google/syzkaller/commit/06db3cec94c54e1cf720cdd5db72761514569d56
301		target.CCompilerPrefix = ""
302	}
303	if target.CCompiler == "" {
304		target.CCompiler = target.CCompilerPrefix + "gcc"
305	}
306}
307
308func checkStaticBuild(target *Target) {
309	for i, flag := range target.CrossCFlags {
310		if flag == "-static" {
311			// Some distributions don't have static libraries.
312			if !supportsStatic(target) {
313				copy(target.CrossCFlags[i:], target.CrossCFlags[i+1:])
314				target.CrossCFlags = target.CrossCFlags[:len(target.CrossCFlags)-1]
315			}
316			break
317		}
318	}
319}
320
321func supportsStatic(target *Target) bool {
322	cmd := exec.Command(target.CCompiler, "-x", "c", "-", "-o", "/dev/null", "-static")
323	cmd.Stdin = strings.NewReader("int main(){}")
324	return cmd.Run() == nil
325}
326
327func needSyscallDefine(nr uint64) bool {
328	return true
329}
330func dontNeedSyscallDefine(nr uint64) bool {
331	return false
332}
333