github.com/panjjo/go@v0.0.0-20161104043856-d62b31386338/src/cmd/objdump/objdump_test.go (about) 1 // Copyright 2014 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package main 6 7 import ( 8 "flag" 9 "fmt" 10 "go/build" 11 "internal/testenv" 12 "io/ioutil" 13 "os" 14 "os/exec" 15 "path/filepath" 16 "runtime" 17 "strings" 18 "testing" 19 ) 20 21 var tmp, exe string // populated by buildObjdump 22 23 func TestMain(m *testing.M) { 24 flag.Parse() 25 if !testenv.HasGoBuild() { 26 return 27 } 28 var exitcode int 29 if err := buildObjdump(); err == nil { 30 exitcode = m.Run() 31 } else { 32 fmt.Println(err) 33 exitcode = 1 34 } 35 os.RemoveAll(tmp) 36 os.Exit(exitcode) 37 } 38 39 func buildObjdump() error { 40 var err error 41 tmp, err = ioutil.TempDir("", "TestObjDump") 42 if err != nil { 43 return fmt.Errorf("TempDir failed: %v", err) 44 } 45 46 exe = filepath.Join(tmp, "testobjdump.exe") 47 gotool, err := testenv.GoTool() 48 if err != nil { 49 return err 50 } 51 out, err := exec.Command(gotool, "build", "-o", exe, "cmd/objdump").CombinedOutput() 52 if err != nil { 53 os.RemoveAll(tmp) 54 return fmt.Errorf("go build -o %v cmd/objdump: %v\n%s", exe, err, string(out)) 55 } 56 57 return nil 58 } 59 60 var x86Need = []string{ 61 "fmthello.go:6", 62 "TEXT main.main(SB)", 63 "JMP main.main(SB)", 64 "CALL fmt.Println(SB)", 65 "RET", 66 } 67 68 var armNeed = []string{ 69 "fmthello.go:6", 70 "TEXT main.main(SB)", 71 //"B.LS main.main(SB)", // TODO(rsc): restore; golang.org/issue/9021 72 "BL fmt.Println(SB)", 73 "RET", 74 } 75 76 var ppcNeed = []string{ 77 "fmthello.go:6", 78 "TEXT main.main(SB)", 79 "BR main.main(SB)", 80 "CALL fmt.Println(SB)", 81 "RET", 82 } 83 84 var target = flag.String("target", "", "test disassembly of `goos/goarch` binary") 85 86 // objdump is fully cross platform: it can handle binaries 87 // from any known operating system and architecture. 88 // We could in principle add binaries to testdata and check 89 // all the supported systems during this test. However, the 90 // binaries would be about 1 MB each, and we don't want to 91 // add that much junk to the hg repository. Instead, build a 92 // binary for the current system (only) and test that objdump 93 // can handle that one. 94 95 func testDisasm(t *testing.T, flags ...string) { 96 goarch := runtime.GOARCH 97 if *target != "" { 98 f := strings.Split(*target, "/") 99 if len(f) != 2 { 100 t.Fatalf("-target argument must be goos/goarch") 101 } 102 defer os.Setenv("GOOS", os.Getenv("GOOS")) 103 defer os.Setenv("GOARCH", os.Getenv("GOARCH")) 104 os.Setenv("GOOS", f[0]) 105 os.Setenv("GOARCH", f[1]) 106 goarch = f[1] 107 } 108 109 hello := filepath.Join(tmp, "hello.exe") 110 args := []string{"build", "-o", hello} 111 args = append(args, flags...) 112 args = append(args, "testdata/fmthello.go") 113 out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput() 114 if err != nil { 115 t.Fatalf("go build fmthello.go: %v\n%s", err, out) 116 } 117 need := []string{ 118 "fmthello.go:6", 119 "TEXT main.main(SB)", 120 } 121 switch goarch { 122 case "amd64", "386": 123 need = append(need, x86Need...) 124 case "arm": 125 need = append(need, armNeed...) 126 case "ppc64", "ppc64le": 127 need = append(need, ppcNeed...) 128 } 129 130 out, err = exec.Command(exe, "-s", "main.main", hello).CombinedOutput() 131 if err != nil { 132 t.Fatalf("objdump fmthello.exe: %v\n%s", err, out) 133 } 134 135 text := string(out) 136 ok := true 137 for _, s := range need { 138 if !strings.Contains(text, s) { 139 t.Errorf("disassembly missing '%s'", s) 140 ok = false 141 } 142 } 143 if !ok { 144 t.Logf("full disassembly:\n%s", text) 145 } 146 } 147 148 func TestDisasm(t *testing.T) { 149 switch runtime.GOARCH { 150 case "arm64": 151 t.Skipf("skipping on %s, issue 10106", runtime.GOARCH) 152 case "mips", "mipsle", "mips64", "mips64le": 153 t.Skipf("skipping on %s, issue 12559", runtime.GOARCH) 154 case "s390x": 155 t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) 156 } 157 testDisasm(t) 158 } 159 160 func TestDisasmExtld(t *testing.T) { 161 switch runtime.GOOS { 162 case "plan9", "windows": 163 t.Skipf("skipping on %s", runtime.GOOS) 164 } 165 switch runtime.GOARCH { 166 case "ppc64": 167 t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH) 168 case "arm64": 169 t.Skipf("skipping on %s, issue 10106", runtime.GOARCH) 170 case "mips64", "mips64le": 171 t.Skipf("skipping on %s, issue 12559 and 12560", runtime.GOARCH) 172 case "s390x": 173 t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) 174 } 175 // TODO(jsing): Reenable once openbsd/arm has external linking support. 176 if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" { 177 t.Skip("skipping on openbsd/arm, no support for external linking, issue 10619") 178 } 179 if !build.Default.CgoEnabled { 180 t.Skip("skipping because cgo is not enabled") 181 } 182 testDisasm(t, "-ldflags=-linkmode=external") 183 }