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.
22 type fileTest
struct {
26 sections
[]*SectionHeader
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},
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,
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,
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},
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,
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
)
223 case *OptionalHeader64
:
224 vb
, ok
:= b
.(*OptionalHeader64
)
235 func TestOpen(t
*testing
.T
) {
236 for i
:= range fileTests
{
239 f
, err
:= Open(tt
.file
)
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
)
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
)
253 for i
, sh
:= range f
.Sections
{
254 if i
>= len(tt
.sections
) {
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
)
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
) {
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
{
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
290 t
.Errorf("open %s: succeeded unexpectedly", filename
)
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")
311 defer os
.RemoveAll(tmpdir
)
313 src
:= filepath
.Join(tmpdir
, "a.go")
314 file
, err
:= os
.Create(src
)
318 err
= template
.Must(template
.New("main").Parse(testprog
)).Execute(file
, linktype
!= linkNoCgo
)
320 if err
:= file
.Close(); err
!= nil {
325 if err
:= file
.Close(); err
!= nil {
329 exe
:= filepath
.Join(tmpdir
, "a.exe")
330 args
:= []string{"build", "-o", exe
}
334 case linkCgoInternal
:
335 args
= append(args
, "-ldflags", "-linkmode=internal")
336 case linkCgoExternal
:
337 args
= append(args
, "-ldflags", "-linkmode=external")
339 t
.Fatalf("invalid linktype parameter of %v", linktype
)
341 args
= append(args
, src
)
342 out
, err
:= exec
.Command(testenv
.GoToolPath(t
), args
...).CombinedOutput()
344 t
.Fatalf("building test executable for linktype %d failed: %s %s", linktype
, err
, out
)
346 out
, err
= exec
.Command(exe
).CombinedOutput()
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)
357 t
.Fatalf("unexpected main address %q: %s", matches
[1], err
)
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")
381 // look for main.main
386 t
.Fatal("r.Next:", err
)
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
{
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")
410 t
.Skip("skipping test: gcc is missing")
413 tmpdir
, err
:= ioutil
.TempDir("", "TestBSSHasZeros")
417 defer os
.RemoveAll(tmpdir
)
419 srcpath
:= filepath
.Join(tmpdir
, "a.c")
428 printf("%d\n", zero);
432 err
= ioutil
.WriteFile(srcpath
, []byte(src
), 0644)
437 objpath
:= filepath
.Join(tmpdir
, "a.obj")
438 cmd
:= exec
.Command(gccpath
, "-c", srcpath
, "-o", objpath
)
439 out
, err
:= cmd
.CombinedOutput()
441 t
.Fatalf("failed to build object file: %v - %v", err
, string(out
))
444 f
, err
:= Open(objpath
)
451 for _
, sect
:= range f
.Sections
{
452 if sect
.Name
== ".bss" {
458 t
.Fatal("could not find .bss section")
460 data
, err
:= bss
.Data()
465 t
.Fatalf("%s file .bss section cannot be empty", objpath
)
467 for _
, b
:= range data
{
469 t
.Fatalf(".bss section has non zero bytes: %v", data
)
474 func TestDWARF(t
*testing
.T
) {
475 testDWARF(t
, linkNoCgo
)
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")
500 defer os
.RemoveAll(tmpdir
)
502 src
:= filepath
.Join(tmpdir
, "a.go")
503 err
= ioutil
.WriteFile(src
, []byte(`package main; func main() {}`), 0644)
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()
511 t
.Fatalf("building test executable failed: %s %s", err
, out
)
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
)
532 t
.Fatalf("unexpected OptionalHeader type: have %T, but want *pe.OptionalHeader32 or *pe.OptionalHeader64", oh
)