Changeset 1811 for trunk/src/kernel32/winimagepeldr.cpp
- Timestamp:
- Nov 22, 1999, 9:35:52 PM (26 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/winimagepeldr.cpp
r1720 r1811 1 /* $Id: winimagepeldr.cpp,v 1.1 3 1999-11-13 15:41:11sandervl Exp $ */1 /* $Id: winimagepeldr.cpp,v 1.14 1999-11-22 20:35:52 sandervl Exp $ */ 2 2 3 3 /* … … 45 45 #include <win\virtual.h> 46 46 #include "oslibdos.h" 47 #include "mmap.h" 47 48 48 49 char szErrorTitle[] = "Odin"; … … 74 75 imageVirtBase(-1), realBaseAddress(0), imageVirtEnd(0), 75 76 nrNameExports(0), nrOrdExports(0), nameexports(NULL), ordexports(NULL), 76 fImgMapping(0)77 memmap(NULL), pFixups(NULL) 77 78 { 78 79 HFILE dllfile; … … 120 121 Win32PeLdrImage::~Win32PeLdrImage() 121 122 { 123 if(memmap) 124 delete memmap; 125 126 if(hFile) { 127 OSLibDosClose(hFile); 128 hFile = 0; 129 } 130 122 131 if(realBaseAddress) 123 132 DosFreeMem((PVOID)realBaseAddress); … … 128 137 if(ordexports) 129 138 free(ordexports); 130 131 //SvL: Only happens for images that aren't really loaded (RSRC_LOAD)132 if(fImgMapping) CloseHandle(fImgMapping);133 fImgMapping = 0;134 139 } 135 140 //****************************************************************************** … … 137 142 BOOL Win32PeLdrImage::init(ULONG reservedMem) 138 143 { 139 LPVOID win32file 140 ULONG filesize, ulRead ;144 LPVOID win32file = NULL; 145 ULONG filesize, ulRead, ulNewPos; 141 146 PIMAGE_SECTION_HEADER psh; 142 147 IMAGE_SECTION_HEADER sh; … … 144 149 int nSections, i; 145 150 char szFullPath[CCHMAXPATH] = ""; 146 147 fImgMapping = VIRTUAL_MapFileA(szFileName, &win32file); 148 149 if (fImgMapping == -1) { 150 strcpy(szErrorModule, OSLibStripPath(szFileName)); 151 IMAGE_DOS_HEADER doshdr; 152 ULONG signature; 153 154 hFile = OSLibDosOpen(szFileName, OSLIB_ACCESS_READONLY|OSLIB_ACCESS_SHAREDENYNONE); 155 156 //default error: 157 strcpy(szErrorModule, OSLibStripPath(szFileName)); 158 if(hFile == NULL) { 151 159 goto failure; 152 160 } 153 154 if(DosQueryPathInfo(szFileName, FIL_QUERYFULLNAME, szFullPath, sizeof(szFullPath)) == 0) { 155 setFullPath(szFullPath); 156 } 157 158 if(GetPEFileHeader (win32file, &fh) == FALSE) { 161 //read dos header 162 if(DosRead(hFile, (LPVOID)&doshdr, sizeof(doshdr), &ulRead)) { 163 goto failure; 164 } 165 if(OSLibDosSetFilePtr(hFile, doshdr.e_lfanew, OSLIB_SETPTR_FILE_BEGIN) == -1) { 166 goto failure; 167 } 168 //read signature dword 169 if(DosRead(hFile, (LPVOID)&signature, sizeof(signature), &ulRead)) { 170 goto failure; 171 } 172 //read pe header 173 if(DosRead(hFile, (LPVOID)&fh, sizeof(fh), &ulRead)) { 174 goto failure; 175 } 176 //read optional header 177 if(DosRead(hFile, (LPVOID)&oh, sizeof(oh), &ulRead)) { 178 goto failure; 179 } 180 if(doshdr.e_magic != IMAGE_DOS_SIGNATURE || signature != IMAGE_NT_SIGNATURE) { 159 181 fout << "Not a valid PE file (probably a 16 bits windows exe/dll)!" << endl; 160 182 WinMessageBox(HWND_DESKTOP, HWND_DESKTOP, szPEErrorMsg, szErrorTitle, 0, MB_OK | MB_ERROR | MB_MOVEABLE); 161 183 goto failure; 184 } 185 186 if(oh.SizeOfImage == 0) {//just in case 187 oh.SizeOfImage = OSLibDosGetFileSize(hFile); 188 } 189 190 imageSize = oh.SizeOfImage; 191 //Allocate memory told hold the entire image 192 if(allocSections(reservedMem) == FALSE) { 193 fout << "Failed to allocate image memory, rc " << errorState << endl; 194 goto failure; 195 } 196 197 memmap = new Win32MemMap(this, realBaseAddress, imageSize); 198 if(memmap == NULL || !memmap->Init(0)) { 199 strcpy(szErrorModule, OSLibStripPath(szFileName)); 200 goto failure; 201 } 202 win32file = memmap->mapViewOfFile(0, 0, 2); 203 204 if(DosQueryPathInfo(szFileName, FIL_QUERYFULLNAME, szFullPath, sizeof(szFullPath)) == 0) { 205 setFullPath(szFullPath); 162 206 } 163 207 … … 183 227 } 184 228 185 GetPEOptionalHeader (win32file, &oh);186 229 fout << "PE file : " << szFileName << endl; 187 230 fout << "PE Optional header: " << endl; … … 200 243 fout << "FileAlignment : " << oh.FileAlignment << endl; 201 244 fout << "Subsystem : " << oh.Subsystem << endl; 245 fout << "Image Size : " << oh.SizeOfImage << endl; 246 fout << "Header Size : " << oh.SizeOfHeaders << endl; 247 248 //get header page 249 commitPage(realBaseAddress, FALSE); 202 250 203 251 nSections = NR_SECTIONS(win32file); … … 205 253 if(loadType == REAL_LOAD) 206 254 { 255 imageSize = 0; 207 256 if ((psh = (PIMAGE_SECTION_HEADER)SECTIONHDROFF (win32file)) != NULL) { 208 257 fout << endl << "*************************PE SECTIONS START**************************" << endl; … … 215 264 if(strcmp(psh[i].Name, ".reloc") == 0) { 216 265 fout << ".reloc" << endl << endl; 217 addSection(SECTION_RELOC, (char *)win32file+psh[i].PointerToRawData,266 addSection(SECTION_RELOC, psh[i].PointerToRawData, 218 267 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 219 268 psh[i].Misc.VirtualSize); … … 222 271 if(strcmp(psh[i].Name, ".edata") == 0) { 223 272 fout << ".edata" << endl << endl; 224 addSection(SECTION_EXPORT, (char *)win32file+psh[i].PointerToRawData,273 addSection(SECTION_EXPORT, psh[i].PointerToRawData, 225 274 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 226 275 psh[i].Misc.VirtualSize); … … 229 278 if(strcmp(psh[i].Name, ".rsrc") == 0) { 230 279 fout << ".rsrc" << endl << endl; 231 addSection(SECTION_RESOURCE, (char *)win32file+psh[i].PointerToRawData,280 addSection(SECTION_RESOURCE, psh[i].PointerToRawData, 232 281 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 233 282 psh[i].Misc.VirtualSize); … … 243 292 fout << "TLS SizeOfZeroFill " << hex(tlsDir->SizeOfZeroFill) << endl; 244 293 fout << "TLS Characteristics " << hex(tlsDir->Characteristics) << endl; 245 addSection(SECTION_TLS, (char *)win32file+psh[i].PointerToRawData,294 addSection(SECTION_TLS, psh[i].PointerToRawData, 246 295 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 247 296 psh[i].Misc.VirtualSize); … … 252 301 if(strcmp(psh[i].Name, ".debug") == 0) { 253 302 fout << ".rdebug" << endl << endl; 254 addSection(SECTION_DEBUG, (char *)win32file+psh[i].PointerToRawData,303 addSection(SECTION_DEBUG, psh[i].PointerToRawData, 255 304 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 256 305 psh[i].Misc.VirtualSize); … … 265 314 type |= SECTION_CODE; 266 315 } 267 addSection(type, (char *)win32file+psh[i].PointerToRawData,316 addSection(type, psh[i].PointerToRawData, 268 317 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 269 318 psh[i].Misc.VirtualSize); … … 278 327 { 279 328 fout << "Code Section" << endl << endl; 280 addSection(SECTION_CODE, (char *)win32file+psh[i].PointerToRawData,329 addSection(SECTION_CODE, psh[i].PointerToRawData, 281 330 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 282 331 psh[i].Misc.VirtualSize); … … 285 334 if(!(psh[i].Characteristics & IMAGE_SCN_MEM_WRITE)) { //read only data section 286 335 fout << "Read Only Data Section" << endl << endl; 287 addSection(SECTION_READONLYDATA, (char *)win32file+psh[i].PointerToRawData,336 addSection(SECTION_READONLYDATA, psh[i].PointerToRawData, 288 337 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 289 338 psh[i].Misc.VirtualSize); … … 292 341 if(psh[i].Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) { 293 342 fout << "Uninitialized Data Section" << endl << endl; 294 addSection(SECTION_UNINITDATA, (char *)win32file+psh[i].PointerToRawData,343 addSection(SECTION_UNINITDATA, psh[i].PointerToRawData, 295 344 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 296 345 psh[i].Misc.VirtualSize); … … 299 348 if(psh[i].Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) { 300 349 fout << "Initialized Data Section" << endl << endl; 301 addSection(SECTION_INITDATA, (char *)win32file+psh[i].PointerToRawData,350 addSection(SECTION_INITDATA, psh[i].PointerToRawData, 302 351 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 303 352 psh[i].Misc.VirtualSize); … … 306 355 if(psh[i].Characteristics & (IMAGE_SCN_MEM_WRITE | IMAGE_SCN_MEM_READ)) { 307 356 fout << "Other Section, stored as read/write uninit data" << endl << endl; 308 addSection(SECTION_UNINITDATA, (char *)win32file+psh[i].PointerToRawData,357 addSection(SECTION_UNINITDATA, psh[i].PointerToRawData, 309 358 psh[i].SizeOfRawData, psh[i].VirtualAddress + oh.ImageBase, 310 359 psh[i].Misc.VirtualSize); … … 319 368 if(GetSectionHdrByName (win32file, &sh, ".rsrc")) 320 369 { 321 addSection(SECTION_RESOURCE, (char *)win32file+sh.PointerToRawData,370 addSection(SECTION_RESOURCE, sh.PointerToRawData, 322 371 sh.SizeOfRawData, sh.VirtualAddress + oh.ImageBase, 323 372 sh.Misc.VirtualSize); … … 335 384 imageSize = imageVirtEnd - oh.ImageBase; 336 385 } 337 if( allocSections(reservedMem) == FALSE) {338 fout << "Failed to allocate image memory, rc " << errorState << endl;339 goto failure;340 } 386 if(imageSize < oh.SizeOfImage) { 387 imageSize = oh.SizeOfImage; 388 } 389 341 390 fout << "OS/2 base address " << realBaseAddress << endl; 342 if(storeSections((char *)win32file) == FALSE) {343 fout << "Failed to store sections, rc " << errorState << endl;344 goto failure;345 }346 391 if(oh.AddressOfEntryPoint) { 347 392 entryPoint = realBaseAddress + oh.AddressOfEntryPoint; … … 350 395 fout << "EntryPoint == NULL" << endl; 351 396 entryPoint = NULL; 397 } 398 399 //set memory protection flags 400 if(setMemFlags() == FALSE) { 401 fout << "Failed to set memory protection" << endl; 402 goto failure; 352 403 } 353 404 … … 361 412 goto failure; 362 413 } 363 setTLSAddress((char *) (sect->realvirtaddr + (tlsDir->StartAddressOfRawData - sect->virtaddr)));414 setTLSAddress((char *)sect->realvirtaddr); 364 415 setTLSInitSize(tlsDir->EndAddressOfRawData - tlsDir->StartAddressOfRawData); 365 416 setTLSTotalSize(tlsDir->EndAddressOfRawData - tlsDir->StartAddressOfRawData + tlsDir->SizeOfZeroFill); … … 381 432 382 433 if(realBaseAddress != oh.ImageBase) { 383 if(setFixups((PIMAGE_BASE_RELOCATION)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC)) == FALSE) { 384 fout << "Failed to set fixups" << endl; 385 goto failure; 386 } 434 pFixups = (PIMAGE_BASE_RELOCATION)ImageDirectoryOffset(win32file, IMAGE_DIRECTORY_ENTRY_BASERELOC); 435 commitPage((ULONG)pFixups, FALSE); 387 436 } 388 437 if(fh.Characteristics & IMAGE_FILE_DLL) { … … 394 443 } 395 444 445 for (i=0; i<nSections; i++) { 446 commitPage((ULONG)section[i].realvirtaddr, FALSE, COMPLETE_SECTION); 447 } 448 396 449 //SvL: Use pointer to image header as module handle now. Some apps needs this 397 450 hinstance = (HINSTANCE)realBaseAddress; … … 413 466 } 414 467 415 //set final memory protection flags (storeSections sets them to read/write)416 if(setMemFlags() == FALSE) {417 fout << "Failed to set memory protection" << endl;418 goto failure;419 }420 CloseHandle(fImgMapping);421 fImgMapping = 0;422 423 468 return(TRUE); 424 469 failure: 425 if(fImgMapping) CloseHandle(fImgMapping); 426 fImgMapping = 0; 470 if(memmap) { 471 delete memmap; 472 memmap = NULL; 473 } 474 if(hFile) { 475 OSLibDosClose(hFile); 476 hFile = 0; 477 } 427 478 errorState = ERROR_INTERNAL; 428 479 return FALSE; 429 480 } 430 481 //****************************************************************************** 431 //****************************************************************************** 432 void Win32PeLdrImage::addSection(ULONG type, char *rawdata, ULONG rawsize, ULONG virtaddress, ULONG virtsize) 482 //commits image page(s) when an access violation exception is dispatched 483 //virtAddress = address of exception (rounded down to page boundary) 484 //****************************************************************************** 485 BOOL Win32PeLdrImage::commitPage(ULONG virtAddress, BOOL fWriteAccess, int fPageCmd) 486 { 487 Section *section; 488 ULONG offset, size, sectionsize, protflags, fileoffset, range, attr; 489 ULONG ulNewPos, ulRead; 490 APIRET rc; 491 492 rc = DosQueryMem((PVOID)virtAddress, &range, &attr); 493 if(rc) { 494 dprintf(("Win32PeLdrImage::commitPage: DosQueryMem returned %d", rc)); 495 return FALSE; 496 } 497 if(attr & PAG_COMMIT) { 498 dprintf(("Win32PeLdrImage::commitPage: Memory at 0x%x already committed!", virtAddress)); 499 return FALSE; 500 } 501 502 section = findSectionByOS2Addr(virtAddress); 503 if(section == NULL) { 504 size = 4096; 505 sectionsize = 4096; 506 protflags = PAG_READ|PAG_WRITE; //readonly? 507 section = findPreviousSectionByOS2Addr(virtAddress); 508 if(section == NULL) {//access to header 509 fileoffset = virtAddress - realBaseAddress; 510 } 511 else { 512 offset = virtAddress - (section->realvirtaddr + section->virtualsize); 513 fileoffset = section->rawoffset + section->rawsize + offset; 514 } 515 } 516 else { 517 protflags = section->pageflags; 518 offset = virtAddress - section->realvirtaddr; 519 sectionsize = section->virtualsize - offset; 520 if(offset > section->rawsize) { 521 //unintialized data (set to 0) 522 size = 0; 523 fileoffset = -1; 524 } 525 else { 526 size = section->rawsize-offset; 527 fileoffset = section->rawoffset + offset; 528 } 529 if(fWriteAccess & !(section->pageflags & PAG_WRITE)) { 530 dprintf(("Win32PeLdrImage::commitPage: No write access to 0%x!", virtAddress)); 531 return FALSE; 532 } 533 } 534 if(fPageCmd == SINGLE_PAGE) { 535 size = min(size, PAGE_SIZE); 536 sectionsize = min(sectionsize, PAGE_SIZE); 537 } 538 else 539 if(fPageCmd == SECTION_PAGES) { 540 size = min(size, DEFAULT_NR_PAGES*PAGE_SIZE); 541 sectionsize = min(sectionsize, DEFAULT_NR_PAGES*PAGE_SIZE); 542 } 543 size = min(size, range); 544 sectionsize = min(sectionsize, range); 545 546 if(fileoffset != -1) { 547 rc = DosSetMem((PVOID)virtAddress, sectionsize, PAG_READ|PAG_WRITE|PAG_COMMIT); 548 if(rc) { 549 dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc)); 550 return FALSE; 551 } 552 553 if(DosSetFilePtr(hFile, fileoffset, FILE_BEGIN, &ulNewPos) == -1) { 554 dprintf(("Win32PeLdrImage::commitPage: DosSetFilePtr failed for 0x%x!", fileoffset)); 555 return FALSE; 556 } 557 if(DosRead(hFile, (PVOID)virtAddress, size, &ulRead)) { 558 dprintf(("Win32PeLdrImage::commitPage: DosRead failed for 0x%x!", virtAddress)); 559 return FALSE; 560 } 561 if(ulRead != size) { 562 dprintf(("Win32PeLdrImage::commitPage: DosRead failed to read %x (%x) bytes for 0x%x!", size, ulRead, virtAddress)); 563 return FALSE; 564 } 565 if(realBaseAddress != oh.ImageBase) { 566 setFixups(virtAddress, sectionsize); 567 } 568 569 rc = DosSetMem((PVOID)virtAddress, sectionsize, protflags); 570 if(rc) { 571 dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc)); 572 return FALSE; 573 } 574 } 575 else { 576 rc = DosSetMem((PVOID)virtAddress, sectionsize, PAG_READ|PAG_WRITE|PAG_COMMIT); 577 if(rc) { 578 dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc)); 579 return FALSE; 580 } 581 if(realBaseAddress != oh.ImageBase) { 582 setFixups(virtAddress, sectionsize); 583 } 584 rc = DosSetMem((PVOID)virtAddress, sectionsize, protflags); 585 if(rc) { 586 dprintf(("Win32PeLdrImage::commitPage: DosSetMem failed (%d)!", rc)); 587 return FALSE; 588 } 589 } 590 return TRUE; 591 } 592 //****************************************************************************** 593 //****************************************************************************** 594 void Win32PeLdrImage::addSection(ULONG type, ULONG rawoffset, ULONG rawsize, ULONG virtaddress, ULONG virtsize) 433 595 { 434 596 virtsize = max(rawsize, virtsize); 435 597 598 section[nrsections].rawoffset = rawoffset; 436 599 section[nrsections].type = type; 437 section[nrsections].rawdata = rawdata;438 600 section[nrsections].rawsize = rawsize; 439 601 section[nrsections].virtaddr = virtaddress; … … 458 620 459 621 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { 460 fout << "No fixups, might not run!" << endl;461 622 return allocFixedMem(reservedMem); 462 623 } 463 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | flAllocMem);624 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | PAG_WRITE | flAllocMem); 464 625 if(rc) { 626 dprintf(("Win32PeLdrImage::allocSections, DosAllocMem returned %d", rc)); 465 627 errorState = rc; 466 628 return(FALSE); … … 490 652 } 491 653 return NULL; 654 } 655 //****************************************************************************** 656 //****************************************************************************** 657 Section *Win32PeLdrImage::findSectionByOS2Addr(ULONG addr) 658 { 659 for(int i=0;i<nrsections;i++) { 660 if(section[i].realvirtaddr <= addr && section[i].realvirtaddr + section[i].virtualsize > addr) { 661 return §ion[i]; 662 } 663 } 664 return NULL; 665 } 666 //****************************************************************************** 667 //****************************************************************************** 668 Section *Win32PeLdrImage::findPreviousSectionByOS2Addr(ULONG addr) 669 { 670 ULONG lowestAddr = 0xffffffff; 671 ULONG index = -1; 672 673 for(int i=0;i<nrsections;i++) { 674 if(section[i].realvirtaddr > addr) { 675 if(section[i].realvirtaddr < lowestAddr) { 676 lowestAddr = section[i].realvirtaddr; 677 index = i; 678 } 679 } 680 } 681 if(index == -1) 682 return NULL; 683 684 return §ion[index]; 492 685 } 493 686 //****************************************************************************** … … 503 696 ULONG diff, i, baseAddress; 504 697 APIRET rc; 698 BOOL allocFlags = flAllocMem; 505 699 506 700 realBaseAddress = 0; … … 521 715 } 522 716 717 if(oh.ImageBase < 512*1024*124) { 718 allocFlags = 0; 719 } 523 720 while(TRUE) { 524 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | flAllocMem);721 rc = DosAllocMem((PPVOID)&address, FALLOC_SIZE, PAG_READ | allocFlags); 525 722 if(rc) break; 526 723 … … 536 733 diff = oh.ImageBase - address; 537 734 if(diff) { 538 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | flAllocMem);735 rc = DosAllocMem((PPVOID)&address, diff, PAG_READ | allocFlags); 539 736 if(rc) break; 540 737 } 541 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | flAllocMem);738 rc = DosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | PAG_WRITE | allocFlags); 542 739 if(rc) break; 543 740 … … 561 758 //****************************************************************************** 562 759 //****************************************************************************** 563 BOOL Win32PeLdrImage::s toreSections(char *win32file)760 BOOL Win32PeLdrImage::setMemFlags() 564 761 { 565 762 int i; 566 APIRET rc;567 ULONG pagFlags = PAG_COMMIT;568 ULONG headersize;569 763 WINIMAGE_LOOKUP *imgLookup; 570 764 571 //Commit memory for image header572 headersize = sizeof(IMAGE_DOS_HEADER) + sizeof(IMAGE_NT_HEADERS) +573 sizeof(IMAGE_SECTION_HEADER) * fh.NumberOfSections;574 575 if(headersize + sizeof(WINIMAGE_LOOKUP) < PAGE_SIZE) {576 headersize = PAGE_SIZE;577 }578 else {//ooops, just in case this doesn't work579 fout << "ERROR: storeSections: header too big!!!!!! Fatal error" << endl;580 return FALSE;581 }582 583 rc = DosSetMem((PVOID)realBaseAddress, headersize, pagFlags | PAG_WRITE | PAG_READ);584 if(rc) {585 fout << "DosSetMem failed for Image header! " << rc << endl;586 return FALSE;587 }588 // Store the NT header at the load addr589 memcpy((char *)realBaseAddress, win32file, sizeof(IMAGE_DOS_HEADER));590 memcpy((char *)PE_HEADER(realBaseAddress), PE_HEADER(win32file), sizeof(IMAGE_NT_HEADERS));591 memcpy(PE_SECTIONS(realBaseAddress), PE_SECTIONS(win32file),592 sizeof(IMAGE_SECTION_HEADER) * fh.NumberOfSections );593 594 765 imgLookup = WINIMAGE_LOOKUPADDR(realBaseAddress); 595 imgLookup->image = this; 596 #ifdef DEBUG 597 imgLookup->magic = MAGIC_WINIMAGE; 598 #endif 766 imgLookup->magic1 = MAGIC_WINIMAGE; 767 imgLookup->image = this; 768 imgLookup->magic2 = MAGIC_WINIMAGE; 599 769 600 770 // Process all the image sections … … 602 772 section[i].realvirtaddr = realBaseAddress + (section[i].virtaddr - oh.ImageBase); 603 773 } 774 604 775 for(i=0;i<nrsections;i++) { 605 pagFlags = PAG_COMMIT;606 switch(section[i].type){776 switch(section[i].type) 777 { 607 778 case SECTION_CODE: 608 779 case (SECTION_CODE | SECTION_IMPORT): 609 case SECTION_INITDATA: 610 case SECTION_UNINITDATA: 611 case SECTION_IMPORT: 612 case SECTION_READONLYDATA: 613 case SECTION_RESOURCE: 614 case SECTION_TLS: 615 pagFlags |= PAG_WRITE | PAG_READ; 616 break; 617 case SECTION_EXPORT: 618 case SECTION_DEBUG: 619 case SECTION_RELOC: 620 pagFlags = 0; //don't commit 621 break; 622 } 623 if(pagFlags == 0) continue; //debug or export section 624 625 rc = DosSetMem((PVOID)section[i].realvirtaddr, section[i].virtualsize, pagFlags); 626 if(rc) { 627 errorState = rc; 628 return(FALSE); 629 } 630 if(section[i].type != SECTION_UNINITDATA) { 631 assert(section[i].rawdata); 632 memcpy((char *)section[i].realvirtaddr, section[i].rawdata, section[i].rawsize); 633 } 634 } 635 return(TRUE); 636 } 637 //****************************************************************************** 638 //****************************************************************************** 639 BOOL Win32PeLdrImage::setMemFlags() 640 { 641 int i; 642 APIRET rc; 643 ULONG pagFlags = 0; 644 645 for(i=0;i<nrsections;i++) { 646 pagFlags = 0; 647 switch(section[i].type) { 648 case SECTION_CODE: 649 case (SECTION_CODE | SECTION_IMPORT): 650 pagFlags |= PAG_EXECUTE | PAG_READ; 780 section[i].pageflags = PAG_EXECUTE | PAG_READ; 651 781 break; 652 782 case SECTION_INITDATA: 653 783 case SECTION_UNINITDATA: 654 784 case SECTION_IMPORT: //TODO: read only? 655 pagFlags |= PAG_WRITE | PAG_READ;785 section[i].pageflags = PAG_WRITE | PAG_READ; 656 786 break; 657 787 case SECTION_READONLYDATA: 658 788 case SECTION_RESOURCE: 659 789 case SECTION_TLS: 660 pagFlags |= PAG_READ; 790 default: 791 section[i].pageflags = PAG_READ; 661 792 break; 662 default:663 continue;664 793 } 665 rc = DosSetMem((PVOID)section[i].realvirtaddr, section[i].virtualsize, pagFlags); 666 if(rc) { 667 errorState = rc; 668 return(FALSE); 669 } 794 } 795 return(TRUE); 796 } 797 //****************************************************************************** 798 //****************************************************************************** 799 BOOL Win32PeLdrImage::setFixups(ULONG virtAddress, ULONG size) 800 { 801 int i, j; 802 char *page; 803 ULONG count, newpage; 804 Section *section; 805 PIMAGE_BASE_RELOCATION prel = pFixups; 806 807 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { 808 return(TRUE); 809 } 810 811 virtAddress -= realBaseAddress; 812 813 if(prel) { 814 j = 1; 815 while(prel->VirtualAddress && prel->VirtualAddress < virtAddress) { 816 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock); 817 } 818 while(prel->VirtualAddress && prel->VirtualAddress < virtAddress + size) { 819 page = (char *)((char *)prel + (ULONG)prel->VirtualAddress); 820 count = (prel->SizeOfBlock - 8)/2; 821 j++; 822 for(i=0;i<count;i++) { 823 int type = prel->TypeOffset[i] >> 12; 824 int offset = prel->TypeOffset[i] & 0xFFF; 825 int fixupsize = 0; 826 827 switch(type) 828 { 829 case IMAGE_REL_BASED_HIGHLOW: 830 fixupsize = 4; 831 break; 832 case IMAGE_REL_BASED_HIGH: 833 case IMAGE_REL_BASED_LOW: 834 fixupsize = 2; 835 break; 836 } 837 //If the fixup crosses the final page boundary, 838 //then we have to load another page 839 if(prel->VirtualAddress + offset + fixupsize > virtAddress + size) 840 { 841 newpage = realBaseAddress + prel->VirtualAddress + offset + fixupsize; 842 newpage &= ~0xFFF; 843 844 section = findSectionByOS2Addr(newpage); 845 if(section == NULL) { 846 //should never happen 847 dprintf(("::setFixups -> section == NULL!!")); 848 return FALSE; 849 } 850 //SvL: Read page from disk 851 commitPage(newpage, TRUE, SINGLE_PAGE); 852 853 //SvL: Enable write access 854 DosSetMem((PVOID)newpage, PAGE_SIZE, PAG_READ|PAG_WRITE); 855 } 856 857 switch(type) 858 { 859 case IMAGE_REL_BASED_ABSOLUTE: 860 break; //skip 861 case IMAGE_REL_BASED_HIGHLOW: 862 AddOff32Fixup(prel->VirtualAddress + offset); 863 break; 864 case IMAGE_REL_BASED_HIGH: 865 AddOff16Fixup(prel->VirtualAddress + offset, TRUE); 866 break; 867 case IMAGE_REL_BASED_LOW: 868 AddOff16Fixup(prel->VirtualAddress + offset, FALSE); 869 break; 870 case IMAGE_REL_BASED_HIGHADJ: 871 case IMAGE_REL_BASED_MIPS_JMPADDR: 872 default: 873 break; 874 } 875 if(prel->VirtualAddress + offset + fixupsize > virtAddress + size) 876 { 877 //SvL: Restore original page protection flags 878 DosSetMem((PVOID)newpage, PAGE_SIZE, section->pageflags); 879 } 880 881 } 882 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock); 883 }//while 884 } 885 else { 886 dprintf(("Win32PeLdrImage::setFixups, no fixups at %x, %d", virtAddress, size)); 887 return(FALSE); 670 888 } 671 889 return(TRUE); … … 680 898 681 899 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { 682 return(TRUE);900 return(TRUE); 683 901 } 684 902 … … 701 919 case IMAGE_REL_BASED_HIGHLOW: 702 920 //// fout << "address " << offset << " type " << type << endl; 703 AddOff32Fixup(oh.ImageBase + 704 prel->VirtualAddress + offset); 921 AddOff32Fixup(prel->VirtualAddress + offset); 705 922 break; 706 923 case IMAGE_REL_BASED_HIGH: 707 AddOff16Fixup( oh.ImageBase +prel->VirtualAddress + offset, TRUE);924 AddOff16Fixup(prel->VirtualAddress + offset, TRUE); 708 925 break; 709 926 case IMAGE_REL_BASED_LOW: 710 AddOff16Fixup( oh.ImageBase +prel->VirtualAddress + offset, FALSE);927 AddOff16Fixup(prel->VirtualAddress + offset, FALSE); 711 928 break; 712 929 case IMAGE_REL_BASED_HIGHADJ: … … 734 951 ULONG *fixup; 735 952 736 fixup = (ULONG *)(fixupaddr - oh.ImageBase+ realBaseAddress);953 fixup = (ULONG *)(fixupaddr + realBaseAddress); 737 954 orgaddr = *fixup; 738 955 *fixup = realBaseAddress + (*fixup - oh.ImageBase); … … 745 962 USHORT *fixup; 746 963 747 fixup = (USHORT *)(fixupaddr - oh.ImageBase+ realBaseAddress);964 fixup = (USHORT *)(fixupaddr + realBaseAddress); 748 965 orgaddr = *fixup; 749 966 if(fHighFixup) { … … 761 978 ULONG apiaddr; 762 979 763 import = (ULONG *) (impaddr - oh.ImageBase + realBaseAddress);980 import = (ULONG *)impaddr; 764 981 apiaddr = WinDll->getApi(ordinal); 765 982 if(apiaddr == 0) 766 983 { 767 dprintf(("KERNEL32:Win32PeLdrImage - %s.%u not found\n",768 WinDll->getName(),769 ordinal));984 dprintf(("KERNEL32:Win32PeLdrImage - %s.%u not found\n", 985 WinDll->getName(), 986 ordinal)); 770 987 771 988 fout << "--->>> NOT FOUND!" << endl; … … 781 998 ULONG apiaddr; 782 999 783 import = (ULONG *) (impaddr - oh.ImageBase + realBaseAddress);1000 import = (ULONG *)impaddr; 784 1001 apiaddr = WinDll->getApi(impname); 785 1002 if(apiaddr == 0) 786 1003 { 787 dprintf(("KERNEL32:Win32PeLdrImage - %s.%s not found\n",788 WinDll->getName(),789 impname));1004 dprintf(("KERNEL32:Win32PeLdrImage - %s.%s not found\n", 1005 WinDll->getName(), 1006 impname)); 790 1007 791 1008 fout << "--->>> NOT FOUND!" << endl; … … 810 1027 811 1028 fout << "Exported Functions: " << endl; 812 ptrOrd = (USHORT *)((ULONG)ped->AddressOfNameOrdinals - 813 (ULONG)sh.VirtualAddress + 814 (ULONG)sh.PointerToRawData + (ULONG)win32file); 815 ptrNames = (ULONG *)((ULONG)ped->AddressOfNames - 816 (ULONG)sh.VirtualAddress + 817 (ULONG)sh.PointerToRawData + (ULONG)win32file); 818 ptrAddress = (ULONG *)((ULONG)ped->AddressOfFunctions - 819 (ULONG)sh.VirtualAddress + 820 (ULONG)sh.PointerToRawData + (ULONG)win32file); 1029 ptrOrd = (USHORT *)((ULONG)ped->AddressOfNameOrdinals + 1030 (ULONG)win32file); 1031 ptrNames = (ULONG *)((ULONG)ped->AddressOfNames + 1032 (ULONG)win32file); 1033 ptrAddress = (ULONG *)((ULONG)ped->AddressOfFunctions + 1034 (ULONG)win32file); 821 1035 nrOrdExports = ped->NumberOfFunctions; 822 1036 nrNameExports = ped->NumberOfNames; … … 826 1040 for(i=0;i<ped->NumberOfNames;i++) { 827 1041 ord = ptrOrd[i] + ped->Base; 828 name = (char *)((ULONG)ptrNames[i] - (ULONG)sh.VirtualAddress + 829 (ULONG)sh.PointerToRawData + (ULONG)win32file); 1042 name = (char *)((ULONG)ptrNames[i] + (ULONG)win32file); 830 1043 RVAExport = ptrAddress[ptrOrd[i]]; 831 1044 #ifdef FORWARDERS … … 833 1046 #endif 834 1047 //points to code (virtual address relative to oh.ImageBase 835 fout << "address 0x"; 836 fout.setf(ios::hex, ios::basefield); 1048 AddNameExport(oh.ImageBase + RVAExport, name, ord); 1049 fout << "address 0x"; 1050 fout.setf(ios::hex, ios::basefield); 837 1051 fout << RVAExport; 838 fout.setf(ios::dec, ios::basefield); 839 fout << " " << name << "@" << ord << endl; 840 AddNameExport(oh.ImageBase + RVAExport, name, ord); 1052 fout.setf(ios::dec, ios::basefield); 1053 fout << " " << name << "@" << ord << endl; 841 1054 #ifdef FORWARDERS 842 1055 843 1056 } 844 1057 else {//forwarder 845 char *forward = (char *)((ULONG)RVAExport - 846 (ULONG)sh.VirtualAddress + 847 (ULONG)sh.PointerToRawData + 848 (ULONG)win32file); 1058 char *forward = (char *)((ULONG)RVAExport + (ULONG)win32file); 849 1059 fout << RVAExport << " " << name << " @" << ord << " is forwarder to " << (int)forward << endl; 850 1060 } … … 868 1078 } 869 1079 else {//forwarder or empty 870 char *forward = (char *)((ULONG)RVAExport - 871 (ULONG)sh.VirtualAddress + 872 (ULONG)sh.PointerToRawData + 873 (ULONG)win32file); 1080 char *forward = (char *)((ULONG)RVAExport + (ULONG)win32file); 874 1081 fout << "ord " << ord << " at 0x"; 875 1082 fout.setf(ios::hex, ios::basefield); 876 1083 fout << RVAExport << " is forwarder to 0x" << (int)forward << endl; 877 1084 fout.setf(ios::dec, ios::basefield); 878 1085 } 879 1086 #endif … … 939 1146 IMAGE_SECTION_HEADER shExtra = {0}; 940 1147 PIMAGE_OPTIONAL_HEADER pOH; 941 int i,j ;1148 int i,j, nrPages; 942 1149 BOOL fBorland = 0; 943 1150 int cModules; … … 949 1156 int Size; 950 1157 Win32PeLdrDll *WinDll; 1158 Section *section; 951 1159 952 1160 /* "algorithm:" … … 975 1183 //test RVA inside ID-Section 976 1184 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)) { 977 pszTmp = (char*)(pID[i].Name - shID.VirtualAddress + shID.PointerToRawData+ (ULONG)win32file);1185 pszTmp = (char*)(pID[i].Name + (ULONG)win32file); 978 1186 } 979 1187 else { … … 983 1191 return FALSE; 984 1192 } 985 pszTmp = (char*)(pID[i].Name - shExtra.VirtualAddress + shExtra.PointerToRawData+ (ULONG)win32file);1193 pszTmp = (char*)(pID[i].Name + (ULONG)win32file); 986 1194 } 987 1195 Size += strlen(pszTmp) + 1; … … 997 1205 //test RVA inside ID-Section 998 1206 if (pID[i].Name >= shID.VirtualAddress && pID[i].Name < shID.VirtualAddress + max(shID.Misc.VirtualSize, shID.SizeOfRawData)) { 999 pszTmp = (char*)(pID[i].Name - shID.VirtualAddress + shID.PointerToRawData+ (ULONG)win32file);1207 pszTmp = (char*)(pID[i].Name + (ULONG)win32file); 1000 1208 } 1001 1209 else { … … 1009 1217 } 1010 1218 } 1011 pszTmp = (char*)(pID[i].Name - shExtra.VirtualAddress + shExtra.PointerToRawData+ (ULONG)win32file);1219 pszTmp = (char*)(pID[i].Name + (ULONG)win32file); 1012 1220 } 1013 1221 … … 1041 1249 } 1042 1250 //light borland-style test 1043 if (pID[i].u.OriginalFirstThunk == 0 || fBorland) 1044 pulImport = (ULONG*)pID[i].FirstThunk; 1251 if (pID[i].u.OriginalFirstThunk == 0 || fBorland) { 1252 pulImport = (ULONG*)pID[i].FirstThunk; 1253 } 1045 1254 else pulImport = (ULONG*)pID[i].u.OriginalFirstThunk; 1046 1255 … … 1131 1340 WinDll->AddRef(); 1132 1341 1133 pulImport = (PULONG)((ULONG)pulImport - shExtra.VirtualAddress + (ULONG)win32file + shExtra.PointerToRawData);1342 pulImport = (PULONG)((ULONG)pulImport + (ULONG)win32file); 1134 1343 j = 0; 1135 ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase; 1344 ulCurFixup = (ULONG)pID[i].FirstThunk + (ULONG)win32file; 1345 1346 section = findSectionByOS2Addr(ulCurFixup); 1347 if(section == NULL) { 1348 fout.setf(ios::hex, ios::basefield); 1349 fout << "Unable to find section for " << ulCurFixup << endl; 1350 return FALSE; 1351 } 1352 //SvL: Read page from disk 1353 commitPage(ulCurFixup & ~0xfff, FALSE, SINGLE_PAGE); 1354 //SvL: Enable write access 1355 DosSetMem((PVOID)(ulCurFixup & ~0xfff), PAGE_SIZE, PAG_READ|PAG_WRITE); 1356 nrPages = 1; 1357 1136 1358 while (pulImport[j] != 0) { 1137 1359 if (pulImport[j] & IMAGE_ORDINAL_FLAG) { //ordinal … … 1151 1373 } 1152 1374 //KSO - Aug 6 1998 1:15am:this eases comparing... 1153 char *pszFunctionName = (char*)(pulImport[j] + (ULONG)win32file + shExtra.PointerToRawData - shExtra.VirtualAddress +2);1375 char *pszFunctionName = (char*)(pulImport[j] + (ULONG)win32file + 2); 1154 1376 fout.setf(ios::hex, ios::basefield); 1155 1377 fout << "0x" << ulCurFixup << " Imported function " << pszFunctionName << endl; … … 1157 1379 StoreImportByName(WinDll, pszFunctionName, ulCurFixup); 1158 1380 } 1159 1381 ulCurFixup += sizeof(IMAGE_THUNK_DATA); 1160 1382 j++; 1383 if((ulCurFixup & 0xfff) == 0) { 1384 commitPage(ulCurFixup & ~0xfff, TRUE, SINGLE_PAGE); 1385 DosSetMem((PVOID)(ulCurFixup & ~0xfff), PAGE_SIZE, PAG_READ|PAG_WRITE); 1386 nrPages++; 1387 } 1161 1388 } 1389 //SvL: And restore original protection flags 1390 ulCurFixup = (ULONG)pID[i].FirstThunk + pOH->ImageBase; 1391 DosSetMem((PVOID)(ulCurFixup & ~0xfff), PAGE_SIZE*nrPages, section->pageflags); 1392 1162 1393 fout << "**********************************************************************" << endl; 1163 1394 fout << "************** End Import Module " << pszCurModule << endl; … … 1184 1415 do { 1185 1416 r = WinMessageBox(HWND_DESKTOP, NULLHANDLE, "The application has called a non-existing api\n", 1186 "Internal Error", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE);1417 "Internal Odin Error", 0, MB_ABORTRETRYIGNORE | MB_ICONEXCLAMATION | MB_MOVEABLE); 1187 1418 } 1188 1419 while(r == MBID_RETRY); //giggle
Note:
See TracChangeset
for help on using the changeset viewer.