libgo: update to go1.9
[official-gcc.git] / libgo / go / debug / pe / file_test.go
blob8645d676b752b2cf9624ff6ab040a7a5a8cea4c9
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.
5 package pe
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"
22 type fileTest struct {
23 file string
24 hdr FileHeader
25 opthdr interface{}
26 sections []*SectionHeader
27 symbols []*Symbol
28 hasNoDwarfInfo bool
31 var fileTests = []fileTest{
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},
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},
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},
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},
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},
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},
143 hasNoDwarfInfo: true,
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},
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},
168 hasNoDwarfInfo: true,
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},
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},
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
222 return *vb == *va
223 case *OptionalHeader64:
224 vb, ok := b.(*OptionalHeader64)
225 if !ok {
226 return false
228 return *vb == *va
229 case nil:
230 return b == nil
232 return false
235 func TestOpen(t *testing.T) {
236 for i := range fileTests {
237 tt := &fileTests[i]
239 f, err := Open(tt.file)
240 if err != nil {
241 t.Error(err)
242 continue
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
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
253 for i, sh := range f.Sections {
254 if i >= len(tt.sections) {
255 break
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)
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)
268 for i, have := range f.Symbols {
269 if i >= len(tt.symbols) {
270 break
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)
277 if !tt.hasNoDwarfInfo {
278 _, err = f.DWARF()
279 if err != nil {
280 t.Errorf("fetching %s dwarf details failed: %v", tt.file, err)
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)
294 const (
295 linkNoCgo = iota
296 linkCgoDefault
297 linkCgoInternal
298 linkCgoExternal
301 func testDWARF(t *testing.T, linktype int) {
302 if runtime.GOOS != "windows" {
303 t.Skip("skipping windows only test")
305 testenv.MustHaveGoRun(t)
307 tmpdir, err := ioutil.TempDir("", "TestDWARF")
308 if err != nil {
309 t.Fatal(err)
311 defer os.RemoveAll(tmpdir)
313 src := filepath.Join(tmpdir, "a.go")
314 file, err := os.Create(src)
315 if err != nil {
316 t.Fatal(err)
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)
323 t.Fatal(err)
325 if err := file.Close(); err != nil {
326 t.Fatal(err)
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)
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)
346 out, err = exec.Command(exe).CombinedOutput()
347 if err != nil {
348 t.Fatalf("running test executable failed: %s %s", err, out)
351 matches := regexp.MustCompile("main=(.*)\n").FindStringSubmatch(string(out))
352 if len(matches) < 2 {
353 t.Fatalf("unexpected program output: %s", out)
355 wantaddr, err := strconv.ParseUint(matches[1], 0, 64)
356 if err != nil {
357 t.Fatalf("unexpected main address %q: %s", matches[1], err)
360 f, err := Open(exe)
361 if err != nil {
362 t.Fatal(err)
364 defer f.Close()
366 var foundDebugGDBScriptsSection bool
367 for _, sect := range f.Sections {
368 if sect.Name == ".debug_gdb_scripts" {
369 foundDebugGDBScriptsSection = true
372 if !foundDebugGDBScriptsSection {
373 t.Error(".debug_gdb_scripts section is not found")
376 d, err := f.DWARF()
377 if err != nil {
378 t.Fatal(err)
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)
388 if e == nil {
389 break
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
399 t.Fatal("main.main not found")
402 func TestBSSHasZeros(t *testing.T) {
403 testenv.MustHaveExec(t)
405 if runtime.GOOS != "windows" {
406 t.Skip("skipping windows only test")
408 gccpath, err := exec.LookPath("gcc")
409 if err != nil {
410 t.Skip("skipping test: gcc is missing")
413 tmpdir, err := ioutil.TempDir("", "TestBSSHasZeros")
414 if err != nil {
415 t.Fatal(err)
417 defer os.RemoveAll(tmpdir)
419 srcpath := filepath.Join(tmpdir, "a.c")
420 src := `
421 #include <stdio.h>
423 int zero = 0;
426 main(void)
428 printf("%d\n", zero);
429 return 0;
432 err = ioutil.WriteFile(srcpath, []byte(src), 0644)
433 if err != nil {
434 t.Fatal(err)
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))
444 f, err := Open(objpath)
445 if err != nil {
446 t.Fatal(err)
448 defer f.Close()
450 var bss *Section
451 for _, sect := range f.Sections {
452 if sect.Name == ".bss" {
453 bss = sect
454 break
457 if bss == nil {
458 t.Fatal("could not find .bss section")
460 data, err := bss.Data()
461 if err != nil {
462 t.Fatal(err)
464 if len(data) == 0 {
465 t.Fatalf("%s file .bss section cannot be empty", objpath)
467 for _, b := range data {
468 if b != 0 {
469 t.Fatalf(".bss section has non zero bytes: %v", data)
474 func TestDWARF(t *testing.T) {
475 testDWARF(t, linkNoCgo)
478 const testprog = `
479 package main
481 import "fmt"
482 {{if .}}import "C"
483 {{end}}
485 func main() {
486 fmt.Printf("main=%p\n", main)
490 func TestBuildingWindowsGUI(t *testing.T) {
491 testenv.MustHaveGoBuild(t)
493 if runtime.GOOS != "windows" {
494 t.Skip("skipping windows only test")
496 tmpdir, err := ioutil.TempDir("", "TestBuildingWindowsGUI")
497 if err != nil {
498 t.Fatal(err)
500 defer os.RemoveAll(tmpdir)
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)
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)
514 f, err := Open(exe)
515 if err != nil {
516 t.Fatal(err)
518 defer f.Close()
520 const _IMAGE_SUBSYSTEM_WINDOWS_GUI = 2
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)
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)
531 default:
532 t.Fatalf("unexpected OptionalHeader type: have %T, but want *pe.OptionalHeader32 or *pe.OptionalHeader64", oh)