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