github.com/sanprasirt/go@v0.0.0-20170607001320-a027466e4b6d/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 if !testenv.HasGoBuild() { 25 return 26 } 27 var exitcode int 28 if err := buildObjdump(); err == nil { 29 exitcode = m.Run() 30 } else { 31 fmt.Println(err) 32 exitcode = 1 33 } 34 os.RemoveAll(tmp) 35 os.Exit(exitcode) 36 } 37 38 func buildObjdump() error { 39 var err error 40 tmp, err = ioutil.TempDir("", "TestObjDump") 41 if err != nil { 42 return fmt.Errorf("TempDir failed: %v", err) 43 } 44 45 exe = filepath.Join(tmp, "testobjdump.exe") 46 gotool, err := testenv.GoTool() 47 if err != nil { 48 return err 49 } 50 out, err := exec.Command(gotool, "build", "-o", exe, "cmd/objdump").CombinedOutput() 51 if err != nil { 52 os.RemoveAll(tmp) 53 return fmt.Errorf("go build -o %v cmd/objdump: %v\n%s", exe, err, string(out)) 54 } 55 56 return nil 57 } 58 59 var x86Need = []string{ 60 "JMP main.main(SB)", 61 "CALL main.Println(SB)", 62 "RET", 63 } 64 65 var armNeed = []string{ 66 //"B.LS main.main(SB)", // TODO(rsc): restore; golang.org/issue/9021 67 "BL main.Println(SB)", 68 "RET", 69 } 70 71 var ppcNeed = []string{ 72 "BR main.main(SB)", 73 "CALL main.Println(SB)", 74 "RET", 75 } 76 77 var target = flag.String("target", "", "test disassembly of `goos/goarch` binary") 78 79 // objdump is fully cross platform: it can handle binaries 80 // from any known operating system and architecture. 81 // We could in principle add binaries to testdata and check 82 // all the supported systems during this test. However, the 83 // binaries would be about 1 MB each, and we don't want to 84 // add that much junk to the hg repository. Instead, build a 85 // binary for the current system (only) and test that objdump 86 // can handle that one. 87 88 func testDisasm(t *testing.T, printCode bool, flags ...string) { 89 goarch := runtime.GOARCH 90 if *target != "" { 91 f := strings.Split(*target, "/") 92 if len(f) != 2 { 93 t.Fatalf("-target argument must be goos/goarch") 94 } 95 defer os.Setenv("GOOS", os.Getenv("GOOS")) 96 defer os.Setenv("GOARCH", os.Getenv("GOARCH")) 97 os.Setenv("GOOS", f[0]) 98 os.Setenv("GOARCH", f[1]) 99 goarch = f[1] 100 } 101 102 hello := filepath.Join(tmp, "hello.exe") 103 args := []string{"build", "-o", hello} 104 args = append(args, flags...) 105 args = append(args, "testdata/fmthello.go") 106 out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput() 107 if err != nil { 108 t.Fatalf("go build fmthello.go: %v\n%s", err, out) 109 } 110 need := []string{ 111 "TEXT main.main(SB)", 112 } 113 114 if printCode { 115 need = append(need, ` Println("hello, world")`) 116 } else { 117 need = append(need, "fmthello.go:6") 118 } 119 120 switch goarch { 121 case "amd64", "386": 122 need = append(need, x86Need...) 123 case "arm": 124 need = append(need, armNeed...) 125 case "ppc64", "ppc64le": 126 need = append(need, ppcNeed...) 127 } 128 129 args = []string{ 130 "-s", "main.main", 131 hello, 132 } 133 134 if printCode { 135 args = append([]string{"-S"}, args...) 136 } 137 138 out, err = exec.Command(exe, args...).CombinedOutput() 139 if err != nil { 140 t.Fatalf("objdump fmthello.exe: %v\n%s", err, out) 141 } 142 143 text := string(out) 144 ok := true 145 for _, s := range need { 146 if !strings.Contains(text, s) { 147 t.Errorf("disassembly missing '%s'", s) 148 ok = false 149 } 150 } 151 if !ok { 152 t.Logf("full disassembly:\n%s", text) 153 } 154 } 155 156 func TestDisasm(t *testing.T) { 157 switch runtime.GOARCH { 158 case "arm64": 159 t.Skipf("skipping on %s, issue 10106", runtime.GOARCH) 160 case "mips", "mipsle", "mips64", "mips64le": 161 t.Skipf("skipping on %s, issue 12559", runtime.GOARCH) 162 case "s390x": 163 t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) 164 } 165 testDisasm(t, false) 166 } 167 168 func TestDisasmCode(t *testing.T) { 169 switch runtime.GOARCH { 170 case "arm64": 171 t.Skipf("skipping on %s, issue 10106", runtime.GOARCH) 172 case "mips", "mipsle", "mips64", "mips64le": 173 t.Skipf("skipping on %s, issue 12559", runtime.GOARCH) 174 case "s390x": 175 t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) 176 } 177 testDisasm(t, true) 178 } 179 180 func TestDisasmExtld(t *testing.T) { 181 switch runtime.GOOS { 182 case "plan9", "windows": 183 t.Skipf("skipping on %s", runtime.GOOS) 184 } 185 switch runtime.GOARCH { 186 case "ppc64": 187 t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH) 188 case "arm64": 189 t.Skipf("skipping on %s, issue 10106", runtime.GOARCH) 190 case "mips64", "mips64le", "mips", "mipsle": 191 t.Skipf("skipping on %s, issue 12559 and 12560", runtime.GOARCH) 192 case "s390x": 193 t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) 194 } 195 // TODO(jsing): Reenable once openbsd/arm has external linking support. 196 if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" { 197 t.Skip("skipping on openbsd/arm, no support for external linking, issue 10619") 198 } 199 if !build.Default.CgoEnabled { 200 t.Skip("skipping because cgo is not enabled") 201 } 202 testDisasm(t, false, "-ldflags=-linkmode=external") 203 } 204 205 func TestDisasmGoobj(t *testing.T) { 206 switch runtime.GOARCH { 207 case "arm": 208 t.Skipf("skipping on %s, issue 19811", runtime.GOARCH) 209 case "arm64": 210 t.Skipf("skipping on %s, issue 10106", runtime.GOARCH) 211 case "mips", "mipsle", "mips64", "mips64le": 212 t.Skipf("skipping on %s, issue 12559", runtime.GOARCH) 213 case "s390x": 214 t.Skipf("skipping on %s, issue 15255", runtime.GOARCH) 215 } 216 217 hello := filepath.Join(tmp, "hello.o") 218 args := []string{"tool", "compile", "-o", hello} 219 args = append(args, "testdata/fmthello.go") 220 out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput() 221 if err != nil { 222 t.Fatalf("go tool compile fmthello.go: %v\n%s", err, out) 223 } 224 need := []string{ 225 "main(SB)", 226 "fmthello.go:6", 227 } 228 229 args = []string{ 230 "-s", "main", 231 hello, 232 } 233 234 out, err = exec.Command(exe, args...).CombinedOutput() 235 if err != nil { 236 t.Fatalf("objdump fmthello.o: %v\n%s", err, out) 237 } 238 239 text := string(out) 240 ok := true 241 for _, s := range need { 242 if !strings.Contains(text, s) { 243 t.Errorf("disassembly missing '%s'", s) 244 ok = false 245 } 246 } 247 if !ok { 248 t.Logf("full disassembly:\n%s", text) 249 } 250 }