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 5package pe 6 7import ( 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 22type fileTest struct { 23 file string 24 hdr FileHeader 25 opthdr interface{} 26 sections []*SectionHeader 27 symbols []*Symbol 28 hasNoDwarfInfo bool 29} 30 31var 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 215func 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 235func 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 286func 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 294const ( 295 linkNoCgo = iota 296 linkCgoDefault 297 linkCgoInternal 298 linkCgoExternal 299) 300 301func getImageBase(f *File) uintptr { 302 switch oh := f.OptionalHeader.(type) { 303 case *OptionalHeader32: 304 return uintptr(oh.ImageBase) 305 case *OptionalHeader64: 306 return uintptr(oh.ImageBase) 307 default: 308 panic("unexpected optionalheader type") 309 } 310} 311 312func testDWARF(t *testing.T, linktype int) { 313 if runtime.GOOS != "windows" { 314 t.Skip("skipping windows only test") 315 } 316 testenv.MustHaveGoRun(t) 317 318 tmpdir, err := ioutil.TempDir("", "TestDWARF") 319 if err != nil { 320 t.Fatal(err) 321 } 322 defer os.RemoveAll(tmpdir) 323 324 src := filepath.Join(tmpdir, "a.go") 325 file, err := os.Create(src) 326 if err != nil { 327 t.Fatal(err) 328 } 329 err = template.Must(template.New("main").Parse(testprog)).Execute(file, linktype != linkNoCgo) 330 if err != nil { 331 if err := file.Close(); err != nil { 332 t.Error(err) 333 } 334 t.Fatal(err) 335 } 336 if err := file.Close(); err != nil { 337 t.Fatal(err) 338 } 339 340 exe := filepath.Join(tmpdir, "a.exe") 341 args := []string{"build", "-o", exe} 342 switch linktype { 343 case linkNoCgo: 344 case linkCgoDefault: 345 case linkCgoInternal: 346 args = append(args, "-ldflags", "-linkmode=internal") 347 case linkCgoExternal: 348 args = append(args, "-ldflags", "-linkmode=external") 349 default: 350 t.Fatalf("invalid linktype parameter of %v", linktype) 351 } 352 args = append(args, src) 353 out, err := exec.Command(testenv.GoToolPath(t), args...).CombinedOutput() 354 if err != nil { 355 t.Fatalf("building test executable for linktype %d failed: %s %s", linktype, err, out) 356 } 357 out, err = exec.Command(exe).CombinedOutput() 358 if err != nil { 359 t.Fatalf("running test executable failed: %s %s", err, out) 360 } 361 t.Logf("Testprog output:\n%s", string(out)) 362 363 matches := regexp.MustCompile("offset=(.*)\n").FindStringSubmatch(string(out)) 364 if len(matches) < 2 { 365 t.Fatalf("unexpected program output: %s", out) 366 } 367 wantoffset, err := strconv.ParseUint(matches[1], 0, 64) 368 if err != nil { 369 t.Fatalf("unexpected main offset %q: %s", matches[1], err) 370 } 371 372 f, err := Open(exe) 373 if err != nil { 374 t.Fatal(err) 375 } 376 defer f.Close() 377 378 imageBase := getImageBase(f) 379 380 var foundDebugGDBScriptsSection bool 381 for _, sect := range f.Sections { 382 if sect.Name == ".debug_gdb_scripts" { 383 foundDebugGDBScriptsSection = true 384 } 385 } 386 if !foundDebugGDBScriptsSection { 387 t.Error(".debug_gdb_scripts section is not found") 388 } 389 390 d, err := f.DWARF() 391 if err != nil { 392 t.Fatal(err) 393 } 394 395 // look for main.main 396 r := d.Reader() 397 for { 398 e, err := r.Next() 399 if err != nil { 400 t.Fatal("r.Next:", err) 401 } 402 if e == nil { 403 break 404 } 405 if e.Tag == dwarf.TagSubprogram { 406 name, ok := e.Val(dwarf.AttrName).(string) 407 if ok && name == "main.main" { 408 t.Logf("Found main.main") 409 addr, ok := e.Val(dwarf.AttrLowpc).(uint64) 410 if !ok { 411 t.Fatal("Failed to get AttrLowpc") 412 } 413 offset := uintptr(addr) - imageBase 414 if offset != uintptr(wantoffset) { 415 t.Fatal("Runtime offset (0x%x) did "+ 416 "not match dwarf offset "+ 417 "(0x%x)", wantoffset, offset) 418 } 419 return 420 } 421 } 422 } 423 t.Fatal("main.main not found") 424} 425 426func TestBSSHasZeros(t *testing.T) { 427 testenv.MustHaveExec(t) 428 429 if runtime.GOOS != "windows" { 430 t.Skip("skipping windows only test") 431 } 432 gccpath, err := exec.LookPath("gcc") 433 if err != nil { 434 t.Skip("skipping test: gcc is missing") 435 } 436 437 tmpdir, err := ioutil.TempDir("", "TestBSSHasZeros") 438 if err != nil { 439 t.Fatal(err) 440 } 441 defer os.RemoveAll(tmpdir) 442 443 srcpath := filepath.Join(tmpdir, "a.c") 444 src := ` 445#include <stdio.h> 446 447int zero = 0; 448 449int 450main(void) 451{ 452 printf("%d\n", zero); 453 return 0; 454} 455` 456 err = ioutil.WriteFile(srcpath, []byte(src), 0644) 457 if err != nil { 458 t.Fatal(err) 459 } 460 461 objpath := filepath.Join(tmpdir, "a.obj") 462 cmd := exec.Command(gccpath, "-c", srcpath, "-o", objpath) 463 out, err := cmd.CombinedOutput() 464 if err != nil { 465 t.Fatalf("failed to build object file: %v - %v", err, string(out)) 466 } 467 468 f, err := Open(objpath) 469 if err != nil { 470 t.Fatal(err) 471 } 472 defer f.Close() 473 474 var bss *Section 475 for _, sect := range f.Sections { 476 if sect.Name == ".bss" { 477 bss = sect 478 break 479 } 480 } 481 if bss == nil { 482 t.Fatal("could not find .bss section") 483 } 484 data, err := bss.Data() 485 if err != nil { 486 t.Fatal(err) 487 } 488 if len(data) == 0 { 489 t.Fatalf("%s file .bss section cannot be empty", objpath) 490 } 491 for _, b := range data { 492 if b != 0 { 493 t.Fatalf(".bss section has non zero bytes: %v", data) 494 } 495 } 496} 497 498func TestDWARF(t *testing.T) { 499 testDWARF(t, linkNoCgo) 500} 501 502const testprog = ` 503package main 504 505import "fmt" 506import "syscall" 507import "unsafe" 508{{if .}}import "C" 509{{end}} 510 511// struct MODULEINFO from the Windows SDK 512type moduleinfo struct { 513 BaseOfDll uintptr 514 SizeOfImage uint32 515 EntryPoint uintptr 516} 517 518func add(p unsafe.Pointer, x uintptr) unsafe.Pointer { 519 return unsafe.Pointer(uintptr(p) + x) 520} 521 522func funcPC(f interface{}) uintptr { 523 var a uintptr 524 return **(**uintptr)(add(unsafe.Pointer(&f), unsafe.Sizeof(a))) 525} 526 527func main() { 528 kernel32 := syscall.MustLoadDLL("kernel32.dll") 529 psapi := syscall.MustLoadDLL("psapi.dll") 530 getModuleHandle := kernel32.MustFindProc("GetModuleHandleW") 531 getCurrentProcess := kernel32.MustFindProc("GetCurrentProcess") 532 getModuleInformation := psapi.MustFindProc("GetModuleInformation") 533 534 procHandle, _, _ := getCurrentProcess.Call() 535 moduleHandle, _, err := getModuleHandle.Call(0) 536 if moduleHandle == 0 { 537 panic(fmt.Sprintf("GetModuleHandle() failed: %d", err)) 538 } 539 540 var info moduleinfo 541 ret, _, err := getModuleInformation.Call(procHandle, moduleHandle, 542 uintptr(unsafe.Pointer(&info)), unsafe.Sizeof(info)) 543 544 if ret == 0 { 545 panic(fmt.Sprintf("GetModuleInformation() failed: %d", err)) 546 } 547 548 offset := funcPC(main) - info.BaseOfDll 549 fmt.Printf("base=0x%x\n", info.BaseOfDll) 550 fmt.Printf("main=%p\n", main) 551 fmt.Printf("offset=0x%x\n", offset) 552} 553` 554 555func TestBuildingWindowsGUI(t *testing.T) { 556 testenv.MustHaveGoBuild(t) 557 558 if runtime.GOOS != "windows" { 559 t.Skip("skipping windows only test") 560 } 561 tmpdir, err := ioutil.TempDir("", "TestBuildingWindowsGUI") 562 if err != nil { 563 t.Fatal(err) 564 } 565 defer os.RemoveAll(tmpdir) 566 567 src := filepath.Join(tmpdir, "a.go") 568 err = ioutil.WriteFile(src, []byte(`package main; func main() {}`), 0644) 569 if err != nil { 570 t.Fatal(err) 571 } 572 exe := filepath.Join(tmpdir, "a.exe") 573 cmd := exec.Command(testenv.GoToolPath(t), "build", "-ldflags", "-H=windowsgui", "-o", exe, src) 574 out, err := cmd.CombinedOutput() 575 if err != nil { 576 t.Fatalf("building test executable failed: %s %s", err, out) 577 } 578 579 f, err := Open(exe) 580 if err != nil { 581 t.Fatal(err) 582 } 583 defer f.Close() 584 585 const _IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 586 587 switch oh := f.OptionalHeader.(type) { 588 case *OptionalHeader32: 589 if oh.Subsystem != _IMAGE_SUBSYSTEM_WINDOWS_GUI { 590 t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, _IMAGE_SUBSYSTEM_WINDOWS_GUI) 591 } 592 case *OptionalHeader64: 593 if oh.Subsystem != _IMAGE_SUBSYSTEM_WINDOWS_GUI { 594 t.Errorf("unexpected Subsystem value: have %d, but want %d", oh.Subsystem, _IMAGE_SUBSYSTEM_WINDOWS_GUI) 595 } 596 default: 597 t.Fatalf("unexpected OptionalHeader type: have %T, but want *pe.OptionalHeader32 or *pe.OptionalHeader64", oh) 598 } 599} 600 601func TestImportTableInUnknownSection(t *testing.T) { 602 if runtime.GOOS != "windows" { 603 t.Skip("skipping Windows-only test") 604 } 605 606 // ws2_32.dll import table is located in ".rdata" section, 607 // so it is good enough to test issue #16103. 608 const filename = "ws2_32.dll" 609 path, err := exec.LookPath(filename) 610 if err != nil { 611 t.Fatalf("unable to locate required file %q in search path: %s", filename, err) 612 } 613 614 f, err := Open(path) 615 if err != nil { 616 t.Error(err) 617 } 618 defer f.Close() 619 620 // now we can extract its imports 621 symbols, err := f.ImportedSymbols() 622 if err != nil { 623 t.Error(err) 624 } 625 626 if len(symbols) == 0 { 627 t.Fatalf("unable to locate any imported symbols within file %q.", path) 628 } 629} 630