github.com/corona10/go@v0.0.0-20180224231303-7a218942be57/src/cmd/link/internal/ld/pe.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 ld 6 7 import ( 8 "cmd/internal/objabi" 9 "cmd/internal/sys" 10 "cmd/link/internal/sym" 11 "debug/pe" 12 "encoding/binary" 13 "fmt" 14 "sort" 15 "strconv" 16 "strings" 17 ) 18 19 type IMAGE_IMPORT_DESCRIPTOR struct { 20 OriginalFirstThunk uint32 21 TimeDateStamp uint32 22 ForwarderChain uint32 23 Name uint32 24 FirstThunk uint32 25 } 26 27 type IMAGE_EXPORT_DIRECTORY struct { 28 Characteristics uint32 29 TimeDateStamp uint32 30 MajorVersion uint16 31 MinorVersion uint16 32 Name uint32 33 Base uint32 34 NumberOfFunctions uint32 35 NumberOfNames uint32 36 AddressOfFunctions uint32 37 AddressOfNames uint32 38 AddressOfNameOrdinals uint32 39 } 40 41 const ( 42 PEBASE = 0x00400000 43 ) 44 45 var ( 46 // SectionAlignment must be greater than or equal to FileAlignment. 47 // The default is the page size for the architecture. 48 PESECTALIGN int64 = 0x1000 49 50 // FileAlignment should be a power of 2 between 512 and 64 K, inclusive. 51 // The default is 512. If the SectionAlignment is less than 52 // the architecture's page size, then FileAlignment must match SectionAlignment. 53 PEFILEALIGN int64 = 2 << 8 54 ) 55 56 const ( 57 IMAGE_FILE_MACHINE_I386 = 0x14c 58 IMAGE_FILE_MACHINE_AMD64 = 0x8664 59 IMAGE_FILE_RELOCS_STRIPPED = 0x0001 60 IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 61 IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 62 IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 63 IMAGE_FILE_32BIT_MACHINE = 0x0100 64 IMAGE_FILE_DEBUG_STRIPPED = 0x0200 65 IMAGE_SCN_CNT_CODE = 0x00000020 66 IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 67 IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 68 IMAGE_SCN_MEM_EXECUTE = 0x20000000 69 IMAGE_SCN_MEM_READ = 0x40000000 70 IMAGE_SCN_MEM_WRITE = 0x80000000 71 IMAGE_SCN_MEM_DISCARDABLE = 0x2000000 72 IMAGE_SCN_LNK_NRELOC_OVFL = 0x1000000 73 IMAGE_SCN_ALIGN_32BYTES = 0x600000 74 IMAGE_DIRECTORY_ENTRY_EXPORT = 0 75 IMAGE_DIRECTORY_ENTRY_IMPORT = 1 76 IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 77 IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 78 IMAGE_DIRECTORY_ENTRY_SECURITY = 4 79 IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 80 IMAGE_DIRECTORY_ENTRY_DEBUG = 6 81 IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 82 IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 83 IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 84 IMAGE_DIRECTORY_ENTRY_TLS = 9 85 IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 86 IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 87 IMAGE_DIRECTORY_ENTRY_IAT = 12 88 IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 89 IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 90 IMAGE_SUBSYSTEM_WINDOWS_GUI = 2 91 IMAGE_SUBSYSTEM_WINDOWS_CUI = 3 92 ) 93 94 // TODO(crawshaw): add these constants to debug/pe. 95 const ( 96 // TODO: the Microsoft doco says IMAGE_SYM_DTYPE_ARRAY is 3 and IMAGE_SYM_DTYPE_FUNCTION is 2 97 IMAGE_SYM_TYPE_NULL = 0 98 IMAGE_SYM_TYPE_STRUCT = 8 99 IMAGE_SYM_DTYPE_FUNCTION = 0x20 100 IMAGE_SYM_DTYPE_ARRAY = 0x30 101 IMAGE_SYM_CLASS_EXTERNAL = 2 102 IMAGE_SYM_CLASS_STATIC = 3 103 104 IMAGE_REL_I386_DIR32 = 0x0006 105 IMAGE_REL_I386_SECREL = 0x000B 106 IMAGE_REL_I386_REL32 = 0x0014 107 108 IMAGE_REL_AMD64_ADDR64 = 0x0001 109 IMAGE_REL_AMD64_ADDR32 = 0x0002 110 IMAGE_REL_AMD64_REL32 = 0x0004 111 IMAGE_REL_AMD64_SECREL = 0x000B 112 ) 113 114 // Copyright 2009 The Go Authors. All rights reserved. 115 // Use of this source code is governed by a BSD-style 116 // license that can be found in the LICENSE file. 117 118 // PE (Portable Executable) file writing 119 // http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx 120 121 // DOS stub that prints out 122 // "This program cannot be run in DOS mode." 123 var dosstub = []uint8{ 124 0x4d, 125 0x5a, 126 0x90, 127 0x00, 128 0x03, 129 0x00, 130 0x04, 131 0x00, 132 0x00, 133 0x00, 134 0x00, 135 0x00, 136 0xff, 137 0xff, 138 0x00, 139 0x00, 140 0x8b, 141 0x00, 142 0x00, 143 0x00, 144 0x00, 145 0x00, 146 0x00, 147 0x00, 148 0x40, 149 0x00, 150 0x00, 151 0x00, 152 0x00, 153 0x00, 154 0x00, 155 0x00, 156 0x00, 157 0x00, 158 0x00, 159 0x00, 160 0x00, 161 0x00, 162 0x00, 163 0x00, 164 0x00, 165 0x00, 166 0x00, 167 0x00, 168 0x00, 169 0x00, 170 0x00, 171 0x00, 172 0x00, 173 0x00, 174 0x00, 175 0x00, 176 0x00, 177 0x00, 178 0x00, 179 0x00, 180 0x00, 181 0x00, 182 0x00, 183 0x00, 184 0x80, 185 0x00, 186 0x00, 187 0x00, 188 0x0e, 189 0x1f, 190 0xba, 191 0x0e, 192 0x00, 193 0xb4, 194 0x09, 195 0xcd, 196 0x21, 197 0xb8, 198 0x01, 199 0x4c, 200 0xcd, 201 0x21, 202 0x54, 203 0x68, 204 0x69, 205 0x73, 206 0x20, 207 0x70, 208 0x72, 209 0x6f, 210 0x67, 211 0x72, 212 0x61, 213 0x6d, 214 0x20, 215 0x63, 216 0x61, 217 0x6e, 218 0x6e, 219 0x6f, 220 0x74, 221 0x20, 222 0x62, 223 0x65, 224 0x20, 225 0x72, 226 0x75, 227 0x6e, 228 0x20, 229 0x69, 230 0x6e, 231 0x20, 232 0x44, 233 0x4f, 234 0x53, 235 0x20, 236 0x6d, 237 0x6f, 238 0x64, 239 0x65, 240 0x2e, 241 0x0d, 242 0x0d, 243 0x0a, 244 0x24, 245 0x00, 246 0x00, 247 0x00, 248 0x00, 249 0x00, 250 0x00, 251 0x00, 252 } 253 254 type Imp struct { 255 s *sym.Symbol 256 off uint64 257 next *Imp 258 argsize int 259 } 260 261 type Dll struct { 262 name string 263 nameoff uint64 264 thunkoff uint64 265 ms *Imp 266 next *Dll 267 } 268 269 var ( 270 rsrcsym *sym.Symbol 271 PESECTHEADR int32 272 PEFILEHEADR int32 273 pe64 int 274 dr *Dll 275 dexport [1024]*sym.Symbol 276 nexport int 277 ) 278 279 // peStringTable is a COFF string table. 280 type peStringTable struct { 281 strings []string 282 stringsLen int 283 } 284 285 // size resturns size of string table t. 286 func (t *peStringTable) size() int { 287 // string table starts with 4-byte length at the beginning 288 return t.stringsLen + 4 289 } 290 291 // add adds string str to string table t. 292 func (t *peStringTable) add(str string) int { 293 off := t.size() 294 t.strings = append(t.strings, str) 295 t.stringsLen += len(str) + 1 // each string will have 0 appended to it 296 return off 297 } 298 299 // write writes string table t into the output file. 300 func (t *peStringTable) write(out *OutBuf) { 301 out.Write32(uint32(t.size())) 302 for _, s := range t.strings { 303 out.WriteString(s) 304 out.Write8(0) 305 } 306 } 307 308 // peSection represents section from COFF section table. 309 type peSection struct { 310 name string 311 shortName string 312 index int // one-based index into the Section Table 313 virtualSize uint32 314 virtualAddress uint32 315 sizeOfRawData uint32 316 pointerToRawData uint32 317 pointerToRelocations uint32 318 numberOfRelocations uint16 319 characteristics uint32 320 } 321 322 // checkOffset verifies COFF section sect offset in the file. 323 func (sect *peSection) checkOffset(off int64) { 324 if off != int64(sect.pointerToRawData) { 325 Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(off)) 326 errorexit() 327 } 328 } 329 330 // checkSegment verifies COFF section sect matches address 331 // and file offset provided in segment seg. 332 func (sect *peSection) checkSegment(seg *sym.Segment) { 333 if seg.Vaddr-PEBASE != uint64(sect.virtualAddress) { 334 Errorf(nil, "%s.VirtualAddress = %#x, want %#x", sect.name, uint64(int64(sect.virtualAddress)), uint64(int64(seg.Vaddr-PEBASE))) 335 errorexit() 336 } 337 if seg.Fileoff != uint64(sect.pointerToRawData) { 338 Errorf(nil, "%s.PointerToRawData = %#x, want %#x", sect.name, uint64(int64(sect.pointerToRawData)), uint64(int64(seg.Fileoff))) 339 errorexit() 340 } 341 } 342 343 // pad adds zeros to the section sect. It writes as many bytes 344 // as necessary to make section sect.SizeOfRawData bytes long. 345 // It assumes that n bytes are already written to the file. 346 func (sect *peSection) pad(out *OutBuf, n uint32) { 347 out.WriteStringN("", int(sect.sizeOfRawData-n)) 348 } 349 350 // write writes COFF section sect into the output file. 351 func (sect *peSection) write(out *OutBuf, linkmode LinkMode) error { 352 h := pe.SectionHeader32{ 353 VirtualSize: sect.virtualSize, 354 SizeOfRawData: sect.sizeOfRawData, 355 PointerToRawData: sect.pointerToRawData, 356 PointerToRelocations: sect.pointerToRelocations, 357 NumberOfRelocations: sect.numberOfRelocations, 358 Characteristics: sect.characteristics, 359 } 360 if linkmode != LinkExternal { 361 h.VirtualAddress = sect.virtualAddress 362 } 363 copy(h.Name[:], sect.shortName) 364 return binary.Write(out, binary.LittleEndian, h) 365 } 366 367 // emitRelocations emits the relocation entries for the sect. 368 // The actual relocations are emitted by relocfn. 369 // This updates the corresponding PE section table entry 370 // with the relocation offset and count. 371 func (sect *peSection) emitRelocations(out *OutBuf, relocfn func() int) { 372 sect.pointerToRelocations = uint32(out.Offset()) 373 // first entry: extended relocs 374 out.Write32(0) // placeholder for number of relocation + 1 375 out.Write32(0) 376 out.Write16(0) 377 378 n := relocfn() + 1 379 380 cpos := out.Offset() 381 out.SeekSet(int64(sect.pointerToRelocations)) 382 out.Write32(uint32(n)) 383 out.SeekSet(cpos) 384 if n > 0x10000 { 385 n = 0x10000 386 sect.characteristics |= IMAGE_SCN_LNK_NRELOC_OVFL 387 } else { 388 sect.pointerToRelocations += 10 // skip the extend reloc entry 389 } 390 sect.numberOfRelocations = uint16(n - 1) 391 } 392 393 // peFile is used to build COFF file. 394 type peFile struct { 395 sections []*peSection 396 stringTable peStringTable 397 textSect *peSection 398 dataSect *peSection 399 bssSect *peSection 400 ctorsSect *peSection 401 nextSectOffset uint32 402 nextFileOffset uint32 403 symtabOffset int64 // offset to the start of symbol table 404 symbolCount int // number of symbol table records written 405 dataDirectory [16]pe.DataDirectory 406 } 407 408 // addSection adds section to the COFF file f. 409 func (f *peFile) addSection(name string, sectsize int, filesize int) *peSection { 410 sect := &peSection{ 411 name: name, 412 shortName: name, 413 index: len(f.sections) + 1, 414 virtualSize: uint32(sectsize), 415 virtualAddress: f.nextSectOffset, 416 pointerToRawData: f.nextFileOffset, 417 } 418 f.nextSectOffset = uint32(Rnd(int64(f.nextSectOffset)+int64(sectsize), PESECTALIGN)) 419 if filesize > 0 { 420 sect.sizeOfRawData = uint32(Rnd(int64(filesize), PEFILEALIGN)) 421 f.nextFileOffset += sect.sizeOfRawData 422 } 423 f.sections = append(f.sections, sect) 424 return sect 425 } 426 427 // addDWARFSection adds DWARF section to the COFF file f. 428 // This function is similar to addSection, but DWARF section names are 429 // longer than 8 characters, so they need to be stored in the string table. 430 func (f *peFile) addDWARFSection(name string, size int) *peSection { 431 if size == 0 { 432 Exitf("DWARF section %q is empty", name) 433 } 434 // DWARF section names are longer than 8 characters. 435 // PE format requires such names to be stored in string table, 436 // and section names replaced with slash (/) followed by 437 // correspondent string table index. 438 // see http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx 439 // for details 440 off := f.stringTable.add(name) 441 h := f.addSection(name, size, size) 442 h.shortName = fmt.Sprintf("/%d", off) 443 h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE 444 return h 445 } 446 447 // addDWARF adds DWARF information to the COFF file f. 448 func (f *peFile) addDWARF() { 449 if *FlagS { // disable symbol table 450 return 451 } 452 if *FlagW { // disable dwarf 453 return 454 } 455 for _, sect := range Segdwarf.Sections { 456 h := f.addDWARFSection(sect.Name, int(sect.Length)) 457 fileoff := sect.Vaddr - Segdwarf.Vaddr + Segdwarf.Fileoff 458 if uint64(h.pointerToRawData) != fileoff { 459 Exitf("%s.PointerToRawData = %#x, want %#x", sect.Name, h.pointerToRawData, fileoff) 460 } 461 } 462 } 463 464 // addInitArray adds .ctors COFF section to the file f. 465 func (f *peFile) addInitArray(ctxt *Link) *peSection { 466 // The size below was determined by the specification for array relocations, 467 // and by observing what GCC writes here. If the initarray section grows to 468 // contain more than one constructor entry, the size will need to be 8 * constructor_count. 469 // However, the entire Go runtime is initialized from just one function, so it is unlikely 470 // that this will need to grow in the future. 471 var size int 472 switch objabi.GOARCH { 473 default: 474 Exitf("peFile.addInitArray: unsupported GOARCH=%q\n", objabi.GOARCH) 475 case "386": 476 size = 4 477 case "amd64": 478 size = 8 479 } 480 sect := f.addSection(".ctors", size, size) 481 sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ 482 sect.sizeOfRawData = uint32(size) 483 ctxt.Out.SeekSet(int64(sect.pointerToRawData)) 484 sect.checkOffset(ctxt.Out.Offset()) 485 486 init_entry := ctxt.Syms.Lookup(*flagEntrySymbol, 0) 487 addr := uint64(init_entry.Value) - init_entry.Sect.Vaddr 488 switch objabi.GOARCH { 489 case "386": 490 ctxt.Out.Write32(uint32(addr)) 491 case "amd64": 492 ctxt.Out.Write64(addr) 493 } 494 return sect 495 } 496 497 // emitRelocations emits relocation entries for go.o in external linking. 498 func (f *peFile) emitRelocations(ctxt *Link) { 499 for ctxt.Out.Offset()&7 != 0 { 500 ctxt.Out.Write8(0) 501 } 502 503 // relocsect relocates symbols from first in section sect, and returns 504 // the total number of relocations emitted. 505 relocsect := func(sect *sym.Section, syms []*sym.Symbol, base uint64) int { 506 // If main section has no bits, nothing to relocate. 507 if sect.Vaddr >= sect.Seg.Vaddr+sect.Seg.Filelen { 508 return 0 509 } 510 relocs := 0 511 sect.Reloff = uint64(ctxt.Out.Offset()) 512 for i, s := range syms { 513 if !s.Attr.Reachable() { 514 continue 515 } 516 if uint64(s.Value) >= sect.Vaddr { 517 syms = syms[i:] 518 break 519 } 520 } 521 eaddr := int32(sect.Vaddr + sect.Length) 522 for _, sym := range syms { 523 if !sym.Attr.Reachable() { 524 continue 525 } 526 if sym.Value >= int64(eaddr) { 527 break 528 } 529 for ri := 0; ri < len(sym.R); ri++ { 530 r := &sym.R[ri] 531 if r.Done { 532 continue 533 } 534 if r.Xsym == nil { 535 Errorf(sym, "missing xsym in relocation") 536 continue 537 } 538 if r.Xsym.Dynid < 0 { 539 Errorf(sym, "reloc %d to non-coff symbol %s (outer=%s) %d", r.Type, r.Sym.Name, r.Xsym.Name, r.Sym.Type) 540 } 541 if !Thearch.PEreloc1(ctxt.Arch, ctxt.Out, sym, r, int64(uint64(sym.Value+int64(r.Off))-base)) { 542 Errorf(sym, "unsupported obj reloc %d/%d to %s", r.Type, r.Siz, r.Sym.Name) 543 } 544 relocs++ 545 } 546 } 547 sect.Rellen = uint64(ctxt.Out.Offset()) - sect.Reloff 548 return relocs 549 } 550 551 f.textSect.emitRelocations(ctxt.Out, func() int { 552 n := relocsect(Segtext.Sections[0], ctxt.Textp, Segtext.Vaddr) 553 for _, sect := range Segtext.Sections[1:] { 554 n += relocsect(sect, datap, Segtext.Vaddr) 555 } 556 return n 557 }) 558 559 f.dataSect.emitRelocations(ctxt.Out, func() int { 560 var n int 561 for _, sect := range Segdata.Sections { 562 n += relocsect(sect, datap, Segdata.Vaddr) 563 } 564 return n 565 }) 566 567 dwarfLoop: 568 for _, sect := range Segdwarf.Sections { 569 for _, pesect := range f.sections { 570 if sect.Name == pesect.name { 571 pesect.emitRelocations(ctxt.Out, func() int { 572 return relocsect(sect, dwarfp, sect.Vaddr) 573 }) 574 continue dwarfLoop 575 } 576 } 577 Errorf(nil, "emitRelocations: could not find %q section", sect.Name) 578 } 579 580 f.ctorsSect.emitRelocations(ctxt.Out, func() int { 581 dottext := ctxt.Syms.Lookup(".text", 0) 582 ctxt.Out.Write32(0) 583 ctxt.Out.Write32(uint32(dottext.Dynid)) 584 switch objabi.GOARCH { 585 default: 586 Errorf(dottext, "unknown architecture for PE: %q\n", objabi.GOARCH) 587 case "386": 588 ctxt.Out.Write16(IMAGE_REL_I386_DIR32) 589 case "amd64": 590 ctxt.Out.Write16(IMAGE_REL_AMD64_ADDR64) 591 } 592 return 1 593 }) 594 } 595 596 // writeSymbol appends symbol s to file f symbol table. 597 // It also sets s.Dynid to written symbol number. 598 func (f *peFile) writeSymbol(out *OutBuf, s *sym.Symbol, value int64, sectidx int, typ uint16, class uint8) { 599 if len(s.Name) > 8 { 600 out.Write32(0) 601 out.Write32(uint32(f.stringTable.add(s.Name))) 602 } else { 603 out.WriteStringN(s.Name, 8) 604 } 605 out.Write32(uint32(value)) 606 out.Write16(uint16(sectidx)) 607 out.Write16(typ) 608 out.Write8(class) 609 out.Write8(0) // no aux entries 610 611 s.Dynid = int32(f.symbolCount) 612 613 f.symbolCount++ 614 } 615 616 // mapToPESection searches peFile f for s symbol's location. 617 // It returns PE section index, and offset within that section. 618 func (f *peFile) mapToPESection(s *sym.Symbol, linkmode LinkMode) (pesectidx int, offset int64, err error) { 619 if s.Sect == nil { 620 return 0, 0, fmt.Errorf("could not map %s symbol with no section", s.Name) 621 } 622 if s.Sect.Seg == &Segtext { 623 return f.textSect.index, int64(uint64(s.Value) - Segtext.Vaddr), nil 624 } 625 if s.Sect.Seg != &Segdata { 626 return 0, 0, fmt.Errorf("could not map %s symbol with non .text or .data section", s.Name) 627 } 628 v := uint64(s.Value) - Segdata.Vaddr 629 if linkmode != LinkExternal { 630 return f.dataSect.index, int64(v), nil 631 } 632 if s.Type == sym.SDATA { 633 return f.dataSect.index, int64(v), nil 634 } 635 // Note: although address of runtime.edata (type sym.SDATA) is at the start of .bss section 636 // it still belongs to the .data section, not the .bss section. 637 if v < Segdata.Filelen { 638 return f.dataSect.index, int64(v), nil 639 } 640 return f.bssSect.index, int64(v - Segdata.Filelen), nil 641 } 642 643 // writeSymbols writes all COFF symbol table records. 644 func (f *peFile) writeSymbols(ctxt *Link) { 645 646 put := func(ctxt *Link, s *sym.Symbol, name string, type_ SymbolType, addr int64, gotype *sym.Symbol) { 647 if s == nil { 648 return 649 } 650 if s.Sect == nil && type_ != UndefinedSym { 651 return 652 } 653 switch type_ { 654 default: 655 return 656 case DataSym, BSSSym, TextSym, UndefinedSym: 657 } 658 659 // Only windows/386 requires underscore prefix on external symbols. 660 if ctxt.Arch.Family == sys.I386 && 661 ctxt.LinkMode == LinkExternal && 662 (s.Type == sym.SHOSTOBJ || s.Attr.CgoExport()) { 663 s.Name = "_" + s.Name 664 } 665 666 var typ uint16 667 if ctxt.LinkMode == LinkExternal { 668 typ = IMAGE_SYM_TYPE_NULL 669 } else { 670 // TODO: fix IMAGE_SYM_DTYPE_ARRAY value and use following expression, instead of 0x0308 671 typ = IMAGE_SYM_DTYPE_ARRAY<<8 + IMAGE_SYM_TYPE_STRUCT 672 typ = 0x0308 // "array of structs" 673 } 674 sect, value, err := f.mapToPESection(s, ctxt.LinkMode) 675 if err != nil { 676 if type_ == UndefinedSym { 677 typ = IMAGE_SYM_DTYPE_FUNCTION 678 } else { 679 Errorf(s, "addpesym: %v", err) 680 } 681 } 682 class := IMAGE_SYM_CLASS_EXTERNAL 683 if s.Version != 0 || s.Attr.VisibilityHidden() || s.Attr.Local() { 684 class = IMAGE_SYM_CLASS_STATIC 685 } 686 f.writeSymbol(ctxt.Out, s, value, sect, typ, uint8(class)) 687 } 688 689 if ctxt.LinkMode == LinkExternal { 690 // Include section symbols as external, because 691 // .ctors and .debug_* section relocations refer to it. 692 for _, pesect := range f.sections { 693 sym := ctxt.Syms.Lookup(pesect.name, 0) 694 f.writeSymbol(ctxt.Out, sym, 0, pesect.index, IMAGE_SYM_TYPE_NULL, IMAGE_SYM_CLASS_STATIC) 695 } 696 } 697 698 genasmsym(ctxt, put) 699 } 700 701 // writeSymbolTableAndStringTable writes out symbol and string tables for peFile f. 702 func (f *peFile) writeSymbolTableAndStringTable(ctxt *Link) { 703 f.symtabOffset = ctxt.Out.Offset() 704 705 // write COFF symbol table 706 if !*FlagS || ctxt.LinkMode == LinkExternal { 707 f.writeSymbols(ctxt) 708 } 709 710 // update COFF file header and section table 711 size := f.stringTable.size() + 18*f.symbolCount 712 var h *peSection 713 if ctxt.LinkMode != LinkExternal { 714 // We do not really need .symtab for go.o, and if we have one, ld 715 // will also include it in the exe, and that will confuse windows. 716 h = f.addSection(".symtab", size, size) 717 h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_DISCARDABLE 718 h.checkOffset(f.symtabOffset) 719 } 720 721 // write COFF string table 722 f.stringTable.write(ctxt.Out) 723 if ctxt.LinkMode != LinkExternal { 724 h.pad(ctxt.Out, uint32(size)) 725 } 726 } 727 728 // writeFileHeader writes COFF file header for peFile f. 729 func (f *peFile) writeFileHeader(arch *sys.Arch, out *OutBuf, linkmode LinkMode) { 730 var fh pe.FileHeader 731 732 switch arch.Family { 733 default: 734 Exitf("unknown PE architecture: %v", arch.Family) 735 case sys.AMD64: 736 fh.Machine = IMAGE_FILE_MACHINE_AMD64 737 case sys.I386: 738 fh.Machine = IMAGE_FILE_MACHINE_I386 739 } 740 741 fh.NumberOfSections = uint16(len(f.sections)) 742 743 // Being able to produce identical output for identical input is 744 // much more beneficial than having build timestamp in the header. 745 fh.TimeDateStamp = 0 746 747 if linkmode == LinkExternal { 748 fh.Characteristics = IMAGE_FILE_LINE_NUMS_STRIPPED 749 } else { 750 fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED | IMAGE_FILE_EXECUTABLE_IMAGE | IMAGE_FILE_DEBUG_STRIPPED 751 } 752 if pe64 != 0 { 753 var oh64 pe.OptionalHeader64 754 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh64)) 755 fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE 756 } else { 757 var oh pe.OptionalHeader32 758 fh.SizeOfOptionalHeader = uint16(binary.Size(&oh)) 759 fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE 760 } 761 762 fh.PointerToSymbolTable = uint32(f.symtabOffset) 763 fh.NumberOfSymbols = uint32(f.symbolCount) 764 765 binary.Write(out, binary.LittleEndian, &fh) 766 } 767 768 // writeOptionalHeader writes COFF optional header for peFile f. 769 func (f *peFile) writeOptionalHeader(ctxt *Link) { 770 var oh pe.OptionalHeader32 771 var oh64 pe.OptionalHeader64 772 773 if pe64 != 0 { 774 oh64.Magic = 0x20b // PE32+ 775 } else { 776 oh.Magic = 0x10b // PE32 777 oh.BaseOfData = f.dataSect.virtualAddress 778 } 779 780 // Fill out both oh64 and oh. We only use one. Oh well. 781 oh64.MajorLinkerVersion = 3 782 oh.MajorLinkerVersion = 3 783 oh64.MinorLinkerVersion = 0 784 oh.MinorLinkerVersion = 0 785 oh64.SizeOfCode = f.textSect.sizeOfRawData 786 oh.SizeOfCode = f.textSect.sizeOfRawData 787 oh64.SizeOfInitializedData = f.dataSect.sizeOfRawData 788 oh.SizeOfInitializedData = f.dataSect.sizeOfRawData 789 oh64.SizeOfUninitializedData = 0 790 oh.SizeOfUninitializedData = 0 791 if ctxt.LinkMode != LinkExternal { 792 oh64.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE) 793 oh.AddressOfEntryPoint = uint32(Entryvalue(ctxt) - PEBASE) 794 } 795 oh64.BaseOfCode = f.textSect.virtualAddress 796 oh.BaseOfCode = f.textSect.virtualAddress 797 oh64.ImageBase = PEBASE 798 oh.ImageBase = PEBASE 799 oh64.SectionAlignment = uint32(PESECTALIGN) 800 oh.SectionAlignment = uint32(PESECTALIGN) 801 oh64.FileAlignment = uint32(PEFILEALIGN) 802 oh.FileAlignment = uint32(PEFILEALIGN) 803 oh64.MajorOperatingSystemVersion = 4 804 oh.MajorOperatingSystemVersion = 4 805 oh64.MinorOperatingSystemVersion = 0 806 oh.MinorOperatingSystemVersion = 0 807 oh64.MajorImageVersion = 1 808 oh.MajorImageVersion = 1 809 oh64.MinorImageVersion = 0 810 oh.MinorImageVersion = 0 811 oh64.MajorSubsystemVersion = 4 812 oh.MajorSubsystemVersion = 4 813 oh64.MinorSubsystemVersion = 0 814 oh.MinorSubsystemVersion = 0 815 oh64.SizeOfImage = f.nextSectOffset 816 oh.SizeOfImage = f.nextSectOffset 817 oh64.SizeOfHeaders = uint32(PEFILEHEADR) 818 oh.SizeOfHeaders = uint32(PEFILEHEADR) 819 if windowsgui { 820 oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI 821 oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_GUI 822 } else { 823 oh64.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI 824 oh.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI 825 } 826 827 // Disable stack growth as we don't want Windows to 828 // fiddle with the thread stack limits, which we set 829 // ourselves to circumvent the stack checks in the 830 // Windows exception dispatcher. 831 // Commit size must be strictly less than reserve 832 // size otherwise reserve will be rounded up to a 833 // larger size, as verified with VMMap. 834 835 // On 64-bit, we always reserve 2MB stacks. "Pure" Go code is 836 // okay with much smaller stacks, but the syscall package 837 // makes it easy to call into arbitrary C code without cgo, 838 // and system calls even in "pure" Go code are actually C 839 // calls that may need more stack than we think. 840 // 841 // The default stack reserve size affects only the main 842 // thread, ctrlhandler thread, and profileloop thread. For 843 // these, it must be greater than the stack size assumed by 844 // externalthreadhandler. 845 // 846 // For other threads we specify stack size in runtime explicitly. 847 // For these, the reserve must match STACKSIZE in 848 // runtime/cgo/gcc_windows_{386,amd64}.c and the correspondent 849 // CreateThread parameter in runtime.newosproc. 850 oh64.SizeOfStackReserve = 0x00200000 851 if !iscgo { 852 oh64.SizeOfStackCommit = 0x00001000 853 } else { 854 // TODO(brainman): Maybe remove optional header writing altogether for cgo. 855 // For cgo it is the external linker that is building final executable. 856 // And it probably does not use any information stored in optional header. 857 oh64.SizeOfStackCommit = 0x00200000 - 0x2000 // account for 2 guard pages 858 } 859 860 oh.SizeOfStackReserve = 0x00100000 861 if !iscgo { 862 oh.SizeOfStackCommit = 0x00001000 863 } else { 864 oh.SizeOfStackCommit = 0x00100000 - 0x2000 // account for 2 guard pages 865 } 866 867 oh64.SizeOfHeapReserve = 0x00100000 868 oh.SizeOfHeapReserve = 0x00100000 869 oh64.SizeOfHeapCommit = 0x00001000 870 oh.SizeOfHeapCommit = 0x00001000 871 oh64.NumberOfRvaAndSizes = 16 872 oh.NumberOfRvaAndSizes = 16 873 874 if pe64 != 0 { 875 oh64.DataDirectory = f.dataDirectory 876 } else { 877 oh.DataDirectory = f.dataDirectory 878 } 879 880 if pe64 != 0 { 881 binary.Write(ctxt.Out, binary.LittleEndian, &oh64) 882 } else { 883 binary.Write(ctxt.Out, binary.LittleEndian, &oh) 884 } 885 } 886 887 var pefile peFile 888 889 func Peinit(ctxt *Link) { 890 var l int 891 892 switch ctxt.Arch.Family { 893 // 64-bit architectures 894 case sys.AMD64: 895 pe64 = 1 896 var oh64 pe.OptionalHeader64 897 l = binary.Size(&oh64) 898 899 // 32-bit architectures 900 default: 901 var oh pe.OptionalHeader32 902 l = binary.Size(&oh) 903 904 } 905 906 if ctxt.LinkMode == LinkExternal { 907 PESECTALIGN = 0 908 PEFILEALIGN = 0 909 } 910 911 var sh [16]pe.SectionHeader32 912 var fh pe.FileHeader 913 PEFILEHEADR = int32(Rnd(int64(len(dosstub)+binary.Size(&fh)+l+binary.Size(&sh)), PEFILEALIGN)) 914 if ctxt.LinkMode != LinkExternal { 915 PESECTHEADR = int32(Rnd(int64(PEFILEHEADR), PESECTALIGN)) 916 } else { 917 PESECTHEADR = 0 918 } 919 pefile.nextSectOffset = uint32(PESECTHEADR) 920 pefile.nextFileOffset = uint32(PEFILEHEADR) 921 922 if ctxt.LinkMode == LinkInternal { 923 // some mingw libs depend on this symbol, for example, FindPESectionByName 924 ctxt.xdefine("__image_base__", sym.SDATA, PEBASE) 925 ctxt.xdefine("_image_base__", sym.SDATA, PEBASE) 926 } 927 928 HEADR = PEFILEHEADR 929 if *FlagTextAddr == -1 { 930 *FlagTextAddr = PEBASE + int64(PESECTHEADR) 931 } 932 if *FlagDataAddr == -1 { 933 *FlagDataAddr = 0 934 } 935 if *FlagRound == -1 { 936 *FlagRound = int(PESECTALIGN) 937 } 938 if *FlagDataAddr != 0 && *FlagRound != 0 { 939 fmt.Printf("warning: -D0x%x is ignored because of -R0x%x\n", uint64(*FlagDataAddr), uint32(*FlagRound)) 940 } 941 } 942 943 func pewrite(ctxt *Link) { 944 ctxt.Out.SeekSet(0) 945 if ctxt.LinkMode != LinkExternal { 946 ctxt.Out.Write(dosstub) 947 ctxt.Out.WriteStringN("PE", 4) 948 } 949 950 pefile.writeFileHeader(ctxt.Arch, ctxt.Out, ctxt.LinkMode) 951 952 pefile.writeOptionalHeader(ctxt) 953 954 for _, sect := range pefile.sections { 955 sect.write(ctxt.Out, ctxt.LinkMode) 956 } 957 } 958 959 func strput(out *OutBuf, s string) { 960 out.WriteString(s) 961 out.Write8(0) 962 // string must be padded to even size 963 if (len(s)+1)%2 != 0 { 964 out.Write8(0) 965 } 966 } 967 968 func initdynimport(ctxt *Link) *Dll { 969 var d *Dll 970 971 dr = nil 972 var m *Imp 973 for _, s := range ctxt.Syms.Allsym { 974 if !s.Attr.Reachable() || s.Type != sym.SDYNIMPORT { 975 continue 976 } 977 for d = dr; d != nil; d = d.next { 978 if d.name == s.Dynimplib { 979 m = new(Imp) 980 break 981 } 982 } 983 984 if d == nil { 985 d = new(Dll) 986 d.name = s.Dynimplib 987 d.next = dr 988 dr = d 989 m = new(Imp) 990 } 991 992 // Because external link requires properly stdcall decorated name, 993 // all external symbols in runtime use %n to denote that the number 994 // of uinptrs this function consumes. Store the argsize and discard 995 // the %n suffix if any. 996 m.argsize = -1 997 if i := strings.IndexByte(s.Extname, '%'); i >= 0 { 998 var err error 999 m.argsize, err = strconv.Atoi(s.Extname[i+1:]) 1000 if err != nil { 1001 Errorf(s, "failed to parse stdcall decoration: %v", err) 1002 } 1003 m.argsize *= ctxt.Arch.PtrSize 1004 s.Extname = s.Extname[:i] 1005 } 1006 1007 m.s = s 1008 m.next = d.ms 1009 d.ms = m 1010 } 1011 1012 if ctxt.LinkMode == LinkExternal { 1013 // Add real symbol name 1014 for d := dr; d != nil; d = d.next { 1015 for m = d.ms; m != nil; m = m.next { 1016 m.s.Type = sym.SDATA 1017 m.s.Grow(int64(ctxt.Arch.PtrSize)) 1018 dynName := m.s.Extname 1019 // only windows/386 requires stdcall decoration 1020 if ctxt.Arch.Family == sys.I386 && m.argsize >= 0 { 1021 dynName += fmt.Sprintf("@%d", m.argsize) 1022 } 1023 dynSym := ctxt.Syms.Lookup(dynName, 0) 1024 dynSym.Attr |= sym.AttrReachable 1025 dynSym.Type = sym.SHOSTOBJ 1026 r := m.s.AddRel() 1027 r.Sym = dynSym 1028 r.Off = 0 1029 r.Siz = uint8(ctxt.Arch.PtrSize) 1030 r.Type = objabi.R_ADDR 1031 } 1032 } 1033 } else { 1034 dynamic := ctxt.Syms.Lookup(".windynamic", 0) 1035 dynamic.Attr |= sym.AttrReachable 1036 dynamic.Type = sym.SWINDOWS 1037 for d := dr; d != nil; d = d.next { 1038 for m = d.ms; m != nil; m = m.next { 1039 m.s.Type = sym.SWINDOWS 1040 m.s.Attr |= sym.AttrSubSymbol 1041 m.s.Sub = dynamic.Sub 1042 dynamic.Sub = m.s 1043 m.s.Value = dynamic.Size 1044 dynamic.Size += int64(ctxt.Arch.PtrSize) 1045 } 1046 1047 dynamic.Size += int64(ctxt.Arch.PtrSize) 1048 } 1049 } 1050 1051 return dr 1052 } 1053 1054 // peimporteddlls returns the gcc command line argument to link all imported 1055 // DLLs. 1056 func peimporteddlls() []string { 1057 var dlls []string 1058 1059 for d := dr; d != nil; d = d.next { 1060 dlls = append(dlls, "-l"+strings.TrimSuffix(d.name, ".dll")) 1061 } 1062 1063 return dlls 1064 } 1065 1066 func addimports(ctxt *Link, datsect *peSection) { 1067 startoff := ctxt.Out.Offset() 1068 dynamic := ctxt.Syms.Lookup(".windynamic", 0) 1069 1070 // skip import descriptor table (will write it later) 1071 n := uint64(0) 1072 1073 for d := dr; d != nil; d = d.next { 1074 n++ 1075 } 1076 ctxt.Out.SeekSet(startoff + int64(binary.Size(&IMAGE_IMPORT_DESCRIPTOR{}))*int64(n+1)) 1077 1078 // write dll names 1079 for d := dr; d != nil; d = d.next { 1080 d.nameoff = uint64(ctxt.Out.Offset()) - uint64(startoff) 1081 strput(ctxt.Out, d.name) 1082 } 1083 1084 // write function names 1085 var m *Imp 1086 for d := dr; d != nil; d = d.next { 1087 for m = d.ms; m != nil; m = m.next { 1088 m.off = uint64(pefile.nextSectOffset) + uint64(ctxt.Out.Offset()) - uint64(startoff) 1089 ctxt.Out.Write16(0) // hint 1090 strput(ctxt.Out, m.s.Extname) 1091 } 1092 } 1093 1094 // write OriginalFirstThunks 1095 oftbase := uint64(ctxt.Out.Offset()) - uint64(startoff) 1096 1097 n = uint64(ctxt.Out.Offset()) 1098 for d := dr; d != nil; d = d.next { 1099 d.thunkoff = uint64(ctxt.Out.Offset()) - n 1100 for m = d.ms; m != nil; m = m.next { 1101 if pe64 != 0 { 1102 ctxt.Out.Write64(m.off) 1103 } else { 1104 ctxt.Out.Write32(uint32(m.off)) 1105 } 1106 } 1107 1108 if pe64 != 0 { 1109 ctxt.Out.Write64(0) 1110 } else { 1111 ctxt.Out.Write32(0) 1112 } 1113 } 1114 1115 // add pe section and pad it at the end 1116 n = uint64(ctxt.Out.Offset()) - uint64(startoff) 1117 1118 isect := pefile.addSection(".idata", int(n), int(n)) 1119 isect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE 1120 isect.checkOffset(startoff) 1121 isect.pad(ctxt.Out, uint32(n)) 1122 endoff := ctxt.Out.Offset() 1123 1124 // write FirstThunks (allocated in .data section) 1125 ftbase := uint64(dynamic.Value) - uint64(datsect.virtualAddress) - PEBASE 1126 1127 ctxt.Out.SeekSet(int64(uint64(datsect.pointerToRawData) + ftbase)) 1128 for d := dr; d != nil; d = d.next { 1129 for m = d.ms; m != nil; m = m.next { 1130 if pe64 != 0 { 1131 ctxt.Out.Write64(m.off) 1132 } else { 1133 ctxt.Out.Write32(uint32(m.off)) 1134 } 1135 } 1136 1137 if pe64 != 0 { 1138 ctxt.Out.Write64(0) 1139 } else { 1140 ctxt.Out.Write32(0) 1141 } 1142 } 1143 1144 // finally write import descriptor table 1145 out := ctxt.Out 1146 out.SeekSet(startoff) 1147 1148 for d := dr; d != nil; d = d.next { 1149 out.Write32(uint32(uint64(isect.virtualAddress) + oftbase + d.thunkoff)) 1150 out.Write32(0) 1151 out.Write32(0) 1152 out.Write32(uint32(uint64(isect.virtualAddress) + d.nameoff)) 1153 out.Write32(uint32(uint64(datsect.virtualAddress) + ftbase + d.thunkoff)) 1154 } 1155 1156 out.Write32(0) //end 1157 out.Write32(0) 1158 out.Write32(0) 1159 out.Write32(0) 1160 out.Write32(0) 1161 1162 // update data directory 1163 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect.virtualAddress 1164 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect.virtualSize 1165 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = uint32(dynamic.Value - PEBASE) 1166 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_IAT].Size = uint32(dynamic.Size) 1167 1168 out.SeekSet(endoff) 1169 } 1170 1171 type byExtname []*sym.Symbol 1172 1173 func (s byExtname) Len() int { return len(s) } 1174 func (s byExtname) Swap(i, j int) { s[i], s[j] = s[j], s[i] } 1175 func (s byExtname) Less(i, j int) bool { return s[i].Extname < s[j].Extname } 1176 1177 func initdynexport(ctxt *Link) { 1178 nexport = 0 1179 for _, s := range ctxt.Syms.Allsym { 1180 if !s.Attr.Reachable() || !s.Attr.CgoExportDynamic() { 1181 continue 1182 } 1183 if nexport+1 > len(dexport) { 1184 Errorf(s, "pe dynexport table is full") 1185 errorexit() 1186 } 1187 1188 dexport[nexport] = s 1189 nexport++ 1190 } 1191 1192 sort.Sort(byExtname(dexport[:nexport])) 1193 } 1194 1195 func addexports(ctxt *Link) { 1196 var e IMAGE_EXPORT_DIRECTORY 1197 1198 size := binary.Size(&e) + 10*nexport + len(*flagOutfile) + 1 1199 for i := 0; i < nexport; i++ { 1200 size += len(dexport[i].Extname) + 1 1201 } 1202 1203 if nexport == 0 { 1204 return 1205 } 1206 1207 sect := pefile.addSection(".edata", size, size) 1208 sect.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ 1209 sect.checkOffset(ctxt.Out.Offset()) 1210 va := int(sect.virtualAddress) 1211 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = uint32(va) 1212 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect.virtualSize 1213 1214 vaName := va + binary.Size(&e) + nexport*4 1215 vaAddr := va + binary.Size(&e) 1216 vaNa := va + binary.Size(&e) + nexport*8 1217 1218 e.Characteristics = 0 1219 e.MajorVersion = 0 1220 e.MinorVersion = 0 1221 e.NumberOfFunctions = uint32(nexport) 1222 e.NumberOfNames = uint32(nexport) 1223 e.Name = uint32(va+binary.Size(&e)) + uint32(nexport)*10 // Program names. 1224 e.Base = 1 1225 e.AddressOfFunctions = uint32(vaAddr) 1226 e.AddressOfNames = uint32(vaName) 1227 e.AddressOfNameOrdinals = uint32(vaNa) 1228 1229 out := ctxt.Out 1230 1231 // put IMAGE_EXPORT_DIRECTORY 1232 binary.Write(out, binary.LittleEndian, &e) 1233 1234 // put EXPORT Address Table 1235 for i := 0; i < nexport; i++ { 1236 out.Write32(uint32(dexport[i].Value - PEBASE)) 1237 } 1238 1239 // put EXPORT Name Pointer Table 1240 v := int(e.Name + uint32(len(*flagOutfile)) + 1) 1241 1242 for i := 0; i < nexport; i++ { 1243 out.Write32(uint32(v)) 1244 v += len(dexport[i].Extname) + 1 1245 } 1246 1247 // put EXPORT Ordinal Table 1248 for i := 0; i < nexport; i++ { 1249 out.Write16(uint16(i)) 1250 } 1251 1252 // put Names 1253 out.WriteStringN(*flagOutfile, len(*flagOutfile)+1) 1254 1255 for i := 0; i < nexport; i++ { 1256 out.WriteStringN(dexport[i].Extname, len(dexport[i].Extname)+1) 1257 } 1258 sect.pad(out, uint32(size)) 1259 } 1260 1261 func (ctxt *Link) dope() { 1262 /* relocation table */ 1263 rel := ctxt.Syms.Lookup(".rel", 0) 1264 1265 rel.Attr |= sym.AttrReachable 1266 rel.Type = sym.SELFROSECT 1267 1268 initdynimport(ctxt) 1269 initdynexport(ctxt) 1270 } 1271 1272 func setpersrc(ctxt *Link, sym *sym.Symbol) { 1273 if rsrcsym != nil { 1274 Errorf(sym, "too many .rsrc sections") 1275 } 1276 1277 rsrcsym = sym 1278 } 1279 1280 func addpersrc(ctxt *Link) { 1281 if rsrcsym == nil { 1282 return 1283 } 1284 1285 h := pefile.addSection(".rsrc", int(rsrcsym.Size), int(rsrcsym.Size)) 1286 h.characteristics = IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA 1287 h.checkOffset(ctxt.Out.Offset()) 1288 1289 // relocation 1290 var p []byte 1291 var r *sym.Reloc 1292 var val uint32 1293 for ri := 0; ri < len(rsrcsym.R); ri++ { 1294 r = &rsrcsym.R[ri] 1295 p = rsrcsym.P[r.Off:] 1296 val = uint32(int64(h.virtualAddress) + r.Add) 1297 1298 // 32-bit little-endian 1299 p[0] = byte(val) 1300 1301 p[1] = byte(val >> 8) 1302 p[2] = byte(val >> 16) 1303 p[3] = byte(val >> 24) 1304 } 1305 1306 ctxt.Out.Write(rsrcsym.P) 1307 h.pad(ctxt.Out, uint32(rsrcsym.Size)) 1308 1309 // update data directory 1310 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h.virtualAddress 1311 1312 pefile.dataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h.virtualSize 1313 } 1314 1315 func Asmbpe(ctxt *Link) { 1316 switch ctxt.Arch.Family { 1317 default: 1318 Exitf("unknown PE architecture: %v", ctxt.Arch.Family) 1319 case sys.AMD64, sys.I386: 1320 } 1321 1322 t := pefile.addSection(".text", int(Segtext.Length), int(Segtext.Length)) 1323 t.characteristics = IMAGE_SCN_CNT_CODE | IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ 1324 if ctxt.LinkMode == LinkExternal { 1325 // some data symbols (e.g. masks) end up in the .text section, and they normally 1326 // expect larger alignment requirement than the default text section alignment. 1327 t.characteristics |= IMAGE_SCN_ALIGN_32BYTES 1328 } 1329 t.checkSegment(&Segtext) 1330 pefile.textSect = t 1331 1332 var d *peSection 1333 if ctxt.LinkMode != LinkExternal { 1334 d = pefile.addSection(".data", int(Segdata.Length), int(Segdata.Filelen)) 1335 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE 1336 d.checkSegment(&Segdata) 1337 pefile.dataSect = d 1338 } else { 1339 d = pefile.addSection(".data", int(Segdata.Filelen), int(Segdata.Filelen)) 1340 d.characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES 1341 d.checkSegment(&Segdata) 1342 pefile.dataSect = d 1343 1344 b := pefile.addSection(".bss", int(Segdata.Length-Segdata.Filelen), 0) 1345 b.characteristics = IMAGE_SCN_CNT_UNINITIALIZED_DATA | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE | IMAGE_SCN_ALIGN_32BYTES 1346 b.pointerToRawData = 0 1347 pefile.bssSect = b 1348 } 1349 1350 pefile.addDWARF() 1351 1352 if ctxt.LinkMode == LinkExternal { 1353 pefile.ctorsSect = pefile.addInitArray(ctxt) 1354 } 1355 1356 ctxt.Out.SeekSet(int64(pefile.nextFileOffset)) 1357 if ctxt.LinkMode != LinkExternal { 1358 addimports(ctxt, d) 1359 addexports(ctxt) 1360 } 1361 pefile.writeSymbolTableAndStringTable(ctxt) 1362 addpersrc(ctxt) 1363 if ctxt.LinkMode == LinkExternal { 1364 pefile.emitRelocations(ctxt) 1365 } 1366 1367 pewrite(ctxt) 1368 }