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