github.com/mattn/go@v0.0.0-20171011075504-07f7db3ea99f/src/debug/pe/file_test.go (about)

     1  // Copyright 2009 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 pe
     6  
     7  import (
     8  	"debug/dwarf"
     9  	"internal/testenv"
    10  	"io/ioutil"
    11  	"os"
    12  	"os/exec"
    13  	"path/filepath"
    14  	"reflect"
    15  	"regexp"
    16  	"runtime"
    17  	"strconv"
    18  	"testing"
    19  	"text/template"
    20  )
    21  
    22  type fileTest struct {
    23  	file           string
    24  	hdr            FileHeader
    25  	opthdr         interface{}
    26  	sections       []*SectionHeader
    27  	symbols        []*Symbol
    28  	hasNoDwarfInfo bool
    29  }
    30  
    31  var fileTests = []fileTest{
    32  	{
    33  		file: "testdata/gcc-386-mingw-obj",
    34  		hdr:  FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
    35  		sections: []*SectionHeader{
    36  			{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
    37  			{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
    38  			{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
    39  			{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
    40  			{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
    41  			{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
    42  			{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
    43  			{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
    44  			{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
    45  			{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
    46  			{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
    47  			{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
    48  		},
    49  		symbols: []*Symbol{
    50  			{".file", 0x0, -2, 0x0, 0x67},
    51  			{"_main", 0x0, 1, 0x20, 0x2},
    52  			{".text", 0x0, 1, 0x0, 0x3},
    53  			{".data", 0x0, 2, 0x0, 0x3},
    54  			{".bss", 0x0, 3, 0x0, 0x3},
    55  			{".debug_abbrev", 0x0, 4, 0x0, 0x3},
    56  			{".debug_info", 0x0, 5, 0x0, 0x3},
    57  			{".debug_line", 0x0, 6, 0x0, 0x3},
    58  			{".rdata", 0x0, 7, 0x0, 0x3},
    59  			{".debug_frame", 0x0, 8, 0x0, 0x3},
    60  			{".debug_loc", 0x0, 9, 0x0, 0x3},
    61  			{".debug_pubnames", 0x0, 10, 0x0, 0x3},
    62  			{".debug_pubtypes", 0x0, 11, 0x0, 0x3},
    63  			{".debug_aranges", 0x0, 12, 0x0, 0x3},
    64  			{"___main", 0x0, 0, 0x20, 0x2},
    65  			{"_puts", 0x0, 0, 0x20, 0x2},
    66  		},
    67  	},
    68  	{
    69  		file: "testdata/gcc-386-mingw-exec",
    70  		hdr:  FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
    71  		opthdr: &OptionalHeader32{
    72  			0x10b, 0x2, 0x38, 0xe00, 0x1a00, 0x200, 0x1160, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x10000, 0x400, 0x14abb, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
    73  			[16]DataDirectory{
    74  				{0x0, 0x0},
    75  				{0x5000, 0x3c8},
    76  				{0x0, 0x0},
    77  				{0x0, 0x0},
    78  				{0x0, 0x0},
    79  				{0x0, 0x0},
    80  				{0x0, 0x0},
    81  				{0x0, 0x0},
    82  				{0x0, 0x0},
    83  				{0x7000, 0x18},
    84  				{0x0, 0x0},
    85  				{0x0, 0x0},
    86  				{0x0, 0x0},
    87  				{0x0, 0x0},
    88  				{0x0, 0x0},
    89  				{0x0, 0x0},
    90  			},
    91  		},
    92  		sections: []*SectionHeader{
    93  			{".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
    94  			{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    95  			{".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
    96  			{".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
    97  			{".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    98  			{".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    99  			{".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   100  			{".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   101  			{".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   102  			{".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   103  			{".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   104  			{".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   105  			{".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   106  			{".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
   107  			{".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   108  		},
   109  	},
   110  	{
   111  		file: "testdata/gcc-386-mingw-no-symbols-exec",
   112  		hdr:  FileHeader{0x14c, 0x8, 0x69676572, 0x0, 0x0, 0xe0, 0x30f},
   113  		opthdr: &OptionalHeader32{0x10b, 0x2, 0x18, 0xe00, 0x1e00, 0x200, 0x1280, 0x1000, 0x2000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x1, 0x0, 0x4, 0x0, 0x0, 0x9000, 0x400, 0x5306, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
   114  			[16]DataDirectory{
   115  				{0x0, 0x0},
   116  				{0x6000, 0x378},
   117  				{0x0, 0x0},
   118  				{0x0, 0x0},
   119  				{0x0, 0x0},
   120  				{0x0, 0x0},
   121  				{0x0, 0x0},
   122  				{0x0, 0x0},
   123  				{0x0, 0x0},
   124  				{0x8004, 0x18},
   125  				{0x0, 0x0},
   126  				{0x0, 0x0},
   127  				{0x60b8, 0x7c},
   128  				{0x0, 0x0},
   129  				{0x0, 0x0},
   130  				{0x0, 0x0},
   131  			},
   132  		},
   133  		sections: []*SectionHeader{
   134  			{".text", 0xc64, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
   135  			{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   136  			{".rdata", 0x134, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   137  			{".eh_fram", 0x3a0, 0x4000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   138  			{".bss", 0x60, 0x5000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0300080},
   139  			{".idata", 0x378, 0x6000, 0x400, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   140  			{".CRT", 0x18, 0x7000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   141  			{".tls", 0x20, 0x8000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   142  		},
   143  		hasNoDwarfInfo: true,
   144  	},
   145  	{
   146  		file: "testdata/gcc-amd64-mingw-obj",
   147  		hdr:  FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
   148  		sections: []*SectionHeader{
   149  			{".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
   150  			{".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
   151  			{".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
   152  			{".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
   153  			{".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   154  			{".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
   155  		},
   156  		symbols: []*Symbol{
   157  			{".file", 0x0, -2, 0x0, 0x67},
   158  			{"main", 0x0, 1, 0x20, 0x2},
   159  			{".text", 0x0, 1, 0x0, 0x3},
   160  			{".data", 0x0, 2, 0x0, 0x3},
   161  			{".bss", 0x0, 3, 0x0, 0x3},
   162  			{".rdata", 0x0, 4, 0x0, 0x3},
   163  			{".xdata", 0x0, 5, 0x0, 0x3},
   164  			{".pdata", 0x0, 6, 0x0, 0x3},
   165  			{"__main", 0x0, 0, 0x20, 0x2},
   166  			{"puts", 0x0, 0, 0x20, 0x2},
   167  		},
   168  		hasNoDwarfInfo: true,
   169  	},
   170  	{
   171  		file: "testdata/gcc-amd64-mingw-exec",
   172  		hdr:  FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27},
   173  		opthdr: &OptionalHeader64{
   174  			0x20b, 0x2, 0x16, 0x6a00, 0x2400, 0x1600, 0x14e0, 0x1000, 0x400000, 0x1000, 0x200, 0x4, 0x0, 0x0, 0x0, 0x5, 0x2, 0x0, 0x45000, 0x600, 0x46f19, 0x3, 0x0, 0x200000, 0x1000, 0x100000, 0x1000, 0x0, 0x10,
   175  			[16]DataDirectory{
   176  				{0x0, 0x0},
   177  				{0xe000, 0x990},
   178  				{0x0, 0x0},
   179  				{0xa000, 0x498},
   180  				{0x0, 0x0},
   181  				{0x0, 0x0},
   182  				{0x0, 0x0},
   183  				{0x0, 0x0},
   184  				{0x0, 0x0},
   185  				{0x10000, 0x28},
   186  				{0x0, 0x0},
   187  				{0x0, 0x0},
   188  				{0xe254, 0x218},
   189  				{0x0, 0x0},
   190  				{0x0, 0x0},
   191  				{0x0, 0x0},
   192  			}},
   193  		sections: []*SectionHeader{
   194  			{".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
   195  			{".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
   196  			{".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
   197  			{".pdata", 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   198  			{".xdata", 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   199  			{".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
   200  			{".idata", 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   201  			{".CRT", 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
   202  			{".tls", 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
   203  			{".debug_aranges", 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
   204  			{".debug_info", 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   205  			{".debug_abbrev", 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   206  			{".debug_line", 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   207  			{".debug_frame", 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
   208  			{".debug_str", 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   209  			{".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   210  			{".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   211  		},
   212  	},
   213  }
   214  
   215  func isOptHdrEq(a, b interface{}) bool {
   216  	switch va := a.(type) {
   217  	case *OptionalHeader32:
   218  		vb, ok := b.(*OptionalHeader32)
   219  		if !ok {
   220  			return false
   221  		}
   222  		return *vb == *va
   223  	case *OptionalHeader64:
   224  		vb, ok := b.(*OptionalHeader64)
   225  		if !ok {
   226  			return false
   227  		}
   228  		return *vb == *va
   229  	case nil:
   230  		return b == nil
   231  	}
   232  	return false
   233  }
   234  
   235  func TestOpen(t *testing.T) {
   236  	for i := range fileTests {
   237  		tt := &fileTests[i]
   238  
   239  		f, err := Open(tt.file)
   240  		if err != nil {
   241  			t.Error(err)
   242  			continue
   243  		}
   244  		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
   245  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
   246  			continue
   247  		}
   248  		if !isOptHdrEq(tt.opthdr, f.OptionalHeader) {
   249  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.OptionalHeader, tt.opthdr)
   250  			continue
   251  		}
   252  
   253  		for i, sh := range f.Sections {
   254  			if i >= len(tt.sections) {
   255  				break
   256  			}
   257  			have := &sh.SectionHeader
   258  			want := tt.sections[i]
   259  			if !reflect.DeepEqual(have, want) {
   260  				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
   261  			}
   262  		}
   263  		tn := len(tt.sections)
   264  		fn := len(f.Sections)
   265  		if tn != fn {
   266  			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
   267  		}
   268  		for i, have := range f.Symbols {
   269  			if i >= len(tt.symbols) {
   270  				break
   271  			}
   272  			want := tt.symbols[i]
   273  			if !reflect.DeepEqual(have, want) {
   274  				t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
   275  			}
   276  		}
   277  		if !tt.hasNoDwarfInfo {
   278  			_, err = f.DWARF()
   279  			if err != nil {
   280  				t.Errorf("fetching %s dwarf details failed: %v", tt.file, err)
   281  			}
   282  		}
   283  	}
   284  }
   285  
   286  func TestOpenFailure(t *testing.T) {
   287  	filename := "file.go"    // not a PE file
   288  	_, err := Open(filename) // don't crash
   289  	if err == nil {
   290  		t.Errorf("open %s: succeeded unexpectedly", filename)
   291  	}
   292  }
   293  
   294  const (
   295  	linkNoCgo = iota
   296  	linkCgoDefault
   297  	linkCgoInternal
   298  	linkCgoExternal
   299  )
   300  
   301  func testDWARF(t *testing.T, linktype int) {
   302  	if runtime.GOOS != "windows" {
   303  		t.Skip("skipping windows only test")
   304  	}
   305  	testenv.MustHaveGoRun(t)
   306  
   307  	tmpdir, err := ioutil.TempDir("", "TestDWARF")
   308  	if err != nil {
   309  		t.Fatal(err)
   310  	}
   311  	defer os.RemoveAll(tmpdir)
   312  
   313  	src := filepath.Join(tmpdir, "a.go")
   314  	file, err := os.Create(src)
   315  	if err != nil {
   316  		t.Fatal(err)
   317  	}
   318  	err = template.Must(template.New("main").Parse(testprog)).Execute(file, linktype != linkNoCgo)
   319  	if err != nil {
   320  		if err := file.Close(); err != nil {
   321  			t.Error(err)
   322  		}
   323  		t.Fatal(err)
   324  	}
   325  	if err := file.Close(); err != nil {
   326  		t.Fatal(err)
   327  	}
   328  
   329  	exe := filepath.Join(tmpdir, "a.exe")
   330  	args := []string{"build", "-o", exe}
   331  	switch linktype {
   332  	case linkNoCgo:
   333  	case linkCgoDefault:
   334  	case linkCgoInternal:
   335  		args = append(args, "-ldflags", "-linkmode=internal")
   336  	case linkCgoExternal:
   337  		args = append(args, "-ldflags", "-linkmode=external")
   338  	default:
   339  		t.Fatalf("invalid linktype parameter of %v", linktype)
   340  	}
   341  	args = append(args, src)
   342  	out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput()
   343  	if err != nil {
   344  		t.Fatalf("building test executable for linktype %d failed: %s %s", linktype, err, out)
   345  	}
   346  	out, err = exec.Command(exe).CombinedOutput()
   347  	if err != nil {
   348  		t.Fatalf("running test executable failed: %s %s", err, out)
   349  	}
   350  
   351  	matches := regexp.MustCompile("main=(.*)\n").FindStringSubmatch(string(out))
   352  	if len(matches) < 2 {
   353  		t.Fatalf("unexpected program output: %s", out)
   354  	}
   355  	wantaddr, err := strconv.ParseUint(matches[1], 0, 64)
   356  	if err != nil {
   357  		t.Fatalf("unexpected main address %q: %s", matches[1], err)
   358  	}
   359  
   360  	f, err := Open(exe)
   361  	if err != nil {
   362  		t.Fatal(err)
   363  	}
   364  	defer f.Close()
   365  
   366  	var foundDebugGDBScriptsSection bool
   367  	for _, sect := range f.Sections {
   368  		if sect.Name == ".debug_gdb_scripts" {
   369  			foundDebugGDBScriptsSection = true
   370  		}
   371  	}
   372  	if !foundDebugGDBScriptsSection {
   373  		t.Error(".debug_gdb_scripts section is not found")
   374  	}
   375  
   376  	d, err := f.DWARF()
   377  	if err != nil {
   378  		t.Fatal(err)
   379  	}
   380  
   381  	// look for main.main
   382  	r := d.Reader()
   383  	for {
   384  		e, err := r.Next()
   385  		if err != nil {
   386  			t.Fatal("r.Next:", err)
   387  		}
   388  		if e == nil {
   389  			break
   390  		}
   391  		if e.Tag == dwarf.TagSubprogram {
   392  			if name, ok := e.Val(dwarf.AttrName).(string); ok && name == "main.main" {
   393  				if addr, ok := e.Val(dwarf.AttrLowpc).(uint64); ok && addr == wantaddr {
   394  					return
   395  				}
   396  			}
   397  		}
   398  	}
   399  	t.Fatal("main.main not found")
   400  }
   401  
   402  func TestBSSHasZeros(t *testing.T) {
   403  	testenv.MustHaveExec(t)
   404  
   405  	if runtime.GOOS != "windows" {
   406  		t.Skip("skipping windows only test")
   407  	}
   408  	gccpath, err := exec.LookPath("gcc")
   409  	if err != nil {
   410  		t.Skip("skipping test: gcc is missing")
   411  	}
   412  
   413  	tmpdir, err := ioutil.TempDir("", "TestBSSHasZeros")
   414  	if err != nil {
   415  		t.Fatal(err)
   416  	}
   417  	defer os.RemoveAll(tmpdir)
   418  
   419  	srcpath := filepath.Join(tmpdir, "a.c")
   420  	src := `
   421  #include <stdio.h>
   422  
   423  int zero = 0;
   424  
   425  int
   426  main(void)
   427  {
   428  	printf("%d\n", zero);
   429  	return 0;
   430  }
   431  `
   432  	err = ioutil.WriteFile(srcpath, []byte(src), 0644)
   433  	if err != nil {
   434  		t.Fatal(err)
   435  	}
   436  
   437  	objpath := filepath.Join(tmpdir, "a.obj")
   438  	cmd := exec.Command(gccpath, "-c", srcpath, "-o", objpath)
   439  	out, err := cmd.CombinedOutput()
   440  	if err != nil {
   441  		t.Fatalf("failed to build object file: %v - %v", err, string(out))
   442  	}
   443  
   444  	f, err := Open(objpath)
   445  	if err != nil {
   446  		t.Fatal(err)
   447  	}
   448  	defer f.Close()
   449  
   450  	var bss *Section
   451  	for _, sect := range f.Sections {
   452  		if sect.Name == ".bss" {
   453  			bss = sect
   454  			break
   455  		}
   456  	}
   457  	if bss == nil {
   458  		t.Fatal("could not find .bss section")
   459  	}
   460  	data, err := bss.Data()
   461  	if err != nil {
   462  		t.Fatal(err)
   463  	}
   464  	if len(data) == 0 {
   465  		t.Fatalf("%s file .bss section cannot be empty", objpath)
   466  	}
   467  	for _, b := range data {
   468  		if b != 0 {
   469  			t.Fatalf(".bss section has non zero bytes: %v", data)
   470  		}
   471  	}
   472  }
   473  
   474  func TestDWARF(t *testing.T) {
   475  	testDWARF(t, linkNoCgo)
   476  }
   477  
   478  const testprog = `
   479  package main
   480  
   481  import "fmt"
   482  {{if .}}import "C"
   483  {{end}}
   484  
   485  func main() {
   486  	fmt.Printf("main=%p\n", main)
   487  }
   488  `
   489  
   490  func TestBuildingWindowsGUI(t *testing.T) {
   491  	testenv.MustHaveGoBuild(t)
   492  
   493  	if runtime.GOOS != "windows" {
   494  		t.Skip("skipping windows only test")
   495  	}
   496  	tmpdir, err := ioutil.TempDir("", "TestBuildingWindowsGUI")
   497  	if err != nil {
   498  		t.Fatal(err)
   499  	}
   500  	defer os.RemoveAll(tmpdir)
   501  
   502  	src := filepath.Join(tmpdir, "a.go")
   503  	err = ioutil.WriteFile(src, []byte(`package main; func main() {}`), 0644)
   504  	if err != nil {
   505  		t.Fatal(err)
   506  	}
   507  	exe := filepath.Join(tmpdir, "a.exe")
   508  	cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags", "-H=windowsgui", "-o", exe, src)
   509  	out, err := cmd.CombinedOutput()
   510  	if err != nil {
   511  		t.Fatalf("building test executable failed: %s %s", err, out)
   512  	}
   513  
   514  	f, err := Open(exe)
   515  	if err != nil {
   516  		t.Fatal(err)
   517  	}
   518  	defer f.Close()
   519  
   520  	const _IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
   521  
   522  	switch oh := f.OptionalHeader.(type) {
   523  	case *OptionalHeader32:
   524  		if oh.Subsystem != _IMAGE_SUBSYSTEM_WINDOWS_GUI {
   525  			t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, _IMAGE_SUBSYSTEM_WINDOWS_GUI)
   526  		}
   527  	case *OptionalHeader64:
   528  		if oh.Subsystem != _IMAGE_SUBSYSTEM_WINDOWS_GUI {
   529  			t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, _IMAGE_SUBSYSTEM_WINDOWS_GUI)
   530  		}
   531  	default:
   532  		t.Fatalf("unexpected OptionalHeader type: have %T, but want *pe.OptionalHeader32 or *pe.OptionalHeader64", oh)
   533  	}
   534  }