// 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 targets import ( "os" "os/exec" "runtime" "strings" "sync" ) type Target struct { init sync.Once osCommon OS string Arch string VMArch string // e.g. amd64 for 386, or arm64 for arm PtrSize uint64 PageSize uint64 NumPages uint64 DataOffset uint64 CFlags []string CrossCFlags []string CCompilerPrefix string CCompiler string KernelArch string KernelHeaderArch string // NeedSyscallDefine is used by csource package to decide when to emit __NR_* defines. NeedSyscallDefine func(nr uint64) bool } type osCommon struct { // Does the OS use syscall numbers (e.g. Linux) or has interface based on functions (e.g. fuchsia). SyscallNumbers bool // E.g. "__NR_" or "SYS_". SyscallPrefix string // ipc<->executor communication tuning. // If ExecutorUsesShmem, programs and coverage are passed through shmem, otherwise via pipes. ExecutorUsesShmem bool // If ExecutorUsesForkServer, executor uses extended protocol with handshake. ExecutorUsesForkServer bool // Extension of executable files (notably, .exe for windows). ExeExtension string } func Get(OS, arch string) *Target { target := List[OS][arch] if target == nil { return nil } target.init.Do(func() { checkStaticBuild(target) }) return target } // nolint: lll var List = map[string]map[string]*Target{ "test": { "64": { PtrSize: 8, PageSize: 4 << 10, CFlags: []string{"-m64"}, CrossCFlags: []string{"-m64", "-static"}, osCommon: osCommon{ SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: false, ExecutorUsesForkServer: false, }, }, "64_fork": { PtrSize: 8, PageSize: 8 << 10, CFlags: []string{"-m64"}, CrossCFlags: []string{"-m64", "-static"}, osCommon: osCommon{ SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: false, ExecutorUsesForkServer: true, }, }, "32_shmem": { PtrSize: 4, PageSize: 8 << 10, CFlags: []string{"-m32"}, CrossCFlags: []string{"-m32", "-static"}, osCommon: osCommon{ SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: true, ExecutorUsesForkServer: false, }, }, "32_fork_shmem": { PtrSize: 4, PageSize: 4 << 10, CFlags: []string{"-m32"}, CrossCFlags: []string{"-m32", "-static"}, osCommon: osCommon{ SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: true, ExecutorUsesForkServer: true, }, }, }, "linux": { "amd64": { PtrSize: 8, PageSize: 4 << 10, CFlags: []string{"-m64"}, CrossCFlags: []string{"-m64", "-static"}, CCompilerPrefix: "x86_64-linux-gnu-", KernelArch: "x86_64", KernelHeaderArch: "x86", NeedSyscallDefine: func(nr uint64) bool { // Only generate defines for new syscalls // (added after commit 8a1ab3155c2ac on 2012-10-04). return nr >= 313 }, }, "386": { VMArch: "amd64", PtrSize: 4, PageSize: 4 << 10, CFlags: []string{"-m32"}, CrossCFlags: []string{"-m32", "-static"}, CCompilerPrefix: "x86_64-linux-gnu-", KernelArch: "i386", KernelHeaderArch: "x86", }, "arm64": { PtrSize: 8, PageSize: 4 << 10, CrossCFlags: []string{"-static"}, CCompilerPrefix: "aarch64-linux-gnu-", KernelArch: "arm64", KernelHeaderArch: "arm64", }, "arm": { VMArch: "arm64", PtrSize: 4, PageSize: 4 << 10, CFlags: []string{"-D__LINUX_ARM_ARCH__=6", "-m32", "-D__ARM_EABI__"}, CrossCFlags: []string{"-D__LINUX_ARM_ARCH__=6", "-march=armv6t2", "-static"}, CCompilerPrefix: "arm-linux-gnueabihf-", KernelArch: "arm", KernelHeaderArch: "arm", }, "ppc64le": { PtrSize: 8, PageSize: 4 << 10, CFlags: []string{"-D__powerpc64__"}, CrossCFlags: []string{"-D__powerpc64__", "-static"}, CCompilerPrefix: "powerpc64le-linux-gnu-", KernelArch: "powerpc", KernelHeaderArch: "powerpc", }, }, "freebsd": { "amd64": { PtrSize: 8, PageSize: 4 << 10, CFlags: []string{"-m64"}, CrossCFlags: []string{"-m64", "-static"}, }, }, "netbsd": { "amd64": { PtrSize: 8, PageSize: 4 << 10, CFlags: []string{"-m64"}, CrossCFlags: []string{"-m64", "-static"}, }, }, "fuchsia": { "amd64": { PtrSize: 8, PageSize: 4 << 10, KernelHeaderArch: "x64", CCompiler: os.ExpandEnv("${SOURCEDIR}/buildtools/linux-x64/clang/bin/clang++"), CrossCFlags: []string{ "-Wno-deprecated", "-Wno-error", "--target=x86_64-fuchsia", "-lfdio", "-lzircon", "-ldriver", "--sysroot", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-x64/sysroot"), "-L", os.ExpandEnv("${SOURCEDIR}/out/x64/x64-shared"), "-L", os.ExpandEnv("${SOURCEDIR}/out/x64/sdks/zircon_sysroot/arch/x64/sysroot/lib"), "-L", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-x64/system/ulib/driver"), }, }, "arm64": { PtrSize: 8, PageSize: 4 << 10, KernelHeaderArch: "arm64", CCompiler: os.ExpandEnv("${SOURCEDIR}/buildtools/linux-x64/clang/bin/clang++"), CrossCFlags: []string{ "-Wno-deprecated", "-Wno-error", "--target=aarch64-fuchsia", "-lfdio", "-lzircon", "-ldriver", "--sysroot", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-arm64/sysroot"), "-L", os.ExpandEnv("${SOURCEDIR}/out/arm64/arm64-shared"), "-L", os.ExpandEnv("${SOURCEDIR}/out/arm64/sdks/zircon_sysroot/arch/arm64/sysroot/lib"), "-L", os.ExpandEnv("${SOURCEDIR}/out/build-zircon/build-arm64/system/ulib/driver"), }, }, }, "windows": { "amd64": { PtrSize: 8, // TODO(dvyukov): what should we do about 4k vs 64k? PageSize: 4 << 10, }, }, "akaros": { "amd64": { PtrSize: 8, PageSize: 4 << 10, KernelHeaderArch: "x86", NeedSyscallDefine: dontNeedSyscallDefine, CCompiler: os.ExpandEnv("${SOURCEDIR}/toolchain/x86_64-ucb-akaros-gcc/bin/x86_64-ucb-akaros-g++"), CrossCFlags: []string{ "-static", }, }, }, } var oses = map[string]osCommon{ "linux": { SyscallNumbers: true, SyscallPrefix: "__NR_", ExecutorUsesShmem: true, ExecutorUsesForkServer: true, }, "freebsd": { SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: true, ExecutorUsesForkServer: true, }, "netbsd": { SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: true, ExecutorUsesForkServer: true, }, "fuchsia": { SyscallNumbers: false, ExecutorUsesShmem: false, ExecutorUsesForkServer: false, }, "windows": { SyscallNumbers: false, ExecutorUsesShmem: false, ExecutorUsesForkServer: false, ExeExtension: ".exe", }, "akaros": { SyscallNumbers: true, SyscallPrefix: "SYS_", ExecutorUsesShmem: false, ExecutorUsesForkServer: true, }, } func init() { for OS, archs := range List { for arch, target := range archs { initTarget(target, OS, arch) } } } func initTarget(target *Target, OS, arch string) { if common, ok := oses[OS]; ok { target.osCommon = common } target.OS = OS target.Arch = arch if target.NeedSyscallDefine == nil { target.NeedSyscallDefine = needSyscallDefine } target.DataOffset = 512 << 20 target.NumPages = (16 << 20) / target.PageSize if OS == runtime.GOOS && arch == runtime.GOARCH { // Don't use cross-compiler for native compilation, there are cases when this does not work: // https://github.com/google/syzkaller/pull/619 // https://github.com/google/syzkaller/issues/387 // https://github.com/google/syzkaller/commit/06db3cec94c54e1cf720cdd5db72761514569d56 target.CCompilerPrefix = "" } if target.CCompiler == "" { target.CCompiler = target.CCompilerPrefix + "gcc" } } func checkStaticBuild(target *Target) { for i, flag := range target.CrossCFlags { if flag == "-static" { // Some distributions don't have static libraries. if !supportsStatic(target) { copy(target.CrossCFlags[i:], target.CrossCFlags[i+1:]) target.CrossCFlags = target.CrossCFlags[:len(target.CrossCFlags)-1] } break } } } func supportsStatic(target *Target) bool { cmd := exec.Command(target.CCompiler, "-x", "c", "-", "-o", "/dev/null", "-static") cmd.Stdin = strings.NewReader("int main(){}") return cmd.Run() == nil } func needSyscallDefine(nr uint64) bool { return true } func dontNeedSyscallDefine(nr uint64) bool { return false }