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  }