github.com/razvanm/vanadium-go-1.3@v0.0.0-20160721203343-4a65068e5915/src/cmd/ld/pe.c (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 // PE (Portable Executable) file writing 6 // http://www.microsoft.com/whdc/system/platform/firmware/PECOFF.mspx 7 8 #include "l.h" 9 #include "../ld/lib.h" 10 #include "../ld/pe.h" 11 #include "../ld/dwarf.h" 12 13 // DOS stub that prints out 14 // "This program cannot be run in DOS mode." 15 static char dosstub[] = 16 { 17 0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x04, 0x00, 18 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 19 0x8b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 20 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 21 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 22 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 23 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 24 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 25 0x0e, 0x1f, 0xba, 0x0e, 0x00, 0xb4, 0x09, 0xcd, 26 0x21, 0xb8, 0x01, 0x4c, 0xcd, 0x21, 0x54, 0x68, 27 0x69, 0x73, 0x20, 0x70, 0x72, 0x6f, 0x67, 0x72, 28 0x61, 0x6d, 0x20, 0x63, 0x61, 0x6e, 0x6e, 0x6f, 29 0x74, 0x20, 0x62, 0x65, 0x20, 0x72, 0x75, 0x6e, 30 0x20, 0x69, 0x6e, 0x20, 0x44, 0x4f, 0x53, 0x20, 31 0x6d, 0x6f, 0x64, 0x65, 0x2e, 0x0d, 0x0d, 0x0a, 32 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 33 }; 34 35 static LSym *rsrcsym; 36 37 static char* strtbl; 38 static int strtblnextoff; 39 static int strtblsize; 40 41 int32 PESECTHEADR; 42 int32 PEFILEHEADR; 43 44 static int pe64; 45 static int nsect; 46 static int nextsectoff; 47 static int nextfileoff; 48 static int textsect; 49 static int datasect; 50 51 static IMAGE_FILE_HEADER fh; 52 static IMAGE_OPTIONAL_HEADER oh; 53 static PE64_IMAGE_OPTIONAL_HEADER oh64; 54 static IMAGE_SECTION_HEADER sh[16]; 55 static IMAGE_DATA_DIRECTORY* dd; 56 57 #define set(n, v) (pe64 ? (oh64.n = v) : (oh.n = v)) 58 #define put(v) (pe64 ? vputl(v) : lputl(v)) 59 60 typedef struct Imp Imp; 61 struct Imp { 62 LSym* s; 63 uvlong off; 64 Imp* next; 65 }; 66 67 typedef struct Dll Dll; 68 struct Dll { 69 char* name; 70 uvlong nameoff; 71 uvlong thunkoff; 72 Imp* ms; 73 Dll* next; 74 }; 75 76 static Dll* dr; 77 78 static LSym *dexport[1024]; 79 static int nexport; 80 81 typedef struct COFFSym COFFSym; 82 struct COFFSym 83 { 84 LSym* sym; 85 int strtbloff; 86 int sect; 87 vlong value; 88 }; 89 90 static COFFSym* coffsym; 91 static int ncoffsym; 92 93 static IMAGE_SECTION_HEADER* 94 addpesection(char *name, int sectsize, int filesize) 95 { 96 IMAGE_SECTION_HEADER *h; 97 98 if(nsect == 16) { 99 diag("too many sections"); 100 errorexit(); 101 } 102 h = &sh[nsect++]; 103 strncpy((char*)h->Name, name, sizeof(h->Name)); 104 h->VirtualSize = sectsize; 105 h->VirtualAddress = nextsectoff; 106 nextsectoff = rnd(nextsectoff+sectsize, PESECTALIGN); 107 h->PointerToRawData = nextfileoff; 108 if(filesize > 0) { 109 h->SizeOfRawData = rnd(filesize, PEFILEALIGN); 110 nextfileoff += h->SizeOfRawData; 111 } 112 return h; 113 } 114 115 static void 116 chksectoff(IMAGE_SECTION_HEADER *h, vlong off) 117 { 118 if(off != h->PointerToRawData) { 119 diag("%s.PointerToRawData = %#llux, want %#llux", (char *)h->Name, (vlong)h->PointerToRawData, off); 120 errorexit(); 121 } 122 } 123 124 static void 125 chksectseg(IMAGE_SECTION_HEADER *h, Segment *s) 126 { 127 if(s->vaddr-PEBASE != h->VirtualAddress) { 128 diag("%s.VirtualAddress = %#llux, want %#llux", (char *)h->Name, (vlong)h->VirtualAddress, (vlong)(s->vaddr-PEBASE)); 129 errorexit(); 130 } 131 if(s->fileoff != h->PointerToRawData) { 132 diag("%s.PointerToRawData = %#llux, want %#llux", (char *)h->Name, (vlong)h->PointerToRawData, (vlong)(s->fileoff)); 133 errorexit(); 134 } 135 } 136 137 void 138 peinit(void) 139 { 140 int32 l; 141 142 switch(thechar) { 143 // 64-bit architectures 144 case '6': 145 pe64 = 1; 146 l = sizeof(oh64); 147 dd = oh64.DataDirectory; 148 break; 149 // 32-bit architectures 150 default: 151 l = sizeof(oh); 152 dd = oh.DataDirectory; 153 break; 154 } 155 156 PEFILEHEADR = rnd(sizeof(dosstub)+sizeof(fh)+l+sizeof(sh), PEFILEALIGN); 157 PESECTHEADR = rnd(PEFILEHEADR, PESECTALIGN); 158 nextsectoff = PESECTHEADR; 159 nextfileoff = PEFILEHEADR; 160 161 // some mingw libs depend on this symbol, for example, FindPESectionByName 162 xdefine("__image_base__", SDATA, PEBASE); 163 xdefine("_image_base__", SDATA, PEBASE); 164 } 165 166 static void 167 pewrite(void) 168 { 169 cseek(0); 170 cwrite(dosstub, sizeof dosstub); 171 strnput("PE", 4); 172 // TODO: This code should not assume that the 173 // memory representation is little-endian or 174 // that the structs are packed identically to 175 // their file representation. 176 cwrite(&fh, sizeof fh); 177 if(pe64) 178 cwrite(&oh64, sizeof oh64); 179 else 180 cwrite(&oh, sizeof oh); 181 cwrite(sh, nsect * sizeof sh[0]); 182 } 183 184 static void 185 strput(char *s) 186 { 187 int n; 188 189 for(n=0; *s; n++) 190 cput(*s++); 191 cput('\0'); 192 n++; 193 // string must be padded to even size 194 if(n%2) 195 cput('\0'); 196 } 197 198 static Dll* 199 initdynimport(void) 200 { 201 Imp *m; 202 Dll *d; 203 LSym *s, *dynamic; 204 205 dr = nil; 206 m = nil; 207 for(s = ctxt->allsym; s != S; s = s->allsym) { 208 if(!s->reachable || s->type != SDYNIMPORT) 209 continue; 210 for(d = dr; d != nil; d = d->next) { 211 if(strcmp(d->name,s->dynimplib) == 0) { 212 m = mal(sizeof *m); 213 break; 214 } 215 } 216 if(d == nil) { 217 d = mal(sizeof *d); 218 d->name = s->dynimplib; 219 d->next = dr; 220 dr = d; 221 m = mal(sizeof *m); 222 } 223 m->s = s; 224 m->next = d->ms; 225 d->ms = m; 226 } 227 228 dynamic = linklookup(ctxt, ".windynamic", 0); 229 dynamic->reachable = 1; 230 dynamic->type = SWINDOWS; 231 for(d = dr; d != nil; d = d->next) { 232 for(m = d->ms; m != nil; m = m->next) { 233 m->s->type = SWINDOWS | SSUB; 234 m->s->sub = dynamic->sub; 235 dynamic->sub = m->s; 236 m->s->value = dynamic->size; 237 dynamic->size += PtrSize; 238 } 239 dynamic->size += PtrSize; 240 } 241 242 return dr; 243 } 244 245 static void 246 addimports(IMAGE_SECTION_HEADER *datsect) 247 { 248 IMAGE_SECTION_HEADER *isect; 249 uvlong n, oftbase, ftbase; 250 vlong startoff, endoff; 251 Imp *m; 252 Dll *d; 253 LSym* dynamic; 254 255 startoff = cpos(); 256 dynamic = linklookup(ctxt, ".windynamic", 0); 257 258 // skip import descriptor table (will write it later) 259 n = 0; 260 for(d = dr; d != nil; d = d->next) 261 n++; 262 cseek(startoff + sizeof(IMAGE_IMPORT_DESCRIPTOR) * (n + 1)); 263 264 // write dll names 265 for(d = dr; d != nil; d = d->next) { 266 d->nameoff = cpos() - startoff; 267 strput(d->name); 268 } 269 270 // write function names 271 for(d = dr; d != nil; d = d->next) { 272 for(m = d->ms; m != nil; m = m->next) { 273 m->off = nextsectoff + cpos() - startoff; 274 wputl(0); // hint 275 strput(m->s->extname); 276 } 277 } 278 279 // write OriginalFirstThunks 280 oftbase = cpos() - startoff; 281 n = cpos(); 282 for(d = dr; d != nil; d = d->next) { 283 d->thunkoff = cpos() - n; 284 for(m = d->ms; m != nil; m = m->next) 285 put(m->off); 286 put(0); 287 } 288 289 // add pe section and pad it at the end 290 n = cpos() - startoff; 291 isect = addpesection(".idata", n, n); 292 isect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| 293 IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; 294 chksectoff(isect, startoff); 295 strnput("", isect->SizeOfRawData - n); 296 endoff = cpos(); 297 298 // write FirstThunks (allocated in .data section) 299 ftbase = dynamic->value - datsect->VirtualAddress - PEBASE; 300 cseek(datsect->PointerToRawData + ftbase); 301 for(d = dr; d != nil; d = d->next) { 302 for(m = d->ms; m != nil; m = m->next) 303 put(m->off); 304 put(0); 305 } 306 307 // finally write import descriptor table 308 cseek(startoff); 309 for(d = dr; d != nil; d = d->next) { 310 lputl(isect->VirtualAddress + oftbase + d->thunkoff); 311 lputl(0); 312 lputl(0); 313 lputl(isect->VirtualAddress + d->nameoff); 314 lputl(datsect->VirtualAddress + ftbase + d->thunkoff); 315 } 316 lputl(0); //end 317 lputl(0); 318 lputl(0); 319 lputl(0); 320 lputl(0); 321 322 // update data directory 323 dd[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress = isect->VirtualAddress; 324 dd[IMAGE_DIRECTORY_ENTRY_IMPORT].Size = isect->VirtualSize; 325 dd[IMAGE_DIRECTORY_ENTRY_IAT].VirtualAddress = dynamic->value - PEBASE; 326 dd[IMAGE_DIRECTORY_ENTRY_IAT].Size = dynamic->size; 327 328 cseek(endoff); 329 } 330 331 static int 332 scmp(const void *p1, const void *p2) 333 { 334 LSym *s1, *s2; 335 336 s1 = *(LSym**)p1; 337 s2 = *(LSym**)p2; 338 return strcmp(s1->extname, s2->extname); 339 } 340 341 static void 342 initdynexport(void) 343 { 344 LSym *s; 345 346 nexport = 0; 347 for(s = ctxt->allsym; s != S; s = s->allsym) { 348 if(!s->reachable || !(s->cgoexport & CgoExportDynamic)) 349 continue; 350 if(nexport+1 > sizeof(dexport)/sizeof(dexport[0])) { 351 diag("pe dynexport table is full"); 352 errorexit(); 353 } 354 355 dexport[nexport] = s; 356 nexport++; 357 } 358 359 qsort(dexport, nexport, sizeof dexport[0], scmp); 360 } 361 362 void 363 addexports(void) 364 { 365 IMAGE_SECTION_HEADER *sect; 366 IMAGE_EXPORT_DIRECTORY e; 367 int size, i, va, va_name, va_addr, va_na, v; 368 369 size = sizeof e + 10*nexport + strlen(outfile) + 1; 370 for(i=0; i<nexport; i++) 371 size += strlen(dexport[i]->extname) + 1; 372 373 if (nexport == 0) 374 return; 375 376 sect = addpesection(".edata", size, size); 377 sect->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA|IMAGE_SCN_MEM_READ; 378 chksectoff(sect, cpos()); 379 va = sect->VirtualAddress; 380 dd[IMAGE_DIRECTORY_ENTRY_EXPORT].VirtualAddress = va; 381 dd[IMAGE_DIRECTORY_ENTRY_EXPORT].Size = sect->VirtualSize; 382 383 va_name = va + sizeof e + nexport*4; 384 va_addr = va + sizeof e; 385 va_na = va + sizeof e + nexport*8; 386 387 e.Characteristics = 0; 388 e.MajorVersion = 0; 389 e.MinorVersion = 0; 390 e.NumberOfFunctions = nexport; 391 e.NumberOfNames = nexport; 392 e.Name = va + sizeof e + nexport*10; // Program names. 393 e.Base = 1; 394 e.AddressOfFunctions = va_addr; 395 e.AddressOfNames = va_name; 396 e.AddressOfNameOrdinals = va_na; 397 // put IMAGE_EXPORT_DIRECTORY 398 for (i=0; i<sizeof(e); i++) 399 cput(((char*)&e)[i]); 400 // put EXPORT Address Table 401 for(i=0; i<nexport; i++) 402 lputl(dexport[i]->value - PEBASE); 403 // put EXPORT Name Pointer Table 404 v = e.Name + strlen(outfile)+1; 405 for(i=0; i<nexport; i++) { 406 lputl(v); 407 v += strlen(dexport[i]->extname)+1; 408 } 409 // put EXPORT Ordinal Table 410 for(i=0; i<nexport; i++) 411 wputl(i); 412 // put Names 413 strnput(outfile, strlen(outfile)+1); 414 for(i=0; i<nexport; i++) 415 strnput(dexport[i]->extname, strlen(dexport[i]->extname)+1); 416 strnput("", sect->SizeOfRawData - size); 417 } 418 419 void 420 dope(void) 421 { 422 LSym *rel; 423 424 /* relocation table */ 425 rel = linklookup(ctxt, ".rel", 0); 426 rel->reachable = 1; 427 rel->type = SELFROSECT; 428 429 initdynimport(); 430 initdynexport(); 431 } 432 433 static int 434 strtbladd(char *name) 435 { 436 int newsize, thisoff; 437 438 newsize = strtblnextoff + strlen(name) + 1; 439 if(newsize > strtblsize) { 440 strtblsize = 2 * (newsize + (1<<18)); 441 strtbl = realloc(strtbl, strtblsize); 442 } 443 thisoff = strtblnextoff+4; // first string starts at offset=4 444 strcpy(&strtbl[strtblnextoff], name); 445 strtblnextoff += strlen(name); 446 strtbl[strtblnextoff] = 0; 447 strtblnextoff++; 448 return thisoff; 449 } 450 451 /* 452 * For more than 8 characters section names, name contains a slash (/) that is 453 * followed by an ASCII representation of a decimal number that is an offset into 454 * the string table. 455 * reference: pecoff_v8.docx Page 24. 456 * <http://www.microsoft.com/whdc/system/platform/firmware/PECOFFdwn.mspx> 457 */ 458 IMAGE_SECTION_HEADER* 459 newPEDWARFSection(char *name, vlong size) 460 { 461 IMAGE_SECTION_HEADER *h; 462 char s[8]; 463 int off; 464 465 if(size == 0) 466 return nil; 467 468 off = strtbladd(name); 469 sprint(s, "/%d\0", off); 470 h = addpesection(s, size, size); 471 h->Characteristics = IMAGE_SCN_MEM_READ| 472 IMAGE_SCN_MEM_DISCARDABLE; 473 474 return h; 475 } 476 477 static void 478 addsym(LSym *s, char *name, int type, vlong addr, vlong size, int ver, LSym *gotype) 479 { 480 COFFSym *cs; 481 USED(name); 482 USED(addr); 483 USED(size); 484 USED(ver); 485 USED(gotype); 486 487 if(s == nil) 488 return; 489 490 if(s->sect == nil) 491 return; 492 493 switch(type) { 494 default: 495 return; 496 case 'D': 497 case 'B': 498 case 'T': 499 break; 500 } 501 502 if(coffsym) { 503 cs = &coffsym[ncoffsym]; 504 cs->sym = s; 505 if(strlen(s->name) > 8) 506 cs->strtbloff = strtbladd(s->name); 507 if(s->value >= segdata.vaddr) { 508 cs->value = s->value - segdata.vaddr; 509 cs->sect = datasect; 510 } else if(s->value >= segtext.vaddr) { 511 cs->value = s->value - segtext.vaddr; 512 cs->sect = textsect; 513 } else { 514 cs->value = 0; 515 cs->sect = 0; 516 diag("addsym %#llx", addr); 517 } 518 } 519 ncoffsym++; 520 } 521 522 static void 523 addsymtable(void) 524 { 525 IMAGE_SECTION_HEADER *h; 526 int i, size; 527 COFFSym *s; 528 529 if(!debug['s']) { 530 genasmsym(addsym); 531 coffsym = mal(ncoffsym * sizeof coffsym[0]); 532 ncoffsym = 0; 533 genasmsym(addsym); 534 } 535 536 size = strtblnextoff + 4 + 18*ncoffsym; 537 h = addpesection(".symtab", size, size); 538 h->Characteristics = IMAGE_SCN_MEM_READ| 539 IMAGE_SCN_MEM_DISCARDABLE; 540 chksectoff(h, cpos()); 541 fh.PointerToSymbolTable = cpos(); 542 fh.NumberOfSymbols = ncoffsym; 543 544 // put COFF symbol table 545 for (i=0; i<ncoffsym; i++) { 546 s = &coffsym[i]; 547 if(s->strtbloff == 0) 548 strnput(s->sym->name, 8); 549 else { 550 lputl(0); 551 lputl(s->strtbloff); 552 } 553 lputl(s->value); 554 wputl(s->sect); 555 wputl(0x0308); // "array of structs" 556 cput(2); // storage class: external 557 cput(0); // no aux entries 558 } 559 560 // put COFF string table 561 lputl(strtblnextoff + 4); 562 for (i=0; i<strtblnextoff; i++) 563 cput(strtbl[i]); 564 strnput("", h->SizeOfRawData - size); 565 } 566 567 void 568 setpersrc(LSym *sym) 569 { 570 if(rsrcsym != nil) 571 diag("too many .rsrc sections"); 572 573 rsrcsym = sym; 574 } 575 576 void 577 addpersrc(void) 578 { 579 IMAGE_SECTION_HEADER *h; 580 uchar *p; 581 uint32 val; 582 Reloc *r; 583 584 if(rsrcsym == nil) 585 return; 586 587 h = addpesection(".rsrc", rsrcsym->size, rsrcsym->size); 588 h->Characteristics = IMAGE_SCN_MEM_READ| 589 IMAGE_SCN_MEM_WRITE | IMAGE_SCN_CNT_INITIALIZED_DATA; 590 chksectoff(h, cpos()); 591 // relocation 592 for(r=rsrcsym->r; r<rsrcsym->r+rsrcsym->nr; r++) { 593 p = rsrcsym->p + r->off; 594 val = h->VirtualAddress + r->add; 595 // 32-bit little-endian 596 p[0] = val; 597 p[1] = val>>8; 598 p[2] = val>>16; 599 p[3] = val>>24; 600 } 601 cwrite(rsrcsym->p, rsrcsym->size); 602 strnput("", h->SizeOfRawData - rsrcsym->size); 603 604 // update data directory 605 dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].VirtualAddress = h->VirtualAddress; 606 dd[IMAGE_DIRECTORY_ENTRY_RESOURCE].Size = h->VirtualSize; 607 } 608 609 void 610 asmbpe(void) 611 { 612 IMAGE_SECTION_HEADER *t, *d; 613 614 switch(thechar) { 615 default: 616 diag("unknown PE architecture"); 617 errorexit(); 618 case '6': 619 fh.Machine = IMAGE_FILE_MACHINE_AMD64; 620 break; 621 case '8': 622 fh.Machine = IMAGE_FILE_MACHINE_I386; 623 break; 624 } 625 626 t = addpesection(".text", segtext.len, segtext.len); 627 t->Characteristics = IMAGE_SCN_CNT_CODE| 628 IMAGE_SCN_CNT_INITIALIZED_DATA| 629 IMAGE_SCN_MEM_EXECUTE|IMAGE_SCN_MEM_READ; 630 chksectseg(t, &segtext); 631 textsect = nsect; 632 633 d = addpesection(".data", segdata.len, segdata.filelen); 634 d->Characteristics = IMAGE_SCN_CNT_INITIALIZED_DATA| 635 IMAGE_SCN_MEM_READ|IMAGE_SCN_MEM_WRITE; 636 chksectseg(d, &segdata); 637 datasect = nsect; 638 639 if(!debug['s']) 640 dwarfaddpeheaders(); 641 642 cseek(nextfileoff); 643 addimports(d); 644 addexports(); 645 addsymtable(); 646 addpersrc(); 647 648 fh.NumberOfSections = nsect; 649 fh.TimeDateStamp = time(0); 650 fh.Characteristics = IMAGE_FILE_RELOCS_STRIPPED| 651 IMAGE_FILE_EXECUTABLE_IMAGE|IMAGE_FILE_DEBUG_STRIPPED; 652 if (pe64) { 653 fh.SizeOfOptionalHeader = sizeof(oh64); 654 fh.Characteristics |= IMAGE_FILE_LARGE_ADDRESS_AWARE; 655 set(Magic, 0x20b); // PE32+ 656 } else { 657 fh.SizeOfOptionalHeader = sizeof(oh); 658 fh.Characteristics |= IMAGE_FILE_32BIT_MACHINE; 659 set(Magic, 0x10b); // PE32 660 oh.BaseOfData = d->VirtualAddress; 661 } 662 set(MajorLinkerVersion, 3); 663 set(MinorLinkerVersion, 0); 664 set(SizeOfCode, t->SizeOfRawData); 665 set(SizeOfInitializedData, d->SizeOfRawData); 666 set(SizeOfUninitializedData, 0); 667 set(AddressOfEntryPoint, entryvalue()-PEBASE); 668 set(BaseOfCode, t->VirtualAddress); 669 set(ImageBase, PEBASE); 670 set(SectionAlignment, PESECTALIGN); 671 set(FileAlignment, PEFILEALIGN); 672 set(MajorOperatingSystemVersion, 4); 673 set(MinorOperatingSystemVersion, 0); 674 set(MajorImageVersion, 1); 675 set(MinorImageVersion, 0); 676 set(MajorSubsystemVersion, 4); 677 set(MinorSubsystemVersion, 0); 678 set(SizeOfImage, nextsectoff); 679 set(SizeOfHeaders, PEFILEHEADR); 680 if(strcmp(headstring, "windowsgui") == 0) 681 set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_GUI); 682 else 683 set(Subsystem, IMAGE_SUBSYSTEM_WINDOWS_CUI); 684 685 // Disable stack growth as we don't want Windows to 686 // fiddle with the thread stack limits, which we set 687 // ourselves to circumvent the stack checks in the 688 // Windows exception dispatcher. 689 // Commit size must be strictly less than reserve 690 // size otherwise reserve will be rounded up to a 691 // larger size, as verified with VMMap. 692 693 // Go code would be OK with 64k stacks, but we need larger stacks for cgo. 694 // That default stack reserve size affects only the main thread, 695 // for other threads we specify stack size in runtime explicitly 696 // (runtime knows whether cgo is enabled or not). 697 // If you change stack reserve sizes here, 698 // change STACKSIZE in runtime/cgo/gcc_windows_{386,amd64}.c as well. 699 if(!iscgo) { 700 set(SizeOfStackReserve, 0x00010000); 701 set(SizeOfStackCommit, 0x0000ffff); 702 } else { 703 set(SizeOfStackReserve, pe64 ? 0x00200000 : 0x00100000); 704 // account for 2 guard pages 705 set(SizeOfStackCommit, (pe64 ? 0x00200000 : 0x00100000) - 0x2000); 706 } 707 set(SizeOfHeapReserve, 0x00100000); 708 set(SizeOfHeapCommit, 0x00001000); 709 set(NumberOfRvaAndSizes, 16); 710 711 pewrite(); 712 }