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);
     119
     120
     121
     122
    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);
     129
     130
     131
     132
    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
     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
    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    /* just do the error checking. */
    11941635    if (!pModLX->pvMapping)
    11951636        return KLDR_ERR_NOT_MAPPED;
     
    12011642static void kldrModLXFreeTLS(PKLDRMOD pMod)
    12021643{
     1644
    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 = k, 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 = k, 0 /* protect */);
    12511693    if (!rc && rc2)
    12521694        rc = rc2;
     
    13971839static int kldrModLXCallThread(PKLDRMOD pMod, uintptr_t uHandle, unsigned fAttachingOrDetaching)
    13981840{
     1841
    13991842    return 0;
    14001843}
Note: See TracChangeset for help on using the changeset viewer.