Changeset 2882 for trunk/kLdr/kLdrModLX.c
- Timestamp:
- Nov 16, 2006, 6:52:27 AM (19 years ago)
- File:
-
- 1 edited
-
trunk/kLdr/kLdrModLX.c (modified) (12 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/kLdr/kLdrModLX.c
r2880 r2882 117 117 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser); 118 118 static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX); 119 120 121 122 119 123 static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits); 120 124 static int kldrModLXDoIterDataUnpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc); … … 123 127 static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect); 124 128 static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle); 129 130 131 132 125 133 static int32_t kldrModLXDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved); 126 134 … … 355 363 /* 356 364 * Get the soname from the resident name table. 357 */ 358 /** @todo */ 365 * Very convenient that it's the 0 ordinal, because then we get a 366 * free string terminator. 367 * (The table entry consists of a pascal string followed by a 16-bit ordinal.) 368 */ 369 pMod->pszName = kldrModLXDoNameTableLookupByOrdinal(pModLX->pbResNameTab, 370 pModLX->pbLoaderSectionLast - pModLX->pbResNameTab + 1, 371 0); 372 if (!pMod->pszName) 373 return KLDR_ERR_LX_NO_SONAME; 374 pMod->cchName = *(const uint8_t *)pMod->pszName++; 375 if (pMod->cchName != kLdrHlpStrLen(pMod->pszName)) 376 return KLDR_ERR_LX_BAD_SONAME; 359 377 360 378 /* … … 484 502 pModLX->pbFixupSection = NULL; 485 503 } 486 if (pMod->pszName)487 {488 kldrHlpFree((void *)pMod->pszName);489 pMod->pszName = NULL;490 }491 504 pMod->u32Magic = 0; 492 505 pMod->pOps = NULL; … … 516 529 PKLDRADDR puValue, uint32_t *pfKind) 517 530 { 518 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 519 //int rc; 520 521 kldrModLXResolveBaseAddress(pModLX, &BaseAddress); 522 531 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 532 uint32_t iOrdinal; 533 int rc; 534 const struct b32_bundle *pBundle; 535 536 537 /* 538 * Give up at once if there is no entry table. 539 */ 540 if (!pModLX->Hdr.e32_enttab) 541 return KLDR_ERR_SYMBOL_NOT_FOUND; 542 543 /* 544 * Translate the symbol name into an ordinal. 545 */ 546 if (pszSymbol) 547 { 548 rc = kldrModLXDoNameLookup(pModLX, pszSymbol, &iSymbol); 549 if (rc) 550 return rc; 551 } 552 553 /* 554 * Iterate the entry table. 555 * (The entry table is made up of bundles of similar exports.) 556 */ 557 iOrdinal = 0; 558 pBundle = (const struct b32_bundle *)pModLX->pbEntryTab; 559 while (!pBundle->b32_cnt && iOrdinal <= iSymbol) 560 { 561 static const size_t s_cbEntry[] = { 0, 3, 5, 5, 7 }; 562 563 /* 564 * Check for a hit first. 565 */ 566 iOrdinal += pBundle->b32_cnt; 567 if (iSymbol < iOrdinal) 568 { 569 uint32_t offObject; 570 const struct e32_entry *pEntry = (const struct e32_entry *)((uintptr_t)(pBundle + 1) 571 + iSymbol - (iOrdinal - pBundle->b32_cnt)); 572 573 /* 574 * Calculate the return address. 575 */ 576 kldrModLXResolveBaseAddress(pModLX, &BaseAddress); 577 switch (pBundle->b32_type) 578 { 579 /* empty bundles are place holders unused ordinal ranges. */ 580 case EMPTY: 581 return KLDR_ERR_SYMBOL_NOT_FOUND; 582 583 /* e32_flags + a 16-bit offset. */ 584 case ENTRY16: 585 offObject = pEntry->e32_variant.e32_offset.offset16; 586 if (pfKind) 587 *pfKind = KLDRSYMKIND_16BIT | KLDRSYMKIND_NO_TYPE; 588 break; 589 590 /* e32_flags + a 16-bit offset + a 16-bit callgate selector. */ 591 case GATE16: 592 offObject = pEntry->e32_variant.e32_callgate.offset; 593 if (pfKind) 594 *pfKind = KLDRSYMKIND_16BIT | KLDRSYMKIND_CODE; 595 break; 596 597 /* e32_flags + a 32-bit offset. */ 598 case ENTRY32: 599 offObject = pEntry->e32_variant.e32_offset.offset32; 600 if (pfKind) 601 *pfKind = KLDRSYMKIND_32BIT; 602 break; 603 604 /* e32_flags + 16-bit import module ordinal + a 32-bit procname or ordinal. */ 605 case ENTRYFWD: 606 return kldrModLXDoForwarderQuery(pModLX, pEntry, pfnGetForwarder, pvUser, puValue, pfKind); 607 608 default: 609 /* anyone actually using TYPEINFO will end up here. */ 610 KLDRMODLX_ASSERT(!"Bad bundle type"); 611 break; 612 } 613 614 /* 615 * Validate the object number and calc the return address. 616 */ 617 if ( pBundle->b32_obj <= 0 618 || pBundle->b32_obj > pMod->cSegments) 619 return KLDR_ERR_LX_BAD_BUNDLE; 620 if (puValue) 621 *puValue = BaseAddress 622 + offObject 623 + pMod->aSegments[pBundle->b32_obj - 1].RVA; 624 return 0; 625 } 626 627 /* 628 * Skip the bundle. 629 */ 630 if (pBundle->b32_type > ENTRYFWD) 631 { 632 KLDRMODLX_ASSERT(!"Bad type"); /** @todo figure out TYPEINFO. */ 633 return KLDR_ERR_LX_BAD_BUNDLE; 634 } 635 if (pBundle->b32_type == 0) 636 pBundle = (const struct b32_bundle *)((const uint8_t *)pBundle + 2); 637 else 638 pBundle = (const struct b32_bundle *)((const uint8_t *)pBundle + s_cbEntry[pBundle->b32_type] * pBundle->b32_cnt); 639 } 640 641 return KLDR_ERR_SYMBOL_NOT_FOUND; 642 } 643 644 645 /** 646 * Do name lookup. 647 * 648 * @returns See kLdrModQuerySymbol. 649 * @param pModLX The module to lookup the symbol in. 650 * @param pszSymbol The symbol to lookup. 651 * @param piSymbol Where to store the symbol ordinal. 652 */ 653 static int kldrModLXDoNameLookup(PKLDRMODLX pModLX, const char *pszSymbol, uint32_t *piSymbol) 654 { 655 656 /* 657 * First do a hash table lookup. 658 */ 659 660 661 662 /* 663 664 */ 665 666 return -1; 667 } 668 669 670 /** 671 * Hash a symbol using the algorithm from sdbm. 672 * 673 * The following was is the documenation of the orignal sdbm functions: 674 * 675 * This algorithm was created for sdbm (a public-domain reimplementation of 676 * ndbm) database library. it was found to do well in scrambling bits, 677 * causing better distribution of the keys and fewer splits. it also happens 678 * to be a good general hashing function with good distribution. the actual 679 * function is hash(i) = hash(i - 1) * 65599 + str[i]; what is included below 680 * is the faster version used in gawk. [there is even a faster, duff-device 681 * version] the magic constant 65599 was picked out of thin air while 682 * experimenting with different constants, and turns out to be a prime. 683 * this is one of the algorithms used in berkeley db (see sleepycat) and 684 * elsewhere. 685 */ 686 static uint32_t kldrModLXDoHash(const char *pchSymbol, uint8_t cchSymbol) 687 { 688 uint32_t hash = 0; 689 int ch; 690 691 while ( cchSymbol-- > 0 692 && (ch = *(unsigned const char *)pchSymbol++)) 693 hash = ch + (hash << 6) + (hash << 16) - hash; 694 695 return hash; 696 } 697 698 699 /** 700 * Lookup a name table entry by name. 701 * 702 * @returns Pointer to the name table entry if found. 703 * @returns NULL if not found. 704 * @param pbNameTable Pointer to the name table that should be searched. 705 * @param cbNameTable The size of the name table. 706 * @param pchSymbol The name of the symbol we're looking for. 707 * @param cchSymbol The length of the symbol name. 708 */ 709 static const uint8_t *kldrModLXDoNameTableLookupByName(const uint8_t *pbNameTable, int32_t cbNameTable, 710 char *pchSymbol, size_t cchSymbol) 711 { 712 /* 713 * Determin the namelength up front so we can skip anything which doesn't matches the length. 714 */ 715 uint8_t cbSymbol8Bit = (uint8_t)cchSymbol; 716 if (cbSymbol8Bit != cchSymbol) 717 return NULL; /* too long. */ 718 719 /* 720 * Walk the name table. 721 */ 722 while (*pbNameTable != 0 && cbNameTable > 0) 723 { 724 const uint8_t cbName = *pbNameTable; 725 726 cbNameTable -= cbName + 1 + 2; 727 if (cbNameTable < 0) 728 break; 729 730 if ( cbName == cbSymbol8Bit 731 && !kLdrHlpMemComp(pbNameTable + 1, pchSymbol, cbName)) 732 return pbNameTable; 733 734 /* next entry */ 735 pbNameTable += cbName + 1 + 2; 736 } 737 738 return NULL; 739 } 740 741 742 /** 743 * Deal with a forwarder entry. 744 * 745 * @returns See kLdrModQuerySymbol. 746 * @param pModLX The PE module interpreter instance. 747 * @param pEntry The forwarder entry. 748 * @param pfnGetForwarder The callback for resolving forwarder symbols. (optional) 749 * @param pvUser The user argument for the callback. 750 * @param puValue Where to put the value. (optional) 751 * @param pfKind Where to put the symbol kind. (optional) 752 */ 753 static int kldrModLXDoForwarderQuery(PKLDRMODLX pModLX, const struct e32_entry *pEntry, 754 PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind) 755 { 756 int rc; 757 uint32_t iSymbol; 758 const char *pszSymbol; 759 760 if (!pfnGetForwarder) 761 return KLDR_ERR_FORWARDER_SYMBOL; 762 763 /* 764 * Validate the entry import module ordinal. 765 */ 766 if ( !pEntry->e32_variant.e32_fwd.modord 767 || pEntry->e32_variant.e32_fwd.modord > pModLX->Hdr.e32_impmodcnt) 768 return KLDR_ERR_LX_BAD_FORWARDER; 769 770 /* 771 * Figure out the parameters. 772 */ 773 if (pEntry->e32_flags & FWD_ORDINAL) 774 { 775 iSymbol = pEntry->e32_variant.e32_fwd.value; 776 pszSymbol = NULL; /* no symbol name. */ 777 } 778 else 779 { 780 const uint8_t *pbName; 781 782 /* load the fixup section if necessary. */ 783 if (!pModLX->pbImportProcs) 784 { 785 rc = kldrModLXDoLoadFixupSection(pModLX); 786 if (rc) 787 return rc; 788 } 789 790 /* Make name pointer. */ 791 pbName = pModLX->pbImportProcs + pEntry->e32_variant.e32_fwd.value; 792 if ( pbName >= pModLX->pbFixupSectionLast 793 || pbName < pModLX->pbFixupSectionLast 794 || !*pbName) 795 return KLDR_ERR_LX_BAD_FORWARDER; 796 797 798 /* check for '#' name. */ 799 if (pbName[1] == '#') 800 { 801 uint8_t cbLeft = *pbName; 802 const uint8_t *pb = pbName + 1; 803 unsigned uBase; 804 805 /* base detection */ 806 uBase = 10; 807 if ( cbLeft > 1 808 && pb[1] == '0' 809 && (pb[2] == 'x' || pb[2] == 'X')) 810 { 811 uBase = 16; 812 pb += 2; 813 cbLeft -= 2; 814 } 815 816 /* ascii to integer */ 817 iSymbol = 0; 818 while (cbLeft-- > 0) 819 { 820 /* convert char to digit. */ 821 unsigned uDigit = *pb++; 822 if (uDigit >= '0' && uDigit <= '9') 823 uDigit -= '0'; 824 else if (uDigit >= 'a' && uDigit <= 'z') 825 uDigit -= 'a' + 10; 826 else if (uDigit >= 'A' && uDigit <= 'Z') 827 uDigit -= 'A' + 10; 828 else if (!uDigit) 829 break; 830 else 831 return KLDR_ERR_LX_BAD_FORWARDER; 832 if (uDigit >= uBase) 833 return KLDR_ERR_LX_BAD_FORWARDER; 834 835 /* insert the digit */ 836 iSymbol *= uBase; 837 iSymbol += uDigit; 838 } 839 if (!iSymbol) 840 return KLDR_ERR_LX_BAD_FORWARDER; 841 842 pszSymbol = NULL; /* no symbol name. */ 843 } 844 else 845 { 846 /* Make a stack copy of the name that's zero terminated. */ 847 char *pszCopy = kLdrHlpAllocA(*pbName + 1); 848 kLdrHlpMemCopy(pszCopy, pbName + 1, *pbName); 849 pszCopy[*pbName] = '\0'; 850 851 pszSymbol = pszCopy; 852 iSymbol = NIL_KLDRMOD_SYM_ORDINAL; 853 } 854 } 855 856 /* 857 * Resolve the forwarder. 858 */ 859 rc = pfnGetForwarder(pModLX->pMod, pEntry->e32_variant.e32_fwd.modord - 1, iSymbol, pszSymbol, puValue, pfKind, pvUser); 860 if (!rc && pfKind) 861 *pfKind |= KLDRSYMKIND_FORWARDER; 862 return rc; 863 } 864 865 866 /** 867 * Loads the fixup section from the executable image. 868 * 869 * The fixup section isn't loaded until it's accessed. It's also freed by kLdrModDone(). 870 * 871 * @returns 0 on success, non-zero kLdr or native status code on failure. 872 * @param pModLX The PE module interpreter instance. 873 */ 874 static int kldrModLXDoLoadFixupSection(PKLDRMODLX pModLX) 875 { 523 876 return -1; 524 877 } … … 535 888 536 889 return -1; 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 537 923 } 538 924 … … 1153 1539 * protect according to the object table. 1154 1540 */ 1155 static int kldrModLXDoProtect(PKLDRMODLX pMod, void *pvBits, unsigned fUnprotectOrProtect) 1156 { 1157 return -1; 1541 static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect) 1542 { 1543 uint32_t i; 1544 PKLDRMOD pMod = pModLX->pMod; 1545 1546 /* 1547 * Change object protection. 1548 */ 1549 for (i = 0; i < pMod->cSegments; i++) 1550 { 1551 int rc; 1552 void *pv; 1553 KLDRPROT enmProt; 1554 1555 /* calc new protection. */ 1556 enmProt = pMod->aSegments[i].enmProt; 1557 if (fUnprotectOrProtect) 1558 { 1559 switch (enmProt) 1560 { 1561 case KLDRPROT_NOACCESS: 1562 case KLDRPROT_READONLY: 1563 case KLDRPROT_READWRITE: 1564 case KLDRPROT_WRITECOPY: 1565 enmProt = KLDRPROT_READWRITE; 1566 break; 1567 case KLDRPROT_EXECUTE: 1568 case KLDRPROT_EXECUTE_READ: 1569 case KLDRPROT_EXECUTE_READWRITE: 1570 case KLDRPROT_EXECUTE_WRITECOPY: 1571 enmProt = KLDRPROT_EXECUTE_READWRITE; 1572 break; 1573 default: 1574 KLDRMODLX_ASSERT(!"bad enmProt"); 1575 return -1; 1576 } 1577 } 1578 else 1579 { 1580 /* copy on write -> normal write. */ 1581 if (enmProt == KLDRPROT_EXECUTE_WRITECOPY) 1582 enmProt = KLDRPROT_EXECUTE_READWRITE; 1583 else if (enmProt == KLDRPROT_WRITECOPY) 1584 enmProt = KLDRPROT_READWRITE; 1585 } 1586 1587 1588 /* calc the address and set page protection. */ 1589 pv = (uint8_t *)pvBits + pMod->aSegments[i].RVA; 1590 1591 rc = kldrHlpPageProtect(pv, pMod->aSegments[i].cbMapped, enmProt); 1592 if (rc) 1593 break; 1594 1595 /** @todo the gap page should be marked NOACCESS! */ 1596 } 1597 1598 return 0; 1158 1599 } 1159 1600 … … 1191 1632 PKLDRMODLX pModLX = (PKLDRMODLX)pMod->pvData; 1192 1633 1193 /* just do the error checking. */1634 /* just do the error checking. */ 1194 1635 if (!pModLX->pvMapping) 1195 1636 return KLDR_ERR_NOT_MAPPED; … … 1201 1642 static void kldrModLXFreeTLS(PKLDRMOD pMod) 1202 1643 { 1644 1203 1645 } 1204 1646 … … 1235 1677 * Before doing anything we'll have to make all pages writable. 1236 1678 */ 1237 rc = k LdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);1679 rc = k, 1 /* unprotect */); 1238 1680 if (rc) 1239 1681 return rc; … … 1248 1690 * Restore protection. 1249 1691 */ 1250 rc2 = k LdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);1692 rc2 = k, 0 /* protect */); 1251 1693 if (!rc && rc2) 1252 1694 rc = rc2; … … 1397 1839 static int kldrModLXCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching) 1398 1840 { 1841 1399 1842 return 0; 1400 1843 }
Note:
See TracChangeset
for help on using the changeset viewer.
