Ignore:
Timestamp:
Nov 16, 2006, 6:52:27 AM (19 years ago)
Author:
bird
Message:

object protection, module name init, symbol resolving.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModLX.c

    r2880 r2882  
    117117                                 PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
    118118static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX);
     119static const uint8_t *kldrModLXDoNameTableLookupByOrdinal(const uint8_t *pbNameTable, int32_t cbNameTable, uint32_t iOrdinal);
     120static int kldrModLXDoNameLookup(PKLDRMODLX pModLX, const char *pszSymbol, uint32_t *piSymbol);
     121static const uint8_t *kldrModLXDoNameTableLookupByName(const uint8_t *pbNameTable, int32_t cbNameTable,
     122                                                       char *pchSymbol, size_t cchSymbol);
    119123static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits);
    120124static int kldrModLXDoIterDataUnpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc);
     
    123127static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect);
    124128static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle);
     129static int32_t kldrModLXDoGetOrdinalByName(PKLDRMODLX pModLX, const char *pszName);
     130static int kldrModLXDoForwarderQuery(PKLDRMODLX pModLX, const struct e32_entry *pEntry,
     131                                     PFNKLDRMODGETIMPORT pfnGetForwarder, void *pvUser, PKLDRADDR puValue, uint32_t *pfKind);
     132static int kldrModLXDoLoadFixupSection(PKLDRMODLX pModLX);
    125133static int32_t kldrModLXDoCall(uintptr_t uEntrypoint, uintptr_t uHandle, uint32_t uOp, void *pvReserved);
    126134
     
    355363    /*
    356364     * 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;
    359377
    360378    /*
     
    484502        pModLX->pbFixupSection = NULL;
    485503    }
    486     if (pMod->pszName)
    487     {
    488         kldrHlpFree((void *)pMod->pszName);
    489         pMod->pszName = NULL;
    490     }
    491504    pMod->u32Magic = 0;
    492505    pMod->pOps = NULL;
     
    516529                                PKLDRADDR puValue, uint32_t *pfKind)
    517530{
    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 */
     653static 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 */
     686static 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 */
     709static 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 */
     753static 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 */
     874static int kldrModLXDoLoadFixupSection(PKLDRMODLX pModLX)
     875{
    523876    return -1;
    524877}
     
    535888
    536889    return -1;
     890}
     891
     892
     893/**
     894 * Lookup a name table entry by ordinal.
     895 *
     896 * @returns Pointer to the name table entry if found.
     897 * @returns NULL if not found.
     898 * @param   pbNameTable Pointer to the name table that should be searched.
     899 * @param   cbNameTable The size of the name table.
     900 * @param   iOrdinal    The ordinal to search for.
     901 */
     902static const uint8_t *kldrModLXDoNameTableLookupByOrdinal(const uint8_t *pbNameTable, int32_t cbNameTable, uint32_t iOrdinal)
     903{
     904    while (*pbNameTable != 0 && cbNameTable > 0)
     905    {
     906        const uint8_t   cbName = *pbNameTable;
     907        uint32_t        iName;
     908
     909        cbNameTable -= cbName + 1 + 2;
     910        if (cbNameTable < 0)
     911            break;
     912
     913        iName = *(pbNameTable + cbName)
     914              | ((unsigned)*(pbNameTable + cbName + 1) << 8);
     915        if (iName == iOrdinal)
     916            return pbNameTable;
     917
     918        /* next entry */
     919        pbNameTable += cbName + 1 + 2;
     920    }
     921
     922    return NULL;
    537923}
    538924
     
    11531539 *          protect according to the object table.
    11541540 */
    1155 static int kldrModLXDoProtect(PKLDRMODLX pMod, void *pvBits, unsigned fUnprotectOrProtect)
    1156 {
    1157     return -1;
     1541static 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;
    11581599}
    11591600
     
    11911632    PKLDRMODLX  pModLX = (PKLDRMODLX)pMod->pvData;
    11921633
    1193     /* just do the error checking. */
     1634    /* no tls, just do the error checking. */
    11941635    if (!pModLX->pvMapping)
    11951636        return KLDR_ERR_NOT_MAPPED;
     
    12011642static void kldrModLXFreeTLS(PKLDRMOD pMod)
    12021643{
     1644    /* no tls. */
    12031645}
    12041646
     
    12351677     * Before doing anything we'll have to make all pages writable.
    12361678     */
    1237     rc = kLdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
     1679    rc = kldrModLXDoProtect(pModLX, (void *)pModLX->pvMapping, 1 /* unprotect */);
    12381680    if (rc)
    12391681        return rc;
     
    12481690     * Restore protection.
    12491691     */
    1250     rc2 = kLdrRdrProtect(pMod->pRdr, (void *)pModLX->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
     1692    rc2 = kldrModLXDoProtect(pModLX, (void *)pModLX->pvMapping, 0 /* protect */);
    12511693    if (!rc && rc2)
    12521694        rc = rc2;
     
    13971839static int kldrModLXCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
    13981840{
     1841    /* no thread attach/detach callout. */
    13991842    return 0;
    14001843}
Note: See TracChangeset for help on using the changeset viewer.