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