github.com/muesli/go@v0.0.0-20170208044820-e410d2a81ef2/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  	"fmthello.go:6",
    61  	"TEXT main.main(SB)",
    62  	"JMP main.main(SB)",
    63  	"CALL fmt.Println(SB)",
    64  	"RET",
    65  }
    66  
    67  var armNeed = []string{
    68  	"fmthello.go:6",
    69  	"TEXT main.main(SB)",
    70  	//"B.LS main.main(SB)", // TODO(rsc): restore; golang.org/issue/9021
    71  	"BL fmt.Println(SB)",
    72  	"RET",
    73  }
    74  
    75  var ppcNeed = []string{
    76  	"fmthello.go:6",
    77  	"TEXT main.main(SB)",
    78  	"BR main.main(SB)",
    79  	"CALL fmt.Println(SB)",
    80  	"RET",
    81  }
    82  
    83  var target = flag.String("target", "", "test disassembly of `goos/goarch` binary")
    84  
    85  // objdump is fully cross platform: it can handle binaries
    86  // from any known operating system and architecture.
    87  // We could in principle add binaries to testdata and check
    88  // all the supported systems during this test. However, the
    89  // binaries would be about 1 MB each, and we don't want to
    90  // add that much junk to the hg repository. Instead, build a
    91  // binary for the current system (only) and test that objdump
    92  // can handle that one.
    93  
    94  func testDisasm(t *testing.T, flags ...string) {
    95  	goarch := runtime.GOARCH
    96  	if *target != "" {
    97  		f := strings.Split(*target, "/")
    98  		if len(f) != 2 {
    99  			t.Fatalf("-target argument must be goos/goarch")
   100  		}
   101  		defer os.Setenv("GOOS", os.Getenv("GOOS"))
   102  		defer os.Setenv("GOARCH", os.Getenv("GOARCH"))
   103  		os.Setenv("GOOS", f[0])
   104  		os.Setenv("GOARCH", f[1])
   105  		goarch = f[1]
   106  	}
   107  
   108  	hello := filepath.Join(tmp, "hello.exe")
   109  	args := []string{"build", "-o", hello}
   110  	args = append(args, flags...)
   111  	args = append(args, "testdata/fmthello.go")
   112  	out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
   113  	if err != nil {
   114  		t.Fatalf("go build fmthello.go: %v\n%s", err, out)
   115  	}
   116  	need := []string{
   117  		"fmthello.go:6",
   118  		"TEXT main.main(SB)",
   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  	out, err = exec.Command(exe, "-s", "main.main", hello).CombinedOutput()
   130  	if err != nil {
   131  		t.Fatalf("objdump fmthello.exe: %v\n%s", err, out)
   132  	}
   133  
   134  	text := string(out)
   135  	ok := true
   136  	for _, s := range need {
   137  		if !strings.Contains(text, s) {
   138  			t.Errorf("disassembly missing '%s'", s)
   139  			ok = false
   140  		}
   141  	}
   142  	if !ok {
   143  		t.Logf("full disassembly:\n%s", text)
   144  	}
   145  }
   146  
   147  func TestDisasm(t *testing.T) {
   148  	switch runtime.GOARCH {
   149  	case "arm64":
   150  		t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
   151  	case "mips", "mipsle", "mips64", "mips64le":
   152  		t.Skipf("skipping on %s, issue 12559", runtime.GOARCH)
   153  	case "s390x":
   154  		t.Skipf("skipping on %s, issue 15255", runtime.GOARCH)
   155  	}
   156  	testDisasm(t)
   157  }
   158  
   159  func TestDisasmExtld(t *testing.T) {
   160  	switch runtime.GOOS {
   161  	case "plan9", "windows":
   162  		t.Skipf("skipping on %s", runtime.GOOS)
   163  	}
   164  	switch runtime.GOARCH {
   165  	case "ppc64":
   166  		t.Skipf("skipping on %s, no support for external linking, issue 9038", runtime.GOARCH)
   167  	case "arm64":
   168  		t.Skipf("skipping on %s, issue 10106", runtime.GOARCH)
   169  	case "mips64", "mips64le", "mips", "mipsle":
   170  		t.Skipf("skipping on %s, issue 12559 and 12560", runtime.GOARCH)
   171  	case "s390x":
   172  		t.Skipf("skipping on %s, issue 15255", runtime.GOARCH)
   173  	}
   174  	// TODO(jsing): Reenable once openbsd/arm has external linking support.
   175  	if runtime.GOOS == "openbsd" && runtime.GOARCH == "arm" {
   176  		t.Skip("skipping on openbsd/arm, no support for external linking, issue 10619")
   177  	}
   178  	if !build.Default.CgoEnabled {
   179  		t.Skip("skipping because cgo is not enabled")
   180  	}
   181  	testDisasm(t, "-ldflags=-linkmode=external")
   182  }