- Timestamp:
- Jul 17, 2002, 11:09:20 PM (23 years ago)
- Location:
- trunk/src/kernel32
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kernel32/winimagelx.cpp
r8877 r8883 1 /* $Id: winimagelx.cpp,v 1.1 5 2002-07-15 14:28:53 sandervlExp $ */1 /* $Id: winimagelx.cpp,v 1.16 2002-07-17 21:09:20 achimha Exp $ */ 2 2 3 3 /* … … 123 123 ULONG apiaddr; 124 124 125 rc = DosQueryProcAddr(hinstanceOS2, dwOrdinalBase +ordinal, NULL, (PFN *)&apiaddr);125 rc = DosQueryProcAddr(hinstanceOS2, dwOrdinalBase + ordinal, NULL, (PFN *)&apiaddr); 126 126 if(rc) { 127 127 dprintf(("Win32LxImage::getApi %x %d -> rc = %d", hinstanceOS2, ordinal, rc)); … … 131 131 } 132 132 //****************************************************************************** 133 // here we build a fake PE header for an LX module. In Windows, HINSTANCE handles 134 // actually contain the virtual address of of the PE header. We try to fill in 135 // sensible values as much as possible... 133 136 //****************************************************************************** 134 137 LPVOID Win32LxImage::buildHeader(DWORD MajorImageVersion, DWORD MinorImageVersion, … … 141 144 DWORD *ntsig; 142 145 146 // AH TODO: we are wasting 60k address space here!!!! (at least without PAG_ANY) 143 147 rc = DosAllocMem(&header, 4096, PAG_READ | PAG_WRITE | PAG_COMMIT | flAllocMem); 144 148 if(rc) { -
trunk/src/kernel32/winimagepeldr.cpp
r8882 r8883 1 /* $Id: winimagepeldr.cpp,v 1.9 7 2002-07-16 08:16:48 sandervlExp $ */1 /* $Id: winimagepeldr.cpp,v 1.98 2002-07-17 21:09:20 achimha Exp $ */ 2 2 3 3 /* … … 580 580 581 581 #ifdef COMMIT_ALL 582 // this is a workaround until we have full page fault handling. We 583 // just commit all pages here, i.e. do the DosReads 582 584 for (i=0; i<nSections; i++) { 583 585 commitPage((ULONG)section[i].realvirtaddr, FALSE, COMPLETE_SECTION); … … 595 597 } 596 598 #endif 599 // here we are going to parse the export table and build a list 600 // in memory of what this module exports 597 601 if(processExports((char *)win32file) == FALSE) { 598 602 dprintf((LOG, "Failed to process exported apis" )); … … 608 612 #endif 609 613 610 // SvL: Use pointer to image header as module handle now. Some apps needs this614 // a HINSTANCE in Windows is actually a pointer to the PE header! 611 615 hinstance = (HINSTANCE)realBaseAddress; 612 616 … … 623 627 } 624 628 625 //Allocate TLS index for this module 626 //Must do this before dlls are loaded for this module. Some apps assume 627 //they get TLS index 0 for their main executable 629 // Allocate TLS index for this module 630 // Must do this before dlls are loaded for this module. Some apps assume 631 // they get TLS index 0 for their main executable 632 // AH TODO: is this really safe here? We call processExports before and 633 // the module might export forwarders so additional DLLs are loaded which 634 // in turn might allocate TLS in the initterm routine! 628 635 { 629 636 USHORT sel = SetWin32TIB(TIB_SWITCH_FORCE_WIN32); … … 635 642 if(!(dwFlags & (FLAG_PELDR_LOADASDATAFILE | FLAG_PELDR_SKIPIMPORTS))) 636 643 { 644 // this will process all import statements and resolve them. I.e. 645 // additional DLLs will be loaded automatically. 637 646 if(processImports((char *)win32file) == FALSE) { 638 647 dprintf((LOG, "Failed to process imports!" )); … … 728 737 { 729 738 Section *section; 730 ULONG offset, size, sectionsize, protflags, fileoffset, range, attr; 739 ULONG fileoffset; // this will be the offset in the file we have to read at 740 // it will be calculated from the virtual address 741 ULONG offset, size, sectionsize, protflags, range, attr; 731 742 ULONG ulNewPos, ulRead, orgVirtAddress = virtAddress; 732 743 APIRET rc; … … 737 748 } 738 749 739 // Round down to nearest page boundary750 // round down to nearest page boundary 740 751 virtAddress = virtAddress & ~0xFFF; 741 752 753 // check if this address corresponds to any PE section 742 754 section = findSectionByOS2Addr(virtAddress); 743 755 if(section == NULL) { 756 // maybe the section does not start at a page boundary? 744 757 section = findSectionByOS2Addr(orgVirtAddress); 745 758 if(section) { … … 747 760 } 748 761 } 762 // if we still haven't found the section, it's a special case 749 763 if(section == NULL) { 750 764 size = 4096; … … 752 766 //Header page must be readonly (same as in NT) 753 767 protflags = PAG_READ; 768 769 // check if there is a previous section 754 770 section = findPreviousSectionByOS2Addr(virtAddress); 755 if(section == NULL) {//access to header 771 772 // no, so it must be the PE header 773 if(section == NULL) { 756 774 offset = 0; 757 775 fileoffset = virtAddress - realBaseAddress; … … 767 785 sectionsize = section->virtualsize - offset; 768 786 787 // check if this is unitialized data (i.e. not present in the PE file 788 // and set to 0 by the PE loader 769 789 if(offset > section->rawsize || section->type == SECTION_UNINITDATA) { 770 // unintialized data (set to 0)790 // AH TODO shouldn't be abusing these variables here... 771 791 size = 0; 772 792 fileoffset = -1; 773 793 } 774 794 else { 775 size = section->rawsize -offset;795 size = section->rawsize - offset; 776 796 fileoffset = section->rawoffset + offset; 777 797 } … … 781 801 } 782 802 } 783 if(fPageCmd == COMPLETE_SECTION && (section && section->type == SECTION_DEBUG)) {//ignore 803 // we completely ignore debug sections! 804 if(fPageCmd == COMPLETE_SECTION && (section && section->type == SECTION_DEBUG)) { 784 805 return TRUE; 785 806 } … … 811 832 sectionsize = min(sectionsize, range); 812 833 834 // make sure this is not address space that has no backing PE file data 835 // (i.e. uninitialized data) 836 // AH TODO: don't abuse these variables! 813 837 if(size && fileoffset != -1) { 814 838 rc = DosEnterCritSec(); … … 817 841 goto fail; 818 842 } 843 // we need write permissions for now to do the actual loading 819 844 rc = DosSetMem((PVOID)virtAddress, sectionsize, PAG_READ|PAG_WRITE|PAG_COMMIT); 820 845 if(rc) { … … 849 874 setFixups(virtAddress, sectionsize); 850 875 876 // set the protection flags to what the section requests 851 877 rc = DosSetMem((PVOID)virtAddress, sectionsize, protflags); 852 878 DosExitCritSec(); … … 857 883 } 858 884 else { 885 // unitialized data section, padded with 0 (done by OS/2) 886 859 887 rc = DosEnterCritSec(); 860 888 if(rc) { … … 863 891 } 864 892 893 // get temporary write permission 865 894 rc = DosSetMem((PVOID)virtAddress, sectionsize, PAG_READ|PAG_WRITE|PAG_COMMIT); 866 895 if(rc) { … … 871 900 setFixups(virtAddress, sectionsize); 872 901 902 // set the protection flags to what the section requests 873 903 rc = DosSetMem((PVOID)virtAddress, sectionsize, protflags); 874 904 DosExitCritSec(); … … 925 955 return allocFixedMem(reservedMem); 926 956 } 957 // AH TODO: aren't we wasting 64kb address space here if things go bad? 927 958 rc = OSLibDosAllocMem((PPVOID)&baseAddress, imageSize, PAG_READ | PAG_WRITE); 928 959 if(rc) { … … 1098 1129 } 1099 1130 //****************************************************************************** 1131 // setFixups: 1132 // this is the main fixup processing function. It uses the virtual image base 1133 // address (oh.ImageBase) and replaces all fixups by the relative virtual address 1134 // plus the image base address 1100 1135 //****************************************************************************** 1101 1136 BOOL Win32PeLdrImage::setFixups(ULONG virtAddress, ULONG size) 1102 1137 { 1103 int i, j;1138 int i; 1104 1139 char *page; 1105 1140 ULONG count, newpage; … … 1107 1142 PIMAGE_BASE_RELOCATION prel = pFixups; 1108 1143 1144 // is fixup processing required? 1109 1145 if(realBaseAddress == oh.ImageBase || fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { 1110 1146 return(TRUE); 1111 1147 } 1112 1148 1149 // convert the virtual address to a relative virtual address 1113 1150 virtAddress -= realBaseAddress; 1114 //round size to next page boundary 1115 size = (size-1) & ~0xFFF; 1151 1152 // round size to next page boundary 1153 size = (size - 1) & ~0xFFF; 1116 1154 size += PAGE_SIZE; 1117 1155 1156 // do we have relocation records (aka fixups)? 1118 1157 if(prel) { 1119 j = 1;1120 while(((ULONG)prel < (ULONG)pFixups +dwFixupSize) &&1158 // move to the first relocation record 1159 while(((ULONG)prel < (ULONG)pFixups + dwFixupSize) && 1121 1160 prel->VirtualAddress && prel->VirtualAddress < virtAddress) 1122 1161 { 1123 1162 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock); 1124 1163 } 1125 while(((ULONG)prel < (ULONG)pFixups+dwFixupSize) && 1164 // go through all relocation records 1165 while(((ULONG)prel < (ULONG)pFixups + dwFixupSize) && 1126 1166 prel->VirtualAddress && prel->VirtualAddress < virtAddress + size) 1127 1167 { 1128 1168 page = (char *)((char *)prel + (ULONG)prel->VirtualAddress); 1129 count = (prel->SizeOfBlock - 8)/2;1130 j++;1131 for(i =0;i<count;i++) {1169 // determine how many fixups we have to process 1170 count = (prel->SizeOfBlock - 8) / 2; 1171 for(i = 0; i < count; i++) { 1132 1172 int type = prel->TypeOffset[i] >> 12; 1133 1173 int offset = prel->TypeOffset[i] & 0xFFF; … … 1144 1184 break; 1145 1185 } 1146 // If the fixup crosses the final page boundary,1147 // then we have to load another page1186 // if the fixup crosses the final page boundary, 1187 // then we have to load another page 1148 1188 if(prel->VirtualAddress + offset + fixupsize > virtAddress + size) 1149 1189 { … … 1151 1191 newpage &= ~0xFFF; 1152 1192 1193 // find the corresponding section so that we know lateron 1194 // what permission bits we have to assign to the new page 1153 1195 section = findSectionByOS2Addr(newpage); 1154 1196 if(section == NULL) { 1155 // should never happen1156 dprintf((LOG, " ::setFixups -> section == NULL!!"));1197 // should never happen 1198 dprintf((LOG, "setFixups -> section == NULL!!")); 1157 1199 return FALSE; 1158 1200 } 1159 // SvL: Read page from disk1201 // explicitly read page from disk 1160 1202 commitPage(newpage, FALSE, SINGLE_PAGE); 1161 1203 1162 1204 //SvL: Enable write access (TODO: may need to prevent other threads from being active) 1163 DosSetMem((PVOID)newpage, PAGE_SIZE, PAG_READ |PAG_WRITE);1205 DosSetMem((PVOID)newpage, PAGE_SIZE, PAG_READ | PAG_WRITE); 1164 1206 } 1165 1207 … … 1182 1224 break; 1183 1225 } 1226 // did we have to load another page? 1184 1227 if(prel->VirtualAddress + offset + fixupsize > virtAddress + size) 1185 1228 { … … 1188 1231 } 1189 1232 } 1233 // move to the next relocation record 1190 1234 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock); 1191 1235 }//while … … 1201 1245 BOOL Win32PeLdrImage::setFixups(PIMAGE_BASE_RELOCATION prel) 1202 1246 { 1203 int i, j; 1247 int i; 1248 #if DEBUG 1249 int j; 1250 #endif 1204 1251 char *page; 1205 1252 ULONG count; 1206 1253 1254 // if there are no fixups, we have nothing to do... 1207 1255 if(fh.Characteristics & IMAGE_FILE_RELOCS_STRIPPED) { 1208 1256 return(TRUE); … … 1210 1258 1211 1259 if(prel) { 1260 #if DEBUG 1212 1261 j = 1; 1262 #endif 1263 // loop through all relocation records 1213 1264 while(prel->VirtualAddress) { 1214 1265 page = (char *)((char *)prel + (ULONG)prel->VirtualAddress); 1215 count = (prel->SizeOfBlock - 8)/2; 1216 dprintf((LOG, "Page %d Address %x Count %d", j, prel->VirtualAddress, count )); 1266 // determine how many fixups we have to process 1267 count = (prel->SizeOfBlock - 8) / 2; 1268 1269 dprintf((LOG, "Page %d Address %x Count %d", j, prel->VirtualAddress, count)); 1270 #if DEBUG 1217 1271 j++; 1218 for(i=0;i<count;i++) { 1272 #endif 1273 1274 for(i = 0; i < count; i++) { 1219 1275 int type = prel->TypeOffset[i] >> 12; 1220 1276 int offset = prel->TypeOffset[i] & 0xFFF; … … 1240 1296 } 1241 1297 } 1298 // advance to the next relocation record 1242 1299 prel = (PIMAGE_BASE_RELOCATION)((char*)prel + prel->SizeOfBlock); 1243 1300 }//while … … 1259 1316 fixup = (ULONG *)(fixupaddr + realBaseAddress); 1260 1317 orgaddr = *fixup; 1261 // dprintf((LOG, "AddOff32Fixup 0x%x org 0x%x -> new 0x%x", fixup, orgaddr, realBaseAddress + (*fixup - oh.ImageBase)));1318 //// dprintf((LOG, "AddOff32Fixup 0x%x org 0x%x -> new 0x%x", fixup, orgaddr, realBaseAddress + (*fixup - oh.ImageBase))); 1262 1319 *fixup = realBaseAddress + (*fixup - oh.ImageBase); 1263 1320 } … … 1562 1619 } 1563 1620 1621 // if it's not a PE image, we let OS/2 load it (LX image) 1564 1622 if(isPEImage(modname, NULL, NULL) != ERROR_SUCCESS_W) 1565 { //LX image, so let OS/2 do all the work for us1623 { 1566 1624 APIRET rc; 1567 1625 char szModuleFailure[CCHMAXPATH] = ""; … … 1569 1627 Win32LxDll *lxdll; 1570 1628 1629 // check if we have the .DLL extension or have to add it first 1571 1630 char *dot = strchr(modname, '.'); 1572 1631 if(dot == NULL) { 1573 1632 strcat(modname, DLL_EXTENSION); 1574 1633 } 1634 // here we load the module. This will also execute the initterm 1635 // function in the DLL. We expect the LX DLL to callback RegisterLxDll 1636 // to register with Odin. This also means we cannot load "standard" 1637 // LX DLLs with this method - they have to be Odin aware 1575 1638 rc = DosLoadModule(szModuleFailure, sizeof(szModuleFailure), modname, (HMODULE *)&hInstanceNewDll); 1576 1639 if(rc) { … … 1580 1643 return NULL; 1581 1644 } 1645 // due to the callback requirement, we can expect to have a structure 1646 // for it by now. Otherwise it didn't work out 1582 1647 lxdll = Win32LxDll::findModuleByOS2Handle(hInstanceNewDll); 1583 1648 if(lxdll == NULL) {//shouldn't happen! 1584 1649 dprintf((LOG, "Just loaded the dll, but can't find it anywhere?!!?")); 1650 // AH TODO: shouldn't we do a DosFreeModule here? 1585 1651 errorState = ERROR_INTERNAL; 1586 1652 return NULL; 1587 1653 } 1588 1654 lxdll->setDllHandleOS2(hInstanceNewDll); 1655 // AddRef for a LX DLL is special - it does not increase the reference counter 1589 1656 if(lxdll->AddRef() == -1) {//-1 -> load failed (attachProcess) 1590 1657 dprintf((LOG, "Dll %s refused to be loaded; aborting", modname)); … … 1597 1664 else { 1598 1665 Win32PeLdrDll *pedll; 1599 1666 // create an object for that DLL 1600 1667 pedll = new Win32PeLdrDll(modname, this); 1601 1668 if(pedll == NULL) { … … 1608 1675 dprintf((LOG, "********************** Loading Module *********************" )); 1609 1676 dprintf((LOG, "**********************************************************************" )); 1677 // do the actual loading including all imports - so this is a point of recursion 1610 1678 if(pedll->init(0) == FALSE) { 1611 1679 dprintf((LOG, "Internal WinDll error ", pedll->getError() )); … … 1616 1684 pedll->AddRef(getModuleName()); 1617 1685 #else 1686 // increase the reference count 1618 1687 pedll->AddRef(); 1619 1688 #endif 1689 // send the attach process message to the DLL, i.e. call the handler 1620 1690 if(pedll->attachProcess() == FALSE) { 1621 1691 dprintf((LOG, "attachProcess failed!" )); … … 2052 2122 } 2053 2123 //****************************************************************************** 2124 // we link this function to all imports we couldn't resolve in our DLLs so the 2125 // user gets a stupid error message dialog 2054 2126 //****************************************************************************** 2055 2127 ULONG WIN32API MissingApi(char *message)
Note:
See TracChangeset
for help on using the changeset viewer.