github.com/q45/go@v0.0.0-20151101211701-a4fb8c13db3f/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  	"io/ioutil"
    10  	"os"
    11  	"os/exec"
    12  	"path/filepath"
    13  	"reflect"
    14  	"runtime"
    15  	"testing"
    16  )
    17  
    18  type fileTest struct {
    19  	file           string
    20  	hdr            FileHeader
    21  	opthdr         interface{}
    22  	sections       []*SectionHeader
    23  	symbols        []*Symbol
    24  	hasNoDwarfInfo bool
    25  }
    26  
    27  var fileTests = []fileTest{
    28  	{
    29  		file: "testdata/gcc-386-mingw-obj",
    30  		hdr:  FileHeader{0x014c, 0x000c, 0x0, 0x64a, 0x1e, 0x0, 0x104},
    31  		sections: []*SectionHeader{
    32  			{".text", 0, 0, 36, 500, 1440, 0, 3, 0, 0x60300020},
    33  			{".data", 0, 0, 0, 0, 0, 0, 0, 0, 3224371264},
    34  			{".bss", 0, 0, 0, 0, 0, 0, 0, 0, 3224371328},
    35  			{".debug_abbrev", 0, 0, 137, 536, 0, 0, 0, 0, 0x42100000},
    36  			{".debug_info", 0, 0, 418, 673, 1470, 0, 7, 0, 1108344832},
    37  			{".debug_line", 0, 0, 128, 1091, 1540, 0, 1, 0, 1108344832},
    38  			{".rdata", 0, 0, 16, 1219, 0, 0, 0, 0, 1076887616},
    39  			{".debug_frame", 0, 0, 52, 1235, 1550, 0, 2, 0, 1110441984},
    40  			{".debug_loc", 0, 0, 56, 1287, 0, 0, 0, 0, 1108344832},
    41  			{".debug_pubnames", 0, 0, 27, 1343, 1570, 0, 1, 0, 1108344832},
    42  			{".debug_pubtypes", 0, 0, 38, 1370, 1580, 0, 1, 0, 1108344832},
    43  			{".debug_aranges", 0, 0, 32, 1408, 1590, 0, 2, 0, 1108344832},
    44  		},
    45  		symbols: []*Symbol{
    46  			{".file", 0x0, -2, 0x0, 0x67},
    47  			{"_main", 0x0, 1, 0x20, 0x2},
    48  			{".text", 0x0, 1, 0x0, 0x3},
    49  			{".data", 0x0, 2, 0x0, 0x3},
    50  			{".bss", 0x0, 3, 0x0, 0x3},
    51  			{".debug_abbrev", 0x0, 4, 0x0, 0x3},
    52  			{".debug_info", 0x0, 5, 0x0, 0x3},
    53  			{".debug_line", 0x0, 6, 0x0, 0x3},
    54  			{".rdata", 0x0, 7, 0x0, 0x3},
    55  			{".debug_frame", 0x0, 8, 0x0, 0x3},
    56  			{".debug_loc", 0x0, 9, 0x0, 0x3},
    57  			{".debug_pubnames", 0x0, 10, 0x0, 0x3},
    58  			{".debug_pubtypes", 0x0, 11, 0x0, 0x3},
    59  			{".debug_aranges", 0x0, 12, 0x0, 0x3},
    60  			{"___main", 0x0, 0, 0x20, 0x2},
    61  			{"_puts", 0x0, 0, 0x20, 0x2},
    62  		},
    63  	},
    64  	{
    65  		file: "testdata/gcc-386-mingw-exec",
    66  		hdr:  FileHeader{0x014c, 0x000f, 0x4c6a1b60, 0x3c00, 0x282, 0xe0, 0x107},
    67  		opthdr: &OptionalHeader32{
    68  			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,
    69  			[16]DataDirectory{
    70  				{0x0, 0x0},
    71  				{0x5000, 0x3c8},
    72  				{0x0, 0x0},
    73  				{0x0, 0x0},
    74  				{0x0, 0x0},
    75  				{0x0, 0x0},
    76  				{0x0, 0x0},
    77  				{0x0, 0x0},
    78  				{0x0, 0x0},
    79  				{0x7000, 0x18},
    80  				{0x0, 0x0},
    81  				{0x0, 0x0},
    82  				{0x0, 0x0},
    83  				{0x0, 0x0},
    84  				{0x0, 0x0},
    85  				{0x0, 0x0},
    86  			},
    87  		},
    88  		sections: []*SectionHeader{
    89  			{".text", 0xcd8, 0x1000, 0xe00, 0x400, 0x0, 0x0, 0x0, 0x0, 0x60500060},
    90  			{".data", 0x10, 0x2000, 0x200, 0x1200, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    91  			{".rdata", 0x120, 0x3000, 0x200, 0x1400, 0x0, 0x0, 0x0, 0x0, 0x40300040},
    92  			{".bss", 0xdc, 0x4000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0400080},
    93  			{".idata", 0x3c8, 0x5000, 0x400, 0x1600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    94  			{".CRT", 0x18, 0x6000, 0x200, 0x1a00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    95  			{".tls", 0x20, 0x7000, 0x200, 0x1c00, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
    96  			{".debug_aranges", 0x20, 0x8000, 0x200, 0x1e00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
    97  			{".debug_pubnames", 0x51, 0x9000, 0x200, 0x2000, 0x0, 0x0, 0x0, 0x0, 0x42100000},
    98  			{".debug_pubtypes", 0x91, 0xa000, 0x200, 0x2200, 0x0, 0x0, 0x0, 0x0, 0x42100000},
    99  			{".debug_info", 0xe22, 0xb000, 0x1000, 0x2400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   100  			{".debug_abbrev", 0x157, 0xc000, 0x200, 0x3400, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   101  			{".debug_line", 0x144, 0xd000, 0x200, 0x3600, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   102  			{".debug_frame", 0x34, 0xe000, 0x200, 0x3800, 0x0, 0x0, 0x0, 0x0, 0x42300000},
   103  			{".debug_loc", 0x38, 0xf000, 0x200, 0x3a00, 0x0, 0x0, 0x0, 0x0, 0x42100000},
   104  		},
   105  	},
   106  	{
   107  		file: "testdata/gcc-amd64-mingw-obj",
   108  		hdr:  FileHeader{0x8664, 0x6, 0x0, 0x198, 0x12, 0x0, 0x4},
   109  		sections: []*SectionHeader{
   110  			{".text", 0x0, 0x0, 0x30, 0x104, 0x15c, 0x0, 0x3, 0x0, 0x60500020},
   111  			{".data", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
   112  			{".bss", 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0500080},
   113  			{".rdata", 0x0, 0x0, 0x10, 0x134, 0x0, 0x0, 0x0, 0x0, 0x40500040},
   114  			{".xdata", 0x0, 0x0, 0xc, 0x144, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   115  			{".pdata", 0x0, 0x0, 0xc, 0x150, 0x17a, 0x0, 0x3, 0x0, 0x40300040},
   116  		},
   117  		symbols: []*Symbol{
   118  			{".file", 0x0, -2, 0x0, 0x67},
   119  			{"main", 0x0, 1, 0x20, 0x2},
   120  			{".text", 0x0, 1, 0x0, 0x3},
   121  			{".data", 0x0, 2, 0x0, 0x3},
   122  			{".bss", 0x0, 3, 0x0, 0x3},
   123  			{".rdata", 0x0, 4, 0x0, 0x3},
   124  			{".xdata", 0x0, 5, 0x0, 0x3},
   125  			{".pdata", 0x0, 6, 0x0, 0x3},
   126  			{"__main", 0x0, 0, 0x20, 0x2},
   127  			{"puts", 0x0, 0, 0x20, 0x2},
   128  		},
   129  		hasNoDwarfInfo: true,
   130  	},
   131  	{
   132  		file: "testdata/gcc-amd64-mingw-exec",
   133  		hdr:  FileHeader{0x8664, 0x11, 0x53e4364f, 0x39600, 0x6fc, 0xf0, 0x27},
   134  		opthdr: &OptionalHeader64{
   135  			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,
   136  			[16]DataDirectory{
   137  				{0x0, 0x0},
   138  				{0xe000, 0x990},
   139  				{0x0, 0x0},
   140  				{0xa000, 0x498},
   141  				{0x0, 0x0},
   142  				{0x0, 0x0},
   143  				{0x0, 0x0},
   144  				{0x0, 0x0},
   145  				{0x0, 0x0},
   146  				{0x10000, 0x28},
   147  				{0x0, 0x0},
   148  				{0x0, 0x0},
   149  				{0xe254, 0x218},
   150  				{0x0, 0x0},
   151  				{0x0, 0x0},
   152  				{0x0, 0x0},
   153  			}},
   154  		sections: []*SectionHeader{
   155  			{".text", 0x6860, 0x1000, 0x6a00, 0x600, 0x0, 0x0, 0x0, 0x0, 0x60500020},
   156  			{".data", 0xe0, 0x8000, 0x200, 0x7000, 0x0, 0x0, 0x0, 0x0, 0xc0500040},
   157  			{".rdata", 0x6b0, 0x9000, 0x800, 0x7200, 0x0, 0x0, 0x0, 0x0, 0x40600040},
   158  			{".pdata", 0x498, 0xa000, 0x600, 0x7a00, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   159  			{".xdata", 0x488, 0xb000, 0x600, 0x8000, 0x0, 0x0, 0x0, 0x0, 0x40300040},
   160  			{".bss", 0x1410, 0xc000, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc0600080},
   161  			{".idata", 0x990, 0xe000, 0xa00, 0x8600, 0x0, 0x0, 0x0, 0x0, 0xc0300040},
   162  			{".CRT", 0x68, 0xf000, 0x200, 0x9000, 0x0, 0x0, 0x0, 0x0, 0xc0400040},
   163  			{".tls", 0x48, 0x10000, 0x200, 0x9200, 0x0, 0x0, 0x0, 0x0, 0xc0600040},
   164  			{".debug_aranges", 0x600, 0x11000, 0x600, 0x9400, 0x0, 0x0, 0x0, 0x0, 0x42500040},
   165  			{".debug_info", 0x1316e, 0x12000, 0x13200, 0x9a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   166  			{".debug_abbrev", 0x2ccb, 0x26000, 0x2e00, 0x1cc00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   167  			{".debug_line", 0x3c4d, 0x29000, 0x3e00, 0x1fa00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   168  			{".debug_frame", 0x18b8, 0x2d000, 0x1a00, 0x23800, 0x0, 0x0, 0x0, 0x0, 0x42400040},
   169  			{".debug_str", 0x396, 0x2f000, 0x400, 0x25200, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   170  			{".debug_loc", 0x13240, 0x30000, 0x13400, 0x25600, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   171  			{".debug_ranges", 0xa70, 0x44000, 0xc00, 0x38a00, 0x0, 0x0, 0x0, 0x0, 0x42100040},
   172  		},
   173  	},
   174  }
   175  
   176  func isOptHdrEq(a, b interface{}) bool {
   177  	switch va := a.(type) {
   178  	case *OptionalHeader32:
   179  		vb, ok := b.(*OptionalHeader32)
   180  		if !ok {
   181  			return false
   182  		}
   183  		return *vb == *va
   184  	case *OptionalHeader64:
   185  		vb, ok := b.(*OptionalHeader64)
   186  		if !ok {
   187  			return false
   188  		}
   189  		return *vb == *va
   190  	case nil:
   191  		return b == nil
   192  	}
   193  	return false
   194  }
   195  
   196  func TestOpen(t *testing.T) {
   197  	for i := range fileTests {
   198  		tt := &fileTests[i]
   199  
   200  		f, err := Open(tt.file)
   201  		if err != nil {
   202  			t.Error(err)
   203  			continue
   204  		}
   205  		if !reflect.DeepEqual(f.FileHeader, tt.hdr) {
   206  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.FileHeader, tt.hdr)
   207  			continue
   208  		}
   209  		if !isOptHdrEq(tt.opthdr, f.OptionalHeader) {
   210  			t.Errorf("open %s:\n\thave %#v\n\twant %#v\n", tt.file, f.OptionalHeader, tt.opthdr)
   211  			continue
   212  		}
   213  
   214  		for i, sh := range f.Sections {
   215  			if i >= len(tt.sections) {
   216  				break
   217  			}
   218  			have := &sh.SectionHeader
   219  			want := tt.sections[i]
   220  			if !reflect.DeepEqual(have, want) {
   221  				t.Errorf("open %s, section %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
   222  			}
   223  		}
   224  		tn := len(tt.sections)
   225  		fn := len(f.Sections)
   226  		if tn != fn {
   227  			t.Errorf("open %s: len(Sections) = %d, want %d", tt.file, fn, tn)
   228  		}
   229  		for i, have := range f.Symbols {
   230  			if i >= len(tt.symbols) {
   231  				break
   232  			}
   233  			want := tt.symbols[i]
   234  			if !reflect.DeepEqual(have, want) {
   235  				t.Errorf("open %s, symbol %d:\n\thave %#v\n\twant %#v\n", tt.file, i, have, want)
   236  			}
   237  		}
   238  		if !tt.hasNoDwarfInfo {
   239  			_, err = f.DWARF()
   240  			if err != nil {
   241  				t.Errorf("fetching %s dwarf details failed: %v", tt.file, err)
   242  			}
   243  		}
   244  	}
   245  }
   246  
   247  func TestOpenFailure(t *testing.T) {
   248  	filename := "file.go"    // not a PE file
   249  	_, err := Open(filename) // don't crash
   250  	if err == nil {
   251  		t.Errorf("open %s: succeeded unexpectedly", filename)
   252  	}
   253  }
   254  
   255  func TestDWARF(t *testing.T) {
   256  	if runtime.GOOS != "windows" {
   257  		t.Skip("skipping windows only test")
   258  	}
   259  
   260  	tmpdir, err := ioutil.TempDir("", "TestDWARF")
   261  	if err != nil {
   262  		t.Fatal("TempDir failed: ", err)
   263  	}
   264  	defer os.RemoveAll(tmpdir)
   265  
   266  	prog := `
   267  package main
   268  func main() {
   269  }
   270  `
   271  	src := filepath.Join(tmpdir, "a.go")
   272  	exe := filepath.Join(tmpdir, "a.exe")
   273  	err = ioutil.WriteFile(src, []byte(prog), 0644)
   274  	output, err := exec.Command("go", "build", "-o", exe, src).CombinedOutput()
   275  	if err != nil {
   276  		t.Fatalf("building test executable failed: %s %s", err, output)
   277  	}
   278  
   279  	f, err := Open(exe)
   280  	if err != nil {
   281  		t.Fatal(err)
   282  	}
   283  	defer f.Close()
   284  
   285  	d, err := f.DWARF()
   286  	if err != nil {
   287  		t.Fatal(err)
   288  	}
   289  
   290  	// look for main.main
   291  	r := d.Reader()
   292  	for {
   293  		e, err := r.Next()
   294  		if err != nil {
   295  			t.Fatal("r.Next:", err)
   296  		}
   297  		if e == nil {
   298  			break
   299  		}
   300  		if e.Tag == dwarf.TagSubprogram {
   301  			for _, f := range e.Field {
   302  				if f.Attr == dwarf.AttrName && e.Val(dwarf.AttrName) == "main.main" {
   303  					return
   304  				}
   305  			}
   306  		}
   307  	}
   308  	t.Fatal("main.main not found")
   309  }