88 "fmt"
99 "math/rand"
1010 "os"
11+ "os/exec"
12+ "path/filepath"
1113 "runtime"
1214 "strings"
1315 "testing"
@@ -24,6 +26,42 @@ import (
2426 "github.com/google/syzkaller/sys/targets"
2527)
2628
29+ // Find the corresponding QEMU binary for the target arch, if needed.
30+ func qemuBinary (arch string ) (string , error ) {
31+ qarch , ok := map [string ]string {
32+ "386" : "i386" ,
33+ "amd64" : "x86_64" ,
34+ "arm64" : "aarch64" ,
35+ "arm" : "arm" ,
36+ "mips64le" : "mips64el" ,
37+ "ppc64le" : "ppc64le" ,
38+ "riscv64" : "riscv64" ,
39+ "s390x" : "s390x" ,
40+ }[arch ]
41+ if ! ok {
42+ return "" , fmt .Errorf ("unsupported architecture: %s" , arch )
43+ }
44+
45+ qemuBinary := "qemu-" + qarch
46+ path , err := exec .LookPath (qemuBinary )
47+ if err != nil {
48+ return "" , fmt .Errorf ("qemu binary not found in PATH: %s" , qemuBinary )
49+ }
50+
51+ return filepath .Base (path ), nil
52+ }
53+
54+ // If the tests are running on CI, or if there is an assertion failure in the executor,
55+ // report a fatal error. Otherwise, assume cross-arch execution does not work, and skip
56+ // the test.
57+ func handleCrossArchError (t * testing.T , err error ) {
58+ if os .Getenv ("CI" ) != "" || strings .Contains (err .Error (), "SYZFAIL:" ) {
59+ t .Fatal (err )
60+ } else {
61+ t .Skipf ("skipping, cross-arch execution failed: %v" , err )
62+ }
63+ }
64+
2765// TestExecutor runs all internal executor unit tests.
2866// We do it here because we already build executor binary here.
2967func TestExecutor (t * testing.T ) {
@@ -41,15 +79,20 @@ func TestExecutor(t *testing.T) {
4179 t .Fatal (err )
4280 }
4381 bin := csource .BuildExecutor (t , target , "../.." )
44- // qemu-user may allow us to run some cross-arch binaries.
45- if _ , err := osutil . RunCmd ( time . Minute , dir , bin , "test" ); err != nil {
46- if sysTarget . Arch == runtime . GOARCH || sysTarget . VMArch == runtime . GOARCH {
82+ if sysTarget . Arch == runtime . GOARCH || sysTarget . VMArch == runtime . GOARCH {
83+ // Execute the tests natively.
84+ if _ , err := osutil . RunCmd ( time . Minute , dir , bin , "test" ); err != nil {
4785 t .Fatal (err )
4886 }
49- if os .Getenv ("CI" ) != "" || strings .Contains (err .Error (), "SYZFAIL:" ) {
50- t .Fatal (err )
51- } else {
52- t .Skipf ("skipping, cross-arch binary failed: %v" , err )
87+ } else {
88+ // Get QEMU binary for the target arch. This code might run inside Docker, so it cannot
89+ // rely on binfmt_misc handlers provided by qemu-user.
90+ qemu , err := qemuBinary (sysTarget .Arch )
91+ if err != nil {
92+ handleCrossArchError (t , err )
93+ }
94+ if _ , err := osutil .RunCmd (time .Minute , dir , qemu , bin , "test" ); err != nil {
95+ handleCrossArchError (t , err )
5396 }
5497 }
5598 })
0 commit comments