Changeset 8003 for trunk/tools/common/kFileLX.cpp
- Timestamp:
- Feb 24, 2002, 3:47:28 AM (24 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tools/common/kFileLX.cpp
r6932 r8003 1 /* $Id: kFileLX.cpp,v 1. 6 2001-10-03 01:44:49bird Exp $1 /* $Id: kFileLX.cpp,v 1.7 2002-02-24 02:47:26 bird Exp $ 2 2 * 3 3 * … … 9 9 */ 10 10 11 /*******************************************************************************12 * Defined Constants *13 *******************************************************************************/14 /* emx fixups */15 #ifdef __EMX__16 #define __stdcall17 #define max(a,b) (((a) > (b)) ? (a) : (b))18 #define min(a,b) (((a) < (b)) ? (a) : (b))19 #endif20 #define INCL_DOSERRORS21 #define FOR_EXEHDR 1 /* exe386.h flag */22 #define DWORD ULONG /* Used by exe386.h / newexe.h */23 #define WORD USHORT /* Used by exe386.h / newexe.h */24 25 26 11 /****************************************************************************** 27 12 * Header Files * 28 13 ******************************************************************************/ 29 #ifdef __EMX__ 30 #define INT INT_ 31 #define PCHAR PCHAR_ 32 #endif 33 #include <os2.h> 34 #ifdef __EMX__ 35 #undef PCHAR 36 #undef INT 37 #endif 38 #include <newexe.h> 39 #include <exe386.h> 14 #include <MZexe.h> 15 #include <LXexe.h> 40 16 41 17 #include <stdio.h> 42 18 #include <stdlib.h> 43 19 #include <string.h> 44 #include <malloc.h> 45 46 #include <assert.h> 47 20 21 #include "kTypes.h" 22 #include "kError.h" 48 23 #include "kFile.h" 49 24 #include "kFileFormatBase.h" 50 #include "k Interfaces.h"25 #include "kFileInterfaces.h" 51 26 #include "kFileLX.h" 52 27 … … 55 30 * Structures and Typedefs * 56 31 *******************************************************************************/ 57 typedef struct _ export_state32 typedef struct _LXExportState 58 33 { 59 34 struct b32_bundle * pb32; /* Pointer to current bundle. */ … … 62 37 int iOrdinal; /* The current ordinal. */ 63 38 } EXPSTATE, *PEXPSTATE; 39 40 41 /** 42 * relocFind*() state info. 43 * Stored as kRelocEntry::pv1. 44 */ 45 typedef struct _LXRelocState 46 { 47 unsigned long ulSegment; /* The current segment. (0-based) */ 48 unsigned long ulPage; /* The current page. (0-based index) */ 49 char * pchFixupRec; /* The current fixup record. */ 50 unsigned short usSrcOffIdx; /* The current source offset index. (0-based) */ 51 } LXRELOCSTATE, *PLXRELOCSTATE; 64 52 65 53 … … 72 60 73 61 62 /******************************************************************************* 63 * Internal Functions * 64 *******************************************************************************/ 65 inline void memcpyw(char *pch1, const char *pch2, size_t cch); 66 inline void memcpyb(char *pch1, const char *pch2, size_t cch); 67 68 74 69 /** 75 70 * Internal worker which lookup the name corresponding to an ordinal. … … 78 73 * @param pszBuffer. 79 74 */ 80 BOOL kFileLX::queryExportName(int iOrdinal, char *pszBuffer)81 { 82 PUSHORTpus;83 PUCHARpuch;75 KBOOL kFileLX::queryExportName(int iOrdinal, char *pszBuffer) 76 { 77 unsigned short *pus; 78 unsigned char * puch; 84 79 85 80 /* resident name table */ 86 81 if (pe32->e32_restab) 87 82 { 88 puch = ( PUCHAR)pvBase + offLXHdr + pe32->e32_restab;83 puch = (unsigned char *)pvBase + offLXHdr + pe32->e32_restab; 89 84 while (*puch != 0) 90 85 { 91 pus = ( PUSHORT)(puch + 1 + *puch);86 pus = (unsigned short *)(puch + 1 + *puch); 92 87 if (*pus == iOrdinal) 93 88 { … … 103 98 if (pe32->e32_nrestab) 104 99 { 105 puch = ( PUCHAR)pvBase + pe32->e32_nrestab;100 puch = (unsigned char *)pvBase + pe32->e32_nrestab; 106 101 while (*puch != 0) 107 102 { 108 pus = ( PUSHORT)(puch + 1 + *puch);103 pus = (unsigned short *)(puch + 1 + *puch); 109 104 if (*pus == iOrdinal) 110 105 { … … 120 115 } 121 116 117 /** 118 * Converts a FLAT address to an obj:offset address. 119 * @returns The offset into the object. 120 * -1 (0xffffffff) on error. 121 * @param ulAddress Address to map. 122 * @param pulObject Pointer to variable which will receive the object number (0-based). 123 */ 124 unsigned long kFileLX::lxAddressToObjectOffset(unsigned long ulAddress, unsigned long * pulObject) const 125 { 126 int i; 127 128 /* look for a object which contains the given address */ 129 for (i = 0; i < pe32->e32_objcnt; i++) 130 { 131 if ( paObject[i].o32_base <= ulAddress 132 && paObject[i].o32_base + paObject[i].o32_size > ulAddress) 133 { 134 if (pulObject) 135 *pulObject = i; 136 return ulAddress - paObject[i].o32_base; 137 } 138 } 139 140 return ~0UL; /* not found */ 141 } 142 143 144 /** 145 * Converts an sel:off address, where sel is one of the special selectors, 146 * to a obj:off address. 147 * @returns The offset into the object. 148 * -1 (0xffffffff) on error. 149 * @param offObject Offset into the selector described by *pulObject. 150 * @param pulObject IN: Special selector. 151 * OUT: Pointer to variable which will receive the object number (0-based). 152 */ 153 unsigned long kFileLX::lxSpecialSelectorToObjectOffset(unsigned long offObject, unsigned long * pulObject) const 154 { 155 switch (*pulObject) 156 { 157 case kRelocEntry::enmRVASelector: 158 return lxAddressToObjectOffset(offObject + paObject[0].o32_base, pulObject); 159 160 case kRelocEntry::enmVASelector: 161 return lxAddressToObjectOffset(offObject, pulObject); 162 163 default: 164 kASSERT(!"Internal error line"); 165 } 166 167 return ~0UL; 168 } 169 170 171 /** 172 * Validates a FLAT address. 173 * @returns TRUE if valid, FALSE if invalid. 174 * @param ulAddress FLAT address to validate. 175 */ 176 KBOOL kFileLX::lxValidateAddress(unsigned long ulAddress) const 177 { 178 int i; 179 180 /* look for a object which contains the given address */ 181 for (i = 0; i < pe32->e32_objcnt; i++) 182 { 183 if ( paObject[i].o32_base <= ulAddress 184 && paObject[i].o32_base + paObject[i].o32_size > ulAddress) 185 { 186 return TRUE; 187 } 188 } 189 190 return FALSE; 191 } 192 193 194 /** 195 * Validates a object:offset address. 196 * @returns TRUE if valid, FALSE if invalid. 197 * @param ulObject Object number. (0-based) 198 * @param offObject Offset into that object. 199 */ 200 KBOOL kFileLX::lxValidateObjectOffset(unsigned long ulObject, unsigned long offObject) const 201 { 202 return pe32->e32_objcnt > ulObject && offObject < paObject[ulObject].o32_size; 203 } 204 205 206 207 /** 208 * Gets the module name corresponding to the given ordinal. 209 * @returns Pointer to sz of the modulename. The caller is responsible for freeing it. 210 * NULL if invalid ordinal. 211 * @param ordModule Ordinal number of the module name. (1-based) 212 */ 213 char *kFileLX::lxGetImportModuleName(unsigned long ordModule) const 214 { 215 if (pe32->e32_impmodcnt < ordModule) 216 return NULL; 217 218 char *pch = (char*)pe32 + pe32->e32_impmod; 219 while (--ordModule) 220 pch += *pch + 1; 221 222 if (!*pch) 223 return NULL; 224 225 /* Copy the module name. */ 226 char *psz = new char[*pch + 1]; 227 strncpy(psz, pch + 1, *pch); 228 psz[*pch] = '\0'; 229 return psz; 230 } 231 232 233 /** 234 * Gets the proc name at the given offset. 235 * @returns Pointer to sz of the proc name. The caller is responsible for freeing it. 236 * NULL if invalid offset. 237 * @param offProc Offset of the proc name. 238 */ 239 char *kFileLX::lxGetImportProcName(unsigned long offProc) const 240 { 241 char *pch = (char*)pe32 + pe32->e32_impproc + offProc; 242 if (!*pch) 243 return NULL; 244 245 /* Copy the proc name. */ 246 char *psz = new char[*pch + 1]; 247 strncpy(psz, pch + 1, *pch); 248 psz[*pch] = '\0'; 249 return psz; 250 } 251 122 252 123 253 … … 126 256 * @param pszFilename LX executable image name. 127 257 */ 128 kFileLX::kFileLX(const char *pszFilename) throw (int)129 :pvBase(NULL)258 kFileLX::kFileLX(const char *pszFilename) : 259 kFileFormatBase(NULL), pvBase(NULL) 130 260 { 131 261 struct exe_hdr * pehdr; 132 262 133 263 /* create filemapping */ 134 pvBase = kFile::readFile(pszFilename); 135 if (pvBase == NULL) 136 throw(1); 137 264 pvBase = kFile::mapFile(pszFilename); 138 265 pehdr = (struct exe_hdr*)pvBase; 139 266 if (pehdr->e_magic == EMAGIC) … … 143 270 144 271 pe32 = (struct e32_exe*)((char*)pvBase + offLXHdr); 145 if (*( PUSHORT)pe32 != E32MAGIC)146 { 147 free(pvBase);272 if (*(unsigned short *)pe32 != E32MAGIC) 273 { 274 kFile::mapFree(pvBase); 148 275 pvBase = NULL; 149 throw( 2);276 throw(kError(kError::INVALID_EXE_SIGNATURE)); 150 277 } 151 278 152 279 paObject = pe32->e32_objtab && pe32->e32_objcnt 153 ? (struct o32_obj *)((char*)pvBase + pe32->e32_objtab + offLXHdr) : NULL;280 ? (struct o32_obj *)((char *)pe32 + pe32->e32_objtab) : NULL; 154 281 paMap = pe32->e32_objmap 155 ? (struct o32_map*)((char*)pvBase + pe32->e32_objmap + offLXHdr) : NULL; 282 ? (struct o32_map *)((char *)pe32 + pe32->e32_objmap) : NULL; 283 paulFixupPageTable = pe32->e32_fpagetab 284 ? (unsigned long *)((char *)pe32 + pe32->e32_fpagetab) : NULL; 285 pchFixupRecs = pe32->e32_frectab 286 ? (char *)((char *)pe32 + pe32->e32_frectab) : NULL; 156 287 } 157 288 … … 161 292 * @param pFile Pointer to opened LX file. 162 293 */ 163 kFileLX::kFileLX(kFile *pFile) throw (int)164 :pvBase(NULL)294 kFileLX::kFileLX(kFile *pFile) : 295 kFileFormatBase(pFile), pvBase(NULL) 165 296 { 166 297 struct exe_hdr * pehdr; 167 298 168 299 /* create filemapping */ 169 pvBase = pFile->readFile(); 170 if (pvBase == NULL) 171 throw(1); 300 pFile->setThrowOnErrors(); 301 pvBase = pFile->mapFile(); 172 302 173 303 pehdr = (struct exe_hdr*)pvBase; … … 178 308 179 309 pe32 = (struct e32_exe*)((char*)pvBase + offLXHdr); 180 if (*( PUSHORT)pe32 != E32MAGIC)181 { 182 free(pvBase);310 if (*(unsigned short *)pe32 != E32MAGIC) 311 { 312 kFile::mapFree(pvBase); 183 313 pvBase = NULL; 184 throw( 2);314 throw(kError(kError::INVALID_EXE_SIGNATURE)); 185 315 } 186 316 187 317 paObject = pe32->e32_objtab && pe32->e32_objcnt 188 ? (struct o32_obj *)((char*)pvBase + pe32->e32_objtab + offLXHdr) : NULL;318 ? (struct o32_obj *)((char *)pe32 + pe32->e32_objtab) : NULL; 189 319 paMap = pe32->e32_objmap 190 ? (struct o32_map*)((char*)pvBase + pe32->e32_objmap + offLXHdr) : NULL; 320 ? (struct o32_map *)((char *)pe32 + pe32->e32_objmap) : NULL; 321 paulFixupPageTable = pe32->e32_fpagetab 322 ? (unsigned long *)((char *)pe32 + pe32->e32_fpagetab) : NULL; 323 pchFixupRecs = pe32->e32_frectab 324 ? (char *)((char *)pe32 + pe32->e32_frectab) : NULL; 191 325 } 192 326 … … 199 333 { 200 334 if (pvBase != NULL) 201 free(pvBase);335 kFile::mapFree(pvBase); 202 336 pvBase = NULL; 203 337 } … … 211 345 * @param cchBuffer Size of the buffer (defaults to 260 chars). 212 346 */ 213 BOOL kFileLX::moduleGetName(char *pszBuffer, int cchBuffer/*= 260*/)347 KBOOL kFileLX::moduleGetName(char *pszBuffer, int cchBuffer/*= 260*/) 214 348 { 215 349 /* The module name is the 0 ordinal entry in resident name table */ 216 assert(cchBuffer >= 255);350 kASSERT(cchBuffer >= 255); 217 351 return queryExportName(0, pszBuffer); 218 352 } … … 224 358 * @param pExport Pointer to export structure. 225 359 */ 226 BOOL kFileLX::exportFindFirst(kExportEntry *pExport)360 KBOOL kFileLX::exportFindFirst(kExportEntry *pExport) 227 361 { 228 362 struct b32_bundle * pBundle = (struct b32_bundle*)((char*)pvBase + pe32->e32_enttab + offLXHdr); … … 274 408 break; 275 409 default: 276 assert(!"ARG!!!! invalid bundle type!");410 kASSERT(!"ARG!!!! invalid bundle type!"); 277 411 } 278 412 279 413 /* store status - current export entry */ 280 PEXPSTATE pExpState = (PEXPSTATE)malloc(sizeof(EXPSTATE));414 PEXPSTATE pExpState = new EXPSTATE; 281 415 pExport->pv = pExpState; 282 416 pExpState->pb32 = pBundle; … … 300 434 * @param pExport Pointer to export structure. 301 435 */ 302 BOOL kFileLX::exportFindNext(kExportEntry *pExport)436 KBOOL kFileLX::exportFindNext(kExportEntry *pExport) 303 437 { 304 438 static int acbEntry[] = … … 357 491 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) + 358 492 pExpState->pb32->b32_cnt * acbEntry[pExpState->pb32->b32_type & ~TYPEINFO]); 359 pExpState->iOrdinal++;360 493 while (pExpState->pb32->b32_cnt != 0) 361 494 { 362 495 /* skip empty bundles */ 363 if(pExpState->pb32->b32_cnt != 0 && pExpState->pb32->b32_type == EMPTY)496 while (pExpState->pb32->b32_cnt != 0 && pExpState->pb32->b32_type == EMPTY) 364 497 { 365 498 pExpState->iOrdinal += pExpState->pb32->b32_cnt; 366 499 pExpState->pb32 = (struct b32_bundle*)((char*)pExpState->pb32 + 2); 367 continue;368 500 } 369 501 370 502 /* FIXME forwarders are not implemented so we'll skip them too. */ 371 if(pExpState->pb32->b32_cnt != 0 && (pExpState->pb32->b32_type & ~TYPEINFO) == ENTRYFWD)503 while (pExpState->pb32->b32_cnt != 0 && (pExpState->pb32->b32_type & ~TYPEINFO) == ENTRYFWD) 372 504 { 373 505 pExpState->iOrdinal += pExpState->pb32->b32_cnt; 374 506 pExpState->pb32 = (struct b32_bundle*)((char*)(pExpState->pb32 + 1) + pExpState->pb32->b32_cnt * 7); 375 continue;376 507 } 377 508 … … 403 534 pExport->ulOffset = pExpState->pe32->e32_variant.e32_callgate.offset; 404 535 break; 405 406 536 default: 407 assert(!"ARG!!!! invalid bundle type!");537 kASSERT(!"ARG!!!! invalid bundle type!"); 408 538 } 409 539 … … 430 560 void kFileLX::exportFindClose(kExportEntry *pExport) 431 561 { 432 free(pExport->pv);562 delete pExport->pv; 433 563 pExport->pv = NULL; 434 564 return; … … 443 573 * @remark stub 444 574 */ 445 BOOL kFileLX::exportLookup(unsigned long ulOrdinal, kExportEntry *pExport)446 { 447 assert(!"not implemented.");575 KBOOL kFileLX::exportLookup(unsigned long ulOrdinal, kExportEntry *pExport) 576 { 577 kASSERT(!"not implemented."); 448 578 ulOrdinal = ulOrdinal; 449 579 pExport = pExport; … … 458 588 * @remark stub 459 589 */ 460 BOOL kFileLX::exportLookup(const char * pszName, kExportEntry *pExport)461 { 462 assert(!"not implemented.");590 KBOOL kFileLX::exportLookup(const char * pszName, kExportEntry *pExport) 591 { 592 kASSERT(!"not implemented."); 463 593 pszName = pszName; 464 594 pExport = pExport; … … 490 620 } 491 621 492 #if 0 493 494 /** @cat Get and put page methods. (the first ones are generic) */ 495 BOOL kFileLX::getPage(char *pachPage, ULONG ulAddress) 622 623 /** 624 * Get a code, data or resource page from the file. 625 * @returns 0 on success. kError number on error. 626 * @param pachPage Pointer to a buffer of the size of a page which 627 * will receive the page data on the specified address. 628 * @param ulAddress Page address. This must be page aligned. 629 */ 630 int kFileLX::pageGet(char *pachPage, unsigned long ulAddress) const 496 631 { 497 632 int iObj; 498 633 499 634 for (iObj = 0; iObj < pe32->e32_objcnt; iObj++) 500 if ( paObject[iObj].o32_base >ulAddress635 if ( paObject[iObj].o32_base <= ulAddress 501 636 && paObject[iObj].o32_base + paObject[iObj].o32_size > ulAddress 502 637 ) 503 return getPage(pachPage, iObj, ulAddress - paObject[iObj].o32_base); 504 505 return FALSE; 506 } 507 508 BOOL kFileLX::getPage(char *pachPage, int iObject, int offObject) 509 { 510 offObject &= ~(PAGESIZE - 1); 511 if ( iObject >= pe32->e32_objcnt 512 && offObject >= paObject[iObject].o32_size 513 ) 514 return FALSE; 638 return pageGet(pachPage, iObj, ulAddress - paObject[iObj].o32_base); 639 640 return kError::INVALID_ADDRESS; 641 } 642 643 /** 644 * Get a code, data or resource page from the file. 645 * @returns 0 on success. kError number on error. 646 * @param pachPage Pointer to a buffer of the size of a page which 647 * will receive the page data on the specified address. 648 * @param iSegment Segment number. (0-based) 649 * @param offObject Offset into the object. This must be page aligned. 650 * @remark Object = Section. 651 */ 652 int kFileLX::pageGet(char *pachPage, int iSegment, int offObject) const 653 { 654 /* 655 * Validation. 656 */ 657 if (offObject & (pe32->e32_pagesize - 1)) 658 return kError::BAD_ALIGNMENT; 659 if (iSegment >= pe32->e32_objcnt) 660 return kError::INVALID_SEGMENT_NUMBER; 661 if (offObject >= paObject[iSegment].o32_size) 662 return kError::INVALID_OFFSET; 515 663 516 664 /* 517 665 * Is there a pagemap entry for the requested page? 518 666 */ 519 if ((offObject >> PAGESHIFT) < paObject[iObject].o32_mapsize)667 if ((offObject / pe32->e32_pagesize) < paObject[iSegment].o32_mapsize) 520 668 { /* yes */ 521 int iPage = (offObject >> PAGESIZE) + paObject[iObject].o32_pagemap - 1;669 int iPage = (offObject / pe32->e32_pagesize) + paObject[iSegment].o32_pagemap - 1; 522 670 char * pchPageData = (char*)((paMap[iPage].o32_pagedataoffset << pe32->e32_pageshift) + pe32->e32_datapage + (char*)pvBase); 523 671 524 if (pchPageData)672 switch (paMap[iPage].o32_pageflags) 525 673 { 674 case VALID: 675 memcpy(pachPage, pchPageData, paMap[iPage].o32_pagesize); 676 if (paMap[iPage].o32_pagesize < pe32->e32_pagesize) 677 memset(pachPage + paMap[iPage].o32_pagesize, 0, pe32->e32_pagesize - paMap[iPage].o32_pagesize); 678 break; 679 680 case ITERDATA: 681 { 682 char achTempBuffer[0x1004]; 683 memcpy(achTempBuffer, pchPageData, paMap[iPage].o32_pagesize); 684 memset(achTempBuffer + paMap[iPage].o32_pagesize, 0, 4); 685 return kFileLX::expandPage1(pachPage, pe32->e32_pagesize, achTempBuffer, paMap[iPage].o32_pagesize); 686 } 687 688 case INVALID: 689 return kError::INVALID_PAGE; 690 691 case ZEROED: 692 memset(pachPage, 0, pe32->e32_pagesize); 693 break; 694 695 case ITERDATA2: 696 { 697 char achTempBuffer[0x1004]; 698 memcpy(achTempBuffer, pchPageData, paMap[iPage].o32_pagesize); 699 memset(achTempBuffer + paMap[iPage].o32_pagesize, 0, 4); 700 return kFileLX::expandPage2(pachPage, pe32->e32_pagesize, achTempBuffer, paMap[iPage].o32_pagesize); 701 } 702 703 case RANGE: 704 default: 705 return kError::BAD_EXE_FORMAT; 526 706 } 527 707 528 708 } 529 709 else 530 { /* no, so it's a zero page */ 531 memset(pachPage, 0, PAGESIZE); 532 } 533 534 return FALSE; 535 } 536 537 BOOL kFileLX::putPage(const char *pachPage, ULONG ulAddress) 538 { 539 return FALSE; 540 } 541 542 BOOL kFileLX::putPage(const char *pachPage, int iObject, int offObject) 543 { 544 return FALSE; 545 } 546 547 BOOL kFileLX::getPageLX(char *pachPage, int iObject, int iPage) 548 { 549 return FALSE; 550 } 551 552 BOOL kFileLX::getPageLX(char *pachPage, int iPage) 553 { 554 return FALSE; 555 } 556 557 BOOL kFileLX::putPageLX(const char *pachPage, int iObject, int iPage) 558 { 559 return FALSE; 560 } 561 562 BOOL kFileLX::putPageLX(const char *pachPage, int iPage) 563 { 564 return FALSE; 710 { /* no, so it's a zerofilled page */ 711 memset(pachPage, 0, pe32->e32_pagesize); 712 } 713 714 return 0; 715 } 716 717 718 /** 719 * Updates or adds a code, data, or resource page to the file. 720 * @returns 0 on success. kError number on error. 721 * @param pachPage Pointer to a buffer of the size of a page which 722 * holds the page data. 723 * @param ulAddress Page address. This must be page aligned. 724 */ 725 int kFileLX::pagePut(const char *pachPage, unsigned long ulAddress) 726 { 727 int iObj; 728 729 for (iObj = 0; iObj < pe32->e32_objcnt; iObj++) 730 if ( paObject[iObj].o32_base <= ulAddress 731 && paObject[iObj].o32_base + paObject[iObj].o32_size > ulAddress 732 ) 733 return pagePut(pachPage, iObj, ulAddress - paObject[iObj].o32_base); 734 735 return kError::INVALID_ADDRESS; 736 } 737 738 739 /** 740 * Updates or adds a code, data, or resource page to the file. 741 * @returns 0 on success. kError number on error. 742 * @param pachPage Pointer to a buffer of the size of a page which 743 * holds the page data. 744 * @param iSegment Segment number. (0-based) 745 * @param offObject Offset into the object. This must be page aligned. 746 */ 747 int kFileLX::pagePut(const char *pachPage, int iSegment, int offObject) 748 { 749 /* 750 * Validation. 751 */ 752 if (offObject & (pe32->e32_pagesize - 1)) 753 return kError::BAD_ALIGNMENT; 754 if (iSegment >= pe32->e32_objcnt) 755 return kError::INVALID_SEGMENT_NUMBER; 756 if (offObject >= paObject[iSegment].o32_size) 757 return kError::INVALID_OFFSET; 758 759 /* 760 * Is there a pagemap entry for the page? 761 */ 762 if ((offObject / pe32->e32_pagesize) < paObject[iSegment].o32_mapsize) 763 { /* yes */ 764 int iPage = (offObject / pe32->e32_pagesize) + paObject[iSegment].o32_pagemap - 1; 765 char * pchPageData = (char*)((paMap[iPage].o32_pagedataoffset << pe32->e32_pageshift) + pe32->e32_datapage + (char*)pvBase); 766 const char *pchPageToWrite = NULL; 767 int cchPageToWrite = 0; 768 long offPageToWrite = (paMap[iPage].o32_pagedataoffset << pe32->e32_pageshift) + pe32->e32_datapage; 769 770 switch (paMap[iPage].o32_pageflags) 771 { 772 case VALID: 773 pchPageToWrite = pachPage; 774 cchPageToWrite = 0x1000; 775 if (paMap[iPage].o32_pagesize != 0x1000) 776 { 777 /* 778 * Check that everything after pagesize is zero. 779 */ 780 for (const char *pch = &pachPage[paMap[iPage].o32_pagesize]; pch < &pachPage[0x1000]; pch++) 781 if (*pch) 782 return kError::NOT_SUPPORTED; 783 cchPageToWrite = paMap[iPage].o32_pagesize; 784 } 785 break; 786 787 case ITERDATA: 788 case ITERDATA2: 789 { 790 char * pchCompressedPage = (char*)alloca(pe32->e32_pagesize+4); 791 792 /* remove spaces at the end of the page. */ 793 int cchPage = pe32->e32_pagesize; 794 while (pachPage[cchPage-1] == '\0') 795 cchPage--; 796 797 /* call the compression function */ 798 if (paMap[iPage].o32_pageflags == ITERDATA) 799 cchPageToWrite = kFileLX::compressPage1(pchCompressedPage, pachPage, cchPage); 800 else 801 cchPageToWrite = kFileLX::compressPage2(pchCompressedPage, pachPage, cchPage); 802 //if (cchPageToWrite != paMap[iPage].o32_pagesize) 803 // printf("compressPageX returned %d (%x) previous size %d (%x)\n", cchPageToWrite, cchPageToWrite, paMap[iPage].o32_pagesize, paMap[iPage].o32_pagesize); 804 if (cchPageToWrite < 0) 805 return kError::NOT_SUPPORTED; 806 #if 0 807 int cbLeft = KMIN(2, paMap[iPage].o32_pagesize - cchPageToWrite); 808 if (cbLeft > 0) 809 { 810 memset(&pchCompressedPage[cchPageToWrite], 0, cbLeft); 811 cchPageToWrite += cbLeft; 812 } 813 #else 814 kASSERT(paMap[iPage].o32_pagesize - cchPageToWrite >= 0); 815 memset(&pchCompressedPage[cchPageToWrite], 0, paMap[iPage].o32_pagesize - cchPageToWrite); 816 cchPageToWrite = paMap[iPage].o32_pagesize; 817 #endif 818 pchPageToWrite = pchCompressedPage; 819 break; 820 } 821 822 case ZEROED: 823 { 824 /* 825 * If the passed in page is not a zero page we'll fail. 826 */ 827 for (unsigned long * pul = (unsigned long *)pachPage; (char*)pul < &pachPage[0x1000]; pul++) 828 if (*pul) 829 return kError::NOT_SUPPORTED; 830 return 0; 831 } 832 833 case INVALID: 834 return kError::INVALID_PAGE; 835 836 case RANGE: 837 default: 838 return kError::BAD_EXE_FORMAT; 839 } 840 841 /* 842 * Write stuff to file. 843 */ 844 pFile->setFailOnErrors(); 845 return pFile->writeAt((void*)pchPageToWrite, cchPageToWrite, offPageToWrite); 846 } 847 else 848 { /* 849 * No, it's a zerofilled page 850 * If the passed in page is not a zero page we'll fail. 851 */ 852 for (unsigned long * pul = (unsigned long *)pachPage; (char*)pul < &pachPage[0x1000]; pul++) 853 if (*pul) 854 return kError::NOT_SUPPORTED; 855 } 856 857 return 0; 858 } 859 860 861 /** 862 * Get pagesize for the file. 863 * @returns Pagesize in bytes. 864 */ 865 int kFileLX::pageGetPageSize() const 866 { 867 return pe32->e32_pagesize; 565 868 } 566 869 … … 569 872 * Expands a page compressed with the old exepack method introduced with OS/2 2.0. 570 873 * (/EXEPACK or just /EXEPACK) 571 * @returns Successindicator.572 * @param pachPage Pointer to output page. size: PAGESIZE874 * @returns 0 on success. kError error code on error. 875 * @param pachPage Pointer to output page. size: cchPage 573 876 * Upon successful return this will contain the expanded page data. 877 * @param cchPage Page size. 574 878 * @param pachSrcPage Pointer to source data. size: cchSrcPage. 575 879 * This data should be compressed with EXEPACK:2! 880 * @param cchSrcPage Size of compressed data. 576 881 * @sketch Have no good idea right now. 577 882 * @status Completely implemented. … … 579 884 * @remark 580 885 */ 581 BOOL kFileLX::expandPage1(char *pachPage, const char * pachSrcPage, int cchSrcPage)886 int kFileLX::expandPage1(char *pachPage, int cchPage, const char * pachSrcPage, int cchSrcPage) 582 887 { 583 888 struct LX_Iter *pIter = (struct LX_Iter *)pachSrcPage; … … 585 890 586 891 /* Validate size of data. */ 587 if (cchSrcPage >= PAGESIZE- 2)588 return FALSE;892 if (cchSrcPage >= cchPage - 2) 893 return kError::BAD_ITERPAGE; 589 894 590 895 /* 591 896 * Expand the page. 592 897 */ 593 while (pIter->LX_nIter )898 while (pIter->LX_nIter && cchSrcPage > 0) 594 899 { 595 900 /* Check if we're out of bound. */ 596 if ( pachPage - pachDes Page + pIter->LX_nIter * pIter->LX_nBytes > PAGESIZE901 if ( pachPage - pachDestPage + pIter->LX_nIter * pIter->LX_nBytes > cchPage 597 902 || cchSrcPage <= 0) 598 return FALSE; 903 return kError::BAD_ITERPAGE; 904 905 //if (pIter->LX_nIter == 1) 906 // printf("get 0x%03x stored %3d bytes\n", pachPage - pachDestPage, pIter->LX_nBytes); 907 //else 908 // printf("get 0x%03x %3d iterations %3d bytes\n", pachPage - pachDestPage, pIter->LX_nIter, pIter->LX_nBytes); 599 909 600 910 if (pIter->LX_nBytes == 1) 601 911 { /* one databyte */ 602 memset(pachPage, &pIter->LX_Iterdata, pIter->LX_nIter);603 p chPage += pIter->LX_nIter;604 cchSrcPage -= pIter->LX_nIter + 4;912 memset(pachPage, pIter->LX_Iterdata, pIter->LX_nIter); 913 pachPage += pIter->LX_nIter; 914 cchSrcPage -= 4 + 1; 605 915 pIter++; 606 916 } 607 917 else 608 918 { 609 for (int i = 0; i < pIter->LX_nIter; i++, pachPage += pIter->LX_nBytes)919 for (int i = pIter->LX_nIter; i > 0; i--, pachPage += pIter->LX_nBytes) 610 920 memcpy(pachPage, &pIter->LX_Iterdata, pIter->LX_nBytes); 611 921 cchSrcPage -= 4 + pIter->LX_nBytes; 612 pIter = (pIter)((char*)pIter 4 + pIter->LX_nBytes); 613 } 614 } 615 return TRUE; 616 #if 0 617 /* example code */ 618 int off; 619 struct LX_Iter *pIter; 620 char * pch = pvPage; /* Current position on page */ 621 622 off = pe32->e32_datapage + (pObjMap->o32_pagedataoffset << pe32->e32_pageshift); 623 if (pObjMap->o32_pagesize && (off + pObjMap->o32_pagesize - 1) >= cbFile) 624 { 625 fprintf(stderr, "Error: Page resides outside of the file.\n"); 626 return 1; 627 } 628 pIter = (struct LX_Iter *)((char*)pvFile + off); 629 630 /* expand page */ 631 while (pIter->LX_nIter > 0) 632 { 633 if (pch + (pIter->LX_nBytes * pIter->LX_nIter) > (char*)pvPage + OBJPAGELEN) 634 { 635 fprintf(stderr, "Error: Iterated page expands to more than a page!\n"); 636 return 1; 637 } 638 639 if (pIter->LX_nBytes == 1) 640 { 641 memset(pch, pIter->LX_Iterdata, pIter->LX_nIter); 642 pch += pIter->LX_nIter; 643 pIter++; 644 } 645 else 646 { 647 int i; 648 for (i = 0; i < pIter->LX_nIter; i++, pch += pIter->LX_nBytes) 649 memcpy(pch, &pIter->LX_Iterdata, pIter->LX_nBytes); 650 #if 1 /* curious */ 651 if (pIter->LX_nBytes > 2) fprintf(stdout, "pIter->LX_nBytes = %\n", pIter->LX_nBytes); 652 #endif 653 654 pIter = (struct LX_Iter*)((char*)pIter + 4 + pIter->LX_nBytes); 655 } 656 } 657 658 return FALSE; 659 #endif 660 } 922 pIter = (struct LX_Iter *)((char*)pIter + 4 + pIter->LX_nBytes); 923 } 924 } 925 926 /* 927 * Zero remaining part of the page. 928 */ 929 if (pachPage - pachDestPage < cchPage) 930 memset(pachPage, 0, cchPage - (pachPage - pachDestPage)); 931 932 return 0; 933 } 661 934 662 935 … … 664 937 * Expands a page compressed with the exepack method introduced with OS/2 Warp 3.0. 665 938 * (/EXEPACK:2) 666 * @returns Successindicator.939 * @returns 0 on success. kError error code on error. 667 940 * @param pachPage Pointer to output page. size: PAGESIZE 668 941 * Upon successful return this will contain the expanded page data. 942 * @param cchPage Page size. 669 943 * @param pachSrcPage Pointer to source data. size: cchSrcPage. 670 944 * This data should be compressed with EXEPACK:2! 945 * @param cchSrcPage Size of compressed data. 671 946 * @sketch Have no good idea right now. 672 * @status Stub.947 * @status Completely implemented and tested. 673 948 * @author knut st. osmundsen (knut.stange.osmundsen@mynd.no) 949 * @remark tested. 950 */ 951 int kFileLX::expandPage2(char *pachPage, int cchPage, const char * pachSrcPage, int cchSrcPage) 952 { 953 char * pachDestPage = pachPage; /* Store the pointer for boundrary checking. */ 954 955 while (cchSrcPage > 0) 956 { 957 /* 958 * Bit 0 and 1 is the encoding type. 959 */ 960 switch (*pachSrcPage & 0x03) 961 { 962 /* 963 * 964 * 0 1 2 3 4 5 6 7 965 * type | | 966 * ---------------- 967 * cch <cch bytes of data> 968 * 969 * Bits 2-7 is, if not zero, the length of an uncompressed run 970 * starting at the following byte. 971 * 972 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 973 * type | | | | | | 974 * ---------------- ---------------------- ----------------------- 975 * zero cch char to multiply 976 * 977 * If the bits are zero, the following two bytes describes a 978 * 1 byte interation run. First byte is count, second is the byte to copy. 979 * A count of zero is means end of data, and we simply stops. In that case 980 * the rest of the data should be zero. 981 */ 982 case 0: 983 { 984 if (*pachSrcPage) 985 { 986 int cch = *pachSrcPage >> 2; 987 if (cchPage < cch || cchSrcPage < cch + 1) 988 return kError::BAD_COMPESSED_PAGE; 989 memcpy(pachPage, pachSrcPage+1, cch); 990 pachPage += cch, cchPage -= cch; 991 pachSrcPage += cch + 1, cchSrcPage -= cch + 1; 992 break; 993 } 994 if (cchSrcPage < 2) 995 return kError::BAD_COMPESSED_PAGE; 996 int cch = pachSrcPage[1]; 997 if (cch) 998 { 999 if (cchSrcPage < 3 || cchPage < cch) 1000 return kError::BAD_COMPESSED_PAGE; 1001 memset(pachPage, pachSrcPage[2], cch); 1002 pachPage += cch, cchPage -= cch; 1003 pachSrcPage += 3, cchSrcPage -= 3; 1004 break; 1005 } 1006 goto endloop; 1007 } 1008 1009 1010 /* 1011 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1012 * type | | | | | | 1013 * ---- ------- ------------------------- 1014 * cch1 cch2 - 3 offset <cch1 bytes of data> 1015 * 1016 * Two bytes layed out as described above, followed by cch1 bytes of data to be copied. 1017 * The cch2(+3) and offset describes an amount of data to be copied from the expanded 1018 * data relative to the current position. The data copied as you would expect it to be. 1019 */ 1020 case 1: 1021 { 1022 if (cchSrcPage < 2) 1023 return kError::BAD_COMPESSED_PAGE; 1024 int off = *(unsigned short*)pachSrcPage >> 7; 1025 int cch1 = *pachSrcPage >> 2 & 3; 1026 int cch2 = (*pachSrcPage >> 4 & 7) + 3; 1027 pachSrcPage += 2, cchSrcPage -= 2; 1028 if (cchSrcPage < cch1 || cchPage < cch1 + cch2 || pachPage + cch1 - off < pachDestPage) 1029 return kError::BAD_COMPESSED_PAGE; 1030 memcpy(pachPage, pachSrcPage, cch1); 1031 pachPage += cch1, cchPage -= cch1; 1032 pachSrcPage += cch1, cchSrcPage -= cch1; 1033 memcpyb(pachPage, pachPage - off, cch2); //memmove doesn't do a good job here for some stupid reason. 1034 pachPage += cch2, cchPage -= cch2; 1035 break; 1036 } 1037 1038 1039 /* 1040 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 1041 * type | | | | 1042 * ---- ---------------------------------- 1043 * cch-3 offset 1044 * 1045 * Two bytes layed out as described above. 1046 * The cch(+3) and offset describes an amount of data to be copied from the expanded 1047 * data relative to the current position. 1048 * 1049 * If offset == 1 the data is not copied as expected, but in the memcpyw manner. 1050 */ 1051 case 2: 1052 { 1053 if (cchSrcPage < 2) 1054 return kError::BAD_COMPESSED_PAGE; 1055 int off = *(unsigned short*)pachSrcPage >> 4; 1056 int cch = (*pachSrcPage >> 2 & 3) + 3; 1057 pachSrcPage += 2, cchSrcPage -= 2; 1058 if (cchPage < cch || pachPage - off < pachDestPage) 1059 return kError::BAD_COMPESSED_PAGE; 1060 memcpyw(pachPage, pachPage - off, cch); 1061 pachPage += cch, cchPage -= cch; 1062 break; 1063 } 1064 1065 1066 /* 1067 * 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 1068 * type | | | | | | 1069 * ---------- ---------------- ---------------------------------- 1070 * cch1 cch2 offset <cch1 bytes of data> 1071 * 1072 * Three bytes layed out as described above, followed by cch1 bytes of data to be copied. 1073 * The cch2 and offset describes an amount of data to be copied from the expanded 1074 * data relative to the current position. 1075 * 1076 * If offset == 1 the data is not copied as expected, but in the memcpyw manner. 1077 */ 1078 case 3: 1079 { 1080 if (cchSrcPage < 3) 1081 return kError::BAD_COMPESSED_PAGE; 1082 int cch1 = *pachSrcPage >> 2 & 0x000f; 1083 int cch2 = *(unsigned short*)pachSrcPage >> 6 & 0x003f; 1084 int off = *(unsigned short*)(pachSrcPage+1) >> 4; 1085 pachSrcPage += 3, cchSrcPage -= 3; 1086 if (cchSrcPage < cch1 || cchPage < cch1 + cch2 || pachPage - off + cch1 < pachDestPage) 1087 return kError::BAD_COMPESSED_PAGE; 1088 memcpy(pachPage, pachSrcPage, cch1); 1089 pachPage += cch1, cchPage -= cch1; 1090 pachSrcPage += cch1, cchSrcPage -= cch1; 1091 memcpyw(pachPage, pachPage - off, cch2); 1092 pachPage += cch2, cchPage -= cch2; 1093 break; 1094 } 1095 } 1096 } 1097 1098 endloop:; 1099 1100 1101 /* 1102 * Zero the rest of the page. 1103 */ 1104 if (cchPage > 0) 1105 memset(pachPage, 0, cchPage); 1106 1107 return 0; 1108 } 1109 1110 1111 /** 1112 * This is a special memcpy for expandPage2 which performs a word based copy. 1113 * The difference between this, memmove and memcpy is that we'll allways read words. 1114 * @param pch1 Target pointer. 1115 * @param pch2 Source pointer. 1116 * @param cch size of memory block to copy from pch2 to pch1. 1117 * @author knut st. osmundsen (kosmunds@csc.com) 674 1118 * @remark 675 1119 */ 676 BOOL kFileLX::expandPage2(char *pachPage, const char * pachSrcPage, int cchSrcPage) 677 { 678 NOREF(pachPage); 679 NOREF(pachSrcPage); 680 NOREF(cchSrcPage); 681 return FALSE; 682 } 1120 inline void memcpyw(char *pch1, const char *pch2, size_t cch) 1121 { 1122 /* 1123 * Use memcpy if possible. 1124 */ 1125 if ((pch2 > pch1 ? pch2 - pch1 : pch1 - pch2) >= 4) 1126 { 1127 memcpy(pch1, pch2, cch); /* BUGBUG! ASSUMES that memcpy move NO more than 4 bytes at the time! */ 1128 return; 1129 } 1130 1131 /* 1132 * Difference is less than 3 bytes. 1133 */ 1134 if (cch & 1) 1135 *pch1++ = *pch2++; 1136 1137 #if 0 //haven't found anyone yet. (not a big surprize!) 1138 /* Looking for a very special case! I wanna see if my theory is right. */ 1139 if ((pch2 > pch1 ? pch2 - pch1 : pch1 - pch2) <= 1) 1140 INT3(); 1141 #endif 1142 1143 for (cch >>= 1; cch > 0; cch--, pch1 += 2, pch2 += 2) 1144 *(unsigned short *)pch1 = *(unsigned short *)pch2; 1145 } 1146 1147 1148 /** 1149 * This is a special memcpy for expandPage2 which performs a memmove operation. 1150 * The difference between this and memmove is that this one works. 1151 * 1152 * @param pch1 Target pointer. 1153 * @param pch2 Source pointer. 1154 * @param cch size of memory block to copy from pch2 to pch1. 1155 * @author knut st. osmundsen (kosmunds@csc.com) 1156 */ 1157 inline void memcpyb(char *pch1, const char *pch2, size_t cch) 1158 { 1159 /* 1160 * Use memcpy if possible. 1161 */ 1162 if ((pch2 > pch1 ? pch2 - pch1 : pch1 - pch2) >= 4) 1163 { 1164 memcpy(pch1, pch2, cch); /* BUGBUG! ASSUMES that memcpy move NO more than 4 bytes at the time! */ 1165 return; 1166 } 1167 1168 /* 1169 * Difference is less than 3 bytes. 1170 */ 1171 while(cch--) 1172 *pch1++ = *pch2++; 1173 } 1174 683 1175 684 1176 … … 689 1181 * PAGESIZE if failed to compress the page. 690 1182 * -1 on error. 691 * @param pachPage Pointer to output buffer. size: PAGESIZE.1183 * @param pachPage Pointer to output buffer. size: cchSrcPage. 692 1184 * This will hold the compressed page data upon return. 693 * @param pachSrcPage Pointer to page to compress. size: PAGESIZE. 1185 * @param pachSrcPage Pointer to page to compress. size: cchSrcPage. 1186 * @param cchSrcPage Page size. 694 1187 * @sketch 695 1188 * @status stub. … … 697 1190 * @remark Not implemented. 698 1191 */ 699 int kFileLX::compressPage1(char *pachPage, const char * pachSrcPage) 700 { 701 NOREF(pachPage); 702 NOREF(pachSrcPage); 1192 1193 int compressPage1Search(const char *pch, const char **ppchSearch, const char *pchEnd, int *pcIterations) 1194 { 1195 int cch; 1196 const char* pchStart = pch; 1197 const char* pchSearch = *ppchSearch; 1198 1199 // if (pch < pchSearch) 1200 // pch = pchSearch - 1; 1201 while ((cch = pchSearch - pch) > 0) 1202 { 1203 int cchLeft = pchEnd - pchSearch; 1204 if (cchLeft < cch) 1205 {pch++; continue;} 1206 int cIter = 1; 1207 const char *pchMatch = pchSearch; 1208 while (pchMatch < pchEnd && !memcmp(pchMatch, pch, cch)) 1209 pchMatch += cch, cIter++; 1210 1211 int cchCost = pchStart < pch ? cch + 8 : cch + 4; 1212 if (cIter == 1 || cIter * cch < cchCost) 1213 {pch++; continue;} 1214 *ppchSearch = pch; 1215 *pcIterations = cIter; 1216 return cch; 1217 } 1218 703 1219 return -1; 704 1220 } 1221 1222 int compressPage1SearchStored(const char *pchStart, const char *pchEnd, int *pcchRun) 1223 { 1224 if (pchStart+1 == pchEnd) 1225 return FALSE; 1226 1227 const char *pch = pchStart; 1228 char ch = *pch++; 1229 while (pch < pchEnd) 1230 if (*pch++ != ch) 1231 break; 1232 1233 if (pch == pchEnd) 1234 { 1235 *pcchRun = 1; 1236 return TRUE; 1237 } 1238 1239 int cch = pchEnd - pchStart; 1240 if (cch < 4 && cch % 2 != 0) 1241 return FALSE; 1242 1243 unsigned short* pus = (unsigned short*)pchStart; 1244 unsigned short us = *pus++; 1245 while ((const char*)pus < pchEnd) 1246 if (*pus++ != us) 1247 return 0; 1248 1249 *pcchRun = 2; 1250 return TRUE; 1251 } 1252 1253 1254 int kFileLX::compressPage1(char *pachPage, const char * pachSrcPage, int cchSrcPage) 1255 { 1256 union 1257 { 1258 char * pch; 1259 unsigned short * push; 1260 struct LX_Iter * pIter; 1261 } Dst; 1262 Dst.pch = pachPage; 1263 const char *pch = pachSrcPage; 1264 const char *pchSearch = pch; 1265 const char *pchEnd = pch + cchSrcPage; 1266 while (pchSearch < pchEnd) 1267 { 1268 int cIterations; 1269 int cchPattern = compressPage1Search(pch, &pchSearch, pchEnd, &cIterations); 1270 if (cchPattern > 0) 1271 { /* Found pattern. */ 1272 /* make uncompressed chunk. */ 1273 if (pch < pchSearch) 1274 { 1275 int cchRun; 1276 int cch = pchSearch - pch; 1277 if (cch < 9 && cch > 1 && compressPage1SearchStored(pch, pchSearch, &cchRun)) 1278 { 1279 /* make compressed chunk. */ 1280 Dst.pIter->LX_nIter = cch / cchRun; 1281 Dst.pIter->LX_nBytes = cchRun; 1282 memcpy(&Dst.pIter->LX_Iterdata, pch, cchPattern); 1283 //printf("put 0x%03x %3d iterations %3d bytes\n", pch - pachSrcPage, Dst.pIter->LX_nIter, Dst.pIter->LX_nBytes); 1284 Dst.pch += cchRun + 4; 1285 } 1286 else 1287 { /* make uncompressed chunk */ 1288 Dst.pIter->LX_nIter = 1; 1289 Dst.pIter->LX_nBytes = cch; 1290 memcpy(&Dst.pIter->LX_Iterdata, pch, cch); 1291 //printf("put 0x%03x stored %3d bytes\n", pch - pachSrcPage, Dst.pIter->LX_nBytes); 1292 Dst.pch += cch + 4; 1293 } 1294 pch += cch; 1295 } 1296 1297 /* make compressed chunk. */ 1298 Dst.pIter->LX_nIter = cIterations; 1299 Dst.pIter->LX_nBytes = cchPattern; 1300 memcpy(&Dst.pIter->LX_Iterdata, pch, cchPattern); 1301 //printf("put 0x%03x %3d iterations %3d bytes\n", pch - pachSrcPage, Dst.pIter->LX_nIter, Dst.pIter->LX_nBytes); 1302 Dst.pch += cchPattern + 4; 1303 pchSearch = pch += cchPattern * cIterations; 1304 } 1305 else 1306 { /* No pattern - got the next byte in the source page. */ 1307 pchSearch++; 1308 } 1309 } 1310 1311 /* make final uncompressed chunk(s) */ 1312 if (pch < pchSearch) 1313 { 1314 int cch = pchSearch - pch; 1315 Dst.pIter->LX_nIter = 1; 1316 Dst.pIter->LX_nBytes = cch; 1317 memcpy(&Dst.pIter->LX_Iterdata, pch, cch); 1318 //printf("put 0x%03x stored %3d bytes %d\n", pch - pachSrcPage, Dst.pIter->LX_nBytes, cch); 1319 Dst.pch += cch + 4; 1320 pch += cch; 1321 } 1322 1323 1324 1325 /* write terminating word - this is really not needed AFAIK, but it makes debugging easier. */ 1326 //*Dst.push++ = 0; 1327 return Dst.pch - pachPage; 1328 } 1329 705 1330 706 1331 … … 711 1336 * PAGESIZE if failed to compress the page. 712 1337 * -1 on error. 713 * @param pachPage Pointer to output buffer. size: PAGESIZE.1338 * @param pachPage Pointer to output buffer. size: cchSrcPage. 714 1339 * This will hold the compressed page data upon return. 715 * @param pachSrcPage Pointer to page to compress. size: PAGESIZE. 1340 * @param pachSrcPage Pointer to page to compress. size: cchSrcPage. 1341 * @param cchSrcPage Page size. 716 1342 * @sketch Have no idea! 717 1343 * @status stub. … … 719 1345 * @remark Not implemented. 720 1346 */ 721 int kFileLX::compressPage2(char *pachPage, const char * pachSrcPage) 722 { 723 NOREF(pachPage); 724 NOREF(pachSrcPage); 1347 int kFileLX::compressPage2(char *pachPage, const char * pachSrcPage, int cchSrcPage) 1348 { 1349 KNOREF(pachPage); 1350 KNOREF(pachSrcPage); 1351 KNOREF(cchSrcPage); 725 1352 return -1; 726 1353 } 727 1354 728 #endif 1355 1356 /** 1357 * Start a relocation enumeration. 1358 * @returns TRUE: Found relocation. 1359 * FALSE: No more relocations. 1360 * @param ulSegment Segment number. Special selector may be specified. 1361 * @param offSegment Offset into the segment described by ulSegment. 1362 * @param preloc Pointer to a relocation 'handle' structure. 1363 * This is used for communicating the relocations in 1364 * a generic format and for keeping track of the current position. 1365 * Please, DO NOT change any members of this structure. 1366 */ 1367 KBOOL kFileLX::relocFindFirst(unsigned long ulSegment, unsigned long offSegment, kRelocEntry *preloc) 1368 { 1369 if (ulSegment >= kRelocEntry::enmFirstSelector) 1370 offSegment = lxSpecialSelectorToObjectOffset(offSegment, &ulSegment); 1371 1372 if ( lxValidateObjectOffset(ulSegment, offSegment) 1373 && pe32->e32_frectab != 0 1374 && pe32->e32_fpagetab != 0 1375 ) 1376 { 1377 PLXRELOCSTATE pState = new LXRELOCSTATE; 1378 pState->ulSegment = ulSegment; 1379 pState->ulPage = paObject[ulSegment].o32_pagemap - 1; 1380 pState->pchFixupRec = pchFixupRecs + paulFixupPageTable[pState->ulPage]; 1381 pState->usSrcOffIdx = 0; 1382 preloc->pv1 = (void*)pState; 1383 preloc->fFlags = 0; 1384 preloc->Info.Name.pszModule = NULL; 1385 preloc->Info.Name.pszName = NULL; 1386 return relocFindNext(preloc); 1387 } 1388 1389 return FALSE; 1390 } 1391 1392 1393 /** 1394 * Start a relocation enumeration. 1395 * @returns TRUE: Found relocation. 1396 * FALSE: No more relocations. 1397 * @param ulAddress Address to start from. 1398 * @param preloc Pointer to a relocation 'handle' structure. 1399 * This is used for communicating the relocations in 1400 * a generic format and for keeping track of the current position. 1401 * Please, DO NOT change any members of this structure. 1402 */ 1403 KBOOL kFileLX::relocFindFirst(unsigned long ulAddress, kRelocEntry *preloc) 1404 { 1405 return relocFindFirst(kRelocEntry::enmVASelector, ulAddress, preloc); 1406 } 1407 1408 1409 /** 1410 * Get the next relocation. 1411 * @returns TRUE: Found relocation. 1412 * FALSE: No more relocations. 1413 * @param preloc Pointer to a relocation 'handle' structure. 1414 * @remark preloc have to be opened by relocFindFirst before calling relocFindNext! 1415 */ 1416 KBOOL kFileLX::relocFindNext(kRelocEntry *preloc) 1417 { 1418 PLXRELOCSTATE pState = (PLXRELOCSTATE)preloc->pv1; 1419 int iObj = pState->ulSegment; 1420 KBOOL fFound = FALSE; 1421 1422 while (iObj < pe32->e32_objcnt) 1423 { 1424 int iPage = pState->ulPage; 1425 1426 while (iPage < paObject[iObj].o32_mapsize + paObject[iObj].o32_pagemap - 1) 1427 { 1428 char * pchFixupRecEnd = pchFixupRecs + paulFixupPageTable[iPage + 1]; 1429 1430 while (pState->pchFixupRec < pchFixupRecEnd) 1431 { 1432 char * pch; /* Fixup record walker. */ 1433 union _rel 1434 { 1435 unsigned long ul; 1436 char * pch; 1437 struct r32_rlc *prlc; 1438 } rel; /* Fixup record */ 1439 1440 /* 1441 * If we're completed here we'll simply return. 1442 */ 1443 if (fFound) 1444 return TRUE; 1445 1446 1447 /* 1448 * Do some init and cleanup. 1449 */ 1450 rel.pch = pState->pchFixupRec; 1451 if (preloc->isName()) 1452 { 1453 delete (void*)preloc->Info.Name.pszModule; 1454 delete (void*)preloc->Info.Name.pszName; 1455 preloc->Info.Name.pszName = preloc->Info.Name.pszModule = NULL; 1456 } 1457 1458 1459 /* 1460 * We've got a problem! chained relocation records! 1461 */ 1462 switch (rel.prlc->nr_stype & NRSTYP) 1463 { 1464 case NRSBYT: preloc->fFlags = kRelocEntry::enm8 | kRelocEntry::enmOffset; break; 1465 case NRSSEG: preloc->fFlags = kRelocEntry::enm16_00 | kRelocEntry::enmOffset; break; 1466 case NRSPTR: preloc->fFlags = kRelocEntry::enm16_16 | kRelocEntry::enmOffset; break; 1467 case NRSOFF: preloc->fFlags = kRelocEntry::enm16 | kRelocEntry::enmOffset; break; 1468 case NRPTR48: preloc->fFlags = kRelocEntry::enm16_32 | kRelocEntry::enmOffset; break; 1469 case NROFF32: preloc->fFlags = kRelocEntry::enm32 | kRelocEntry::enmOffset; break; 1470 case NRSOFF32: preloc->fFlags = kRelocEntry::enm32 | kRelocEntry::enmRelEnd; break; 1471 default: 1472 kASSERT(FALSE); 1473 return FALSE; 1474 } 1475 1476 /* Set endian flag. */ 1477 if (pe32->e32_border == E32LEBO && pe32->e32_border == E32LEWO) 1478 preloc->fFlags |= kRelocEntry::enmLittleEndian; 1479 else if (pe32->e32_border == E32BEBO && pe32->e32_border == E32BEWO) 1480 preloc->fFlags |= kRelocEntry::enmBigEndian; 1481 else 1482 { 1483 kASSERT(FALSE); 1484 return FALSE; 1485 } 1486 1487 1488 /* 1489 * LX target type. 1490 */ 1491 pch = rel.pch + 3 + (rel.prlc->nr_stype & NRCHAIN ? 0 : 1); /* place pch at the 4th member. */ 1492 switch (rel.prlc->nr_flags & NRRTYP) 1493 { 1494 case NRRINT: 1495 preloc->fFlags |= kRelocEntry::enmInternal; 1496 if (rel.prlc->nr_flags & NR16OBJMOD) 1497 { 1498 preloc->Info.Internal.ulSegment = *(unsigned short *)pch - 1; 1499 pch += 2; 1500 } 1501 else 1502 { 1503 preloc->Info.Internal.ulSegment = *(unsigned char *)pch - 1; 1504 pch += 1; 1505 } 1506 if (rel.prlc->nr_flags & NR32BITOFF) 1507 { 1508 preloc->Info.Internal.offSegment = *(unsigned long *)pch; 1509 pch += 4; 1510 } 1511 else 1512 { 1513 preloc->Info.Internal.offSegment = *(unsigned short *)pch; 1514 pch += 2; 1515 } 1516 break; 1517 1518 case NRRORD: 1519 preloc->fFlags |= kRelocEntry::enmOrdDLL; 1520 if (rel.prlc->nr_flags & NR16OBJMOD) 1521 { 1522 preloc->Info.Name.pszModule = lxGetImportModuleName(*(unsigned short *)pch); 1523 pch += 2; 1524 } 1525 else 1526 { 1527 preloc->Info.Name.pszModule = lxGetImportModuleName(*(unsigned char *)pch); 1528 pch += 1; 1529 } 1530 if (rel.prlc->nr_flags & NR32BITOFF) 1531 { 1532 sprintf(preloc->Info.Name.pszName = new char[16], "#%lu", *(unsigned long *)pch); 1533 preloc->Info.Name.ulOrdinal = (unsigned)*(unsigned long *)pch; 1534 pch += 4; 1535 } 1536 else if (rel.prlc->nr_flags & NR8BITORD) 1537 { 1538 sprintf(preloc->Info.Name.pszName = new char[8], "#%u", (unsigned)*(unsigned char *)pch); 1539 preloc->Info.Name.ulOrdinal = (unsigned)*(unsigned char *)pch; 1540 pch += 1; 1541 } 1542 else 1543 { 1544 sprintf(preloc->Info.Name.pszName = new char[12], "#%u", (unsigned)*(unsigned short *)pch); 1545 preloc->Info.Name.ulOrdinal = (unsigned)*(unsigned short *)pch; 1546 pch += 2; 1547 } 1548 break; 1549 1550 case NRRNAM: 1551 preloc->fFlags |= kRelocEntry::enmNameDLL; 1552 if (rel.prlc->nr_flags & NR16OBJMOD) 1553 { 1554 preloc->Info.Name.pszModule = lxGetImportModuleName(*(unsigned short *)pch); 1555 pch += 2; 1556 } 1557 else 1558 { 1559 preloc->Info.Name.pszModule = lxGetImportModuleName(*(unsigned char *)pch); 1560 pch += 1; 1561 } 1562 preloc->Info.Name.ulOrdinal = ~0UL;; 1563 if (rel.prlc->nr_flags & NR32BITOFF) 1564 { 1565 preloc->Info.Name.pszName = lxGetImportProcName(*(unsigned long *)pch); 1566 pch += 4; 1567 } 1568 else 1569 { 1570 preloc->Info.Name.pszName = lxGetImportProcName(*(unsigned short *)pch); 1571 pch += 2; 1572 } 1573 break; 1574 1575 case NRRENT: 1576 preloc->fFlags |= kRelocEntry::enmInternal; 1577 kASSERT(!"Not Implemented"); 1578 return FALSE; 1579 } 1580 1581 /* addiative fixup? */ 1582 if (rel.prlc->nr_flags & NRADD) 1583 { 1584 preloc->fFlags |= kRelocEntry::enmAdditive; 1585 if (rel.prlc->nr_flags & NR32BITADD) 1586 { 1587 preloc->ulAdd = *(unsigned long *)pch; 1588 pch += 4; 1589 } 1590 else 1591 { 1592 preloc->ulAdd = *(unsigned short *)pch; 1593 pch += 2; 1594 } 1595 } 1596 1597 /* 1598 * obj:offset of the fixup 1599 * If the offset is negative we'll skip it (ie. not set the found flag). 1600 */ 1601 preloc->ulSegment = iObj; 1602 preloc->offSegment = (iPage - paObject[iObj].o32_pagemap + 1) * pe32->e32_pagesize; 1603 if (rel.prlc->nr_stype & NRCHAIN) 1604 { 1605 while (pState->usSrcOffIdx < (unsigned char)rel.prlc->r32_soff) 1606 { 1607 if (!(((unsigned short *)pch)[pState->usSrcOffIdx] & 0x8000)) 1608 { 1609 preloc->offSegment += ((unsigned short*)pch)[pState->usSrcOffIdx]; 1610 fFound = TRUE; 1611 break; 1612 } 1613 pState->usSrcOffIdx++; 1614 } 1615 } 1616 else 1617 { 1618 preloc->offSegment += rel.prlc->r32_soff; 1619 if (!(rel.prlc->r32_soff & 0x8000)) 1620 fFound = TRUE; 1621 } 1622 1623 1624 /* 1625 * Go to the next relocation. 1626 */ 1627 if (rel.prlc->nr_stype & NRCHAIN) 1628 { 1629 if (++pState->usSrcOffIdx >= (unsigned char)rel.prlc->r32_soff) 1630 { 1631 pState->pchFixupRec = pState->pchFixupRec + (KSIZE)pch - rel.ul + ((unsigned char)rel.prlc->r32_soff) * 2; 1632 pState->usSrcOffIdx = 0; 1633 } 1634 } 1635 else 1636 pState->pchFixupRec = pState->pchFixupRec + (KSIZE)pch - rel.ul; 1637 } 1638 1639 1640 /* next page */ 1641 pState->ulPage = ++iPage; 1642 pState->pchFixupRec = pchFixupRecEnd; 1643 pState->usSrcOffIdx = 0; /* Source Offset Index */ 1644 } 1645 1646 1647 /* next object */ 1648 pState->ulSegment = ++iObj; 1649 if (iObj >= pe32->e32_objcnt) 1650 break; 1651 pState->ulPage = paObject[iObj].o32_pagemap - 1; 1652 pState->pchFixupRec = pchFixupRecs + paulFixupPageTable[pState->ulPage]; 1653 pState->usSrcOffIdx = 0; /* Source Offset Index */ 1654 } 1655 1656 return fFound; 1657 } 1658 1659 1660 /** 1661 * Closes a relocatation search/enumeration. 1662 * Will free any internally allocated resources. 1663 * 1664 * @param preloc The enumeration 'handel'. 1665 * @remark This function *must* be called to close a search/enumeration. 1666 */ 1667 void kFileLX::relocFindClose(kRelocEntry *preloc) 1668 { 1669 /* free name storage */ 1670 if (preloc->isName()) 1671 { 1672 delete (void*)preloc->Info.Name.pszModule; 1673 delete (void*)preloc->Info.Name.pszName; 1674 preloc->Info.Name.pszName = preloc->Info.Name.pszModule = NULL; 1675 } 1676 1677 /* free state info */ 1678 memset(preloc->pv1, 0xff, sizeof(LXRELOCSTATE)); 1679 delete preloc->pv1; 1680 preloc->pv1 = (void*)0xdeadbeef; 1681 } 1682 1683 1684
Note:
See TracChangeset
for help on using the changeset viewer.