Changeset 2880


Ignore:
Timestamp:
Nov 13, 2006, 9:20:19 PM (19 years ago)
Author:
bird
Message:

Loading of LX bits, including exepack and exepack2 decompression.

Location:
trunk/kLdr
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdr.h

    r2879 r2880  
    3636#include <stddef.h>
    3737#ifdef _MSC_VER
    38 typedef signed char         int8_t;
    39 typedef unsigned char       uint8_t;
    40 typedef signed short        int16_t;
    41 typedef unsigned short      uint16_t;
    42 typedef signed int          int32_t;
    43 typedef unsigned int        uint32_t;
    44 typedef signed __int64      int64_t;
    45 typedef unsigned __int64    uint64_t;
    46 typedef int64_t             intmax_t;
    47 typedef uint64_t            uintmax_t;
    48 #define UINT32_C(c)         (c##U)
     38  typedef signed char         int8_t;
     39  typedef unsigned char       uint8_t;
     40  typedef signed short        int16_t;
     41  typedef unsigned short      uint16_t;
     42  typedef signed int          int32_t;
     43  typedef unsigned int        uint32_t;
     44  typedef signed __int64      int64_t;
     45  typedef unsigned __int64    uint64_t;
     46  typedef int64_t             intmax_t;
     47  typedef uint64_t            uintmax_t;
     48# define UINT16_C(c)          (c ## U)
     49# define UINT32_C(c)          (c ## U)
     50# define UINT64_C(c)          (c ## ULL)
    4951#else
    5052# include <stdint.h>
     
    10731075/** validation of the LX object table failed. */
    10741076#define KLDR_ERR_LX_BAD_OBJECT_TABLE                        (KLDR_ERR_LX_BASE + 3)
     1077/** A bad page map entry was encountered. */
     1078#define KLDR_ERR_LX_BAD_PAGE_MAP                            (KLDR_ERR_LX_BASE + 4)
     1079/** Bad iterdata (EXEPACK) data. */
     1080#define KLDR_ERR_LX_BAD_ITERDATA                            (KLDR_ERR_LX_BASE + 5)
     1081/** Bad iterdata2 (EXEPACK2) data. */
     1082#define KLDR_ERR_LX_BAD_ITERDATA2                           (KLDR_ERR_LX_BASE + 6)
    10751083/** @} */
    10761084
    10771085/** End of the valid kLdr status codes. */
    1078 #define KLDR_ERR_END                                        (KLDR_ERR_LX_BASE + 4)
     1086#define KLDR_ERR_END                                        (KLDR_ERR_LX_BASE + 7)
    10791087
    10801088/** @} */
  • trunk/kLdr/kLdrHlp.h

    r2867 r2880  
    7373/** memcpy */
    7474# define kLdrHlpMemCopy(a,b,c) __builtin_memcpy(a,b,c)
     75/** memmove */
     76# define kLdrHlpMemMove(a,b,c) __builtin_memmove(a,b,c)
    7577/** memset */
    7678# define kLdrHlpMemSet(a,b,c)  __builtin_memset(a,b,c)
     
    101103/** memcpy */
    102104# define kLdrHlpMemCopy(a,b,c) memcpy(a,b,c)
     105/** memmove */
     106# define kLdrHlpMemMove_needed
    103107/** memset */
    104108# define kLdrHlpMemSet(a,b,c)  memset(a,b,c)
     
    124128#ifdef kLdrHlpStrChr_needed
    125129void   *kLdrHlpMemChr(const void *pv, int ch, size_t cb);
     130#endif
     131#ifdef kLdrHlpStrChr_needed
     132void   *kLdrHlpMemMove(void *pv1, const void *pv2, size_t cb);
    126133#endif
    127134int     kLdrHlpMemIComp(const void *pv1, const void *pv2, size_t cb);
  • trunk/kLdr/kLdrModLX.c

    r2879 r2880  
    118118static int kldrModLXDoCreate(PKLDRRDR pRdr, off_t offNewHdr, PKLDRMODLX *ppModLX);
    119119static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits);
     120static int kldrModLXDoIterDataUnpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc);
     121static int kldrModLXDoIterData2Unpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc);
     122static void kLdrModLXMemCopyW(uint8_t *pbDst, const uint8_t *pbSrc, int cb);
    120123static int kldrModLXDoProtect(PKLDRMODLX pModLX, void *pvBits, unsigned fUnprotectOrProtect);
    121124static int kldrModLXDoCallDLL(PKLDRMODLX pModLX, unsigned uOp, uintptr_t uHandle);
     
    720723static int kldrModLXDoLoadBits(PKLDRMODLX pModLX, void *pvBits)
    721724{
    722     //E32NOLOAD
    723 
    724     return -1;
     725    const PKLDRRDR pRdr = pModLX->pMod->pRdr;
     726    uint8_t *pbTmpPage = NULL;
     727    int rc = 0;
     728    uint32_t i;
     729
     730    /*
     731     * Iterate the segments.
     732     */
     733    for (i = 0; i < pModLX->Hdr.e32_objcnt; i++)
     734    {
     735        const struct o32_obj * const pObj = &pModLX->paObjs[i];
     736        const uint32_t  cPages = pModLX->pMod->aSegments[i].cbMapped / OBJPAGELEN;
     737        uint32_t        iPage;
     738        uint8_t        *pbPage = (uint8_t *)pvBits + (uintptr_t)pModLX->pMod->aSegments[i].RVA;
     739
     740        /*
     741         * Iterate the page map pages.
     742         */
     743        for (iPage = 0; !rc && iPage < pObj->o32_mapsize; iPage++, pbPage += OBJPAGELEN)
     744        {
     745            const struct o32_map *pMap = &pModLX->paPageMappings[iPage + pObj->o32_pagemap - 1];
     746            switch (pMap->o32_pageflags)
     747            {
     748                case VALID:
     749                    if (pMap->o32_pagesize == OBJPAGELEN)
     750                        rc = kLdrRdrRead(pRdr, pbPage, OBJPAGELEN, pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift);
     751                    else if (pMap->o32_pagesize < OBJPAGELEN)
     752                    {
     753                        rc = kLdrRdrRead(pRdr, pbPage, pMap->o32_pagesize, pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift);
     754                        kLdrHlpMemSet(pbPage + pMap->o32_pagesize, 0, OBJPAGELEN - pMap->o32_pagesize);
     755                    }
     756                    else
     757                        rc = KLDR_ERR_LX_BAD_PAGE_MAP;
     758                    break;
     759
     760                case ITERDATA:
     761                case ITERDATA2:
     762                    /* make sure we've got a temp page .*/
     763                    if (!pbTmpPage)
     764                    {
     765                        pbTmpPage = kldrHlpAlloc(OBJPAGELEN + 256);
     766                        if (!pbTmpPage)
     767                            break;
     768                    }
     769                    /* validate the size. */
     770                    if (pMap->o32_pagesize > OBJPAGELEN + 252)
     771                    {
     772                        rc = KLDR_ERR_LX_BAD_PAGE_MAP;
     773                        break;
     774                    }
     775
     776                    /* read it and ensure 4 extra zero bytes. */
     777                    rc = kLdrRdrRead(pRdr, pbTmpPage, pMap->o32_pagesize, pMap->o32_pagedataoffset << pModLX->Hdr.e32_pageshift);
     778                    if (rc)
     779                        break;
     780                    kLdrHlpMemSet(pbTmpPage + pMap->o32_pagesize, 0, 4);
     781
     782                    /* unpack it into the image page. */
     783                    if (pMap->o32_pageflags == ITERDATA2)
     784                        rc = kldrModLXDoIterData2Unpacking(pbPage, pbTmpPage, pMap->o32_pagesize);
     785                    else
     786                        rc = kldrModLXDoIterDataUnpacking(pbPage, pbTmpPage, pMap->o32_pagesize);
     787                    break;
     788
     789                case INVALID: /* we're probably not dealing correctly with INVALID pages... */
     790                case ZEROED:
     791                    kLdrHlpMemSet(pbPage, 0, OBJPAGELEN);
     792                    break;
     793
     794                case RANGE:
     795                    KLDRMODLX_ASSERT(!"RANGE");
     796                default:
     797                    rc = KLDR_ERR_LX_BAD_PAGE_MAP;
     798                    break;
     799            }
     800        }
     801        if (rc)
     802            break;
     803
     804        /*
     805         * Zero the remaining pages.
     806         */
     807        if (iPage < cPages)
     808            kLdrHlpMemSet(pbPage, 0, (cPages - iPage) * OBJPAGELEN);
     809    }
     810
     811    if (pbTmpPage)
     812        kldrHlpFree(pbTmpPage);
     813    return rc;
     814}
     815
     816
     817/**
     818 * Unpacks iterdata (aka EXEPACK).
     819 *
     820 * @returns 0 on success, non-zero kLdr status code on failure.
     821 * @param   pbDst       Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
     822 * @param   pbSrc       The compressed source data.
     823 * @param   cbSrc       The file size of the compressed data. The source buffer
     824 *                      contains 4 additional zero bytes.
     825 */
     826static int kldrModLXDoIterDataUnpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc)
     827{
     828    const struct LX_Iter   *pIter = (const struct LX_Iter *)pbSrc;
     829    int                     cbDst = OBJPAGELEN;
     830
     831    /* Validate size of data. */
     832    if (cbSrc >= OBJPAGELEN - 2)
     833        return KLDR_ERR_LX_BAD_ITERDATA;
     834
     835    /*
     836     * Expand the page.
     837     */
     838    while (cbSrc > 0 && pIter->LX_nIter)
     839    {
     840        if (pIter->LX_nBytes == 1)
     841        {
     842            /*
     843             * Special case - one databyte.
     844             */
     845            cbDst -= pIter->LX_nIter;
     846            if (cbDst < 0)
     847                return KLDR_ERR_LX_BAD_ITERDATA;
     848
     849            cbSrc -= 4 + 1;
     850            if (cbSrc < -4)
     851                return KLDR_ERR_LX_BAD_ITERDATA;
     852
     853            kLdrHlpMemSet(pbDst, pIter->LX_Iterdata, pIter->LX_nIter);
     854            pbDst += pIter->LX_nIter;
     855            pIter++;
     856        }
     857        else
     858        {
     859            /*
     860             * General.
     861             */
     862            int i;
     863
     864            cbDst -= pIter->LX_nIter * pIter->LX_nBytes;
     865            if (cbDst < 0)
     866                return KLDR_ERR_LX_BAD_ITERDATA;
     867
     868            cbSrc -= 4 + pIter->LX_nBytes;
     869            if (cbSrc < -4)
     870                return KLDR_ERR_LX_BAD_ITERDATA;
     871
     872            for (i = pIter->LX_nIter; i > 0; i--, pbDst += pIter->LX_nBytes)
     873                memcpy(pbDst, &pIter->LX_Iterdata, pIter->LX_nBytes);
     874            pIter   = (struct LX_Iter *)((char*)pIter + 4 + pIter->LX_nBytes);
     875        }
     876    }
     877
     878    /*
     879     * Zero remainder of the page.
     880     */
     881    if (cbDst > 0)
     882        kLdrHlpMemSet(pbDst, 0, cbDst);
     883
     884    return 0;
     885}
     886
     887
     888/**
     889 * Unpacks iterdata (aka EXEPACK).
     890 *
     891 * @returns 0 on success, non-zero kLdr status code on failure.
     892 * @param   pbDst       Where to put the uncompressed data. (Assumes OBJPAGELEN size.)
     893 * @param   pbSrc       The compressed source data.
     894 * @param   cbSrc       The file size of the compressed data. The source buffer
     895 *                      contains 4 additional zero bytes.
     896 */
     897static int kldrModLXDoIterData2Unpacking(uint8_t *pbDst, const uint8_t *pbSrc, int cbSrc)
     898{
     899    int cbDst = OBJPAGELEN;
     900
     901    while (cbSrc > 0)
     902    {
     903        /*
     904         * Bit 0 and 1 is the encoding type.
     905         */
     906        switch (*pbSrc & 0x03)
     907        {
     908            /*
     909             *
     910             *  0  1  2  3  4  5  6  7
     911             *  type  |              |
     912             *        ----------------
     913             *             cb         <cb bytes of data>
     914             *
     915             * Bits 2-7 is, if not zero, the length of an uncompressed run
     916             * starting at the following byte.
     917             *
     918             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
     919             *  type  |              |  |                    | |                     |
     920             *        ----------------  ---------------------- -----------------------
     921             *             zero                 cb                 char to multiply
     922             *
     923             * If the bits are zero, the following two bytes describes a 1 byte interation
     924             * run. First byte is count, second is the byte to copy. A count of zero is
     925             * means end of data, and we simply stops. In that case the rest of the data
     926             * should be zero.
     927             */
     928            case 0:
     929            {
     930                if (*pbSrc)
     931                {
     932                    const int cb = *pbSrc >> 2;
     933                    cbDst -= cb;
     934                    if (cbDst < 0)
     935                        return KLDR_ERR_LX_BAD_ITERDATA2;
     936                    cbSrc -= cb;
     937                    if (cbSrc < 0)
     938                        return KLDR_ERR_LX_BAD_ITERDATA2;
     939                    kLdrHlpMemCopy(pbDst, ++pbSrc, cb);
     940                    pbDst += cb;
     941                    pbSrc += cb;
     942                }
     943                else if (cbSrc < 2)
     944                    return KLDR_ERR_LX_BAD_ITERDATA2;
     945                else
     946                {
     947                    const int cb = pbSrc[1];
     948                    if (!cb)
     949                        goto l_endloop;
     950                    cbDst -= cb;
     951                    if (cbDst < 0)
     952                        return KLDR_ERR_LX_BAD_ITERDATA2;
     953                    cbSrc -= 3;
     954                    if (cbSrc < 0)
     955                        return KLDR_ERR_LX_BAD_ITERDATA2;
     956                    memset(pbDst, pbSrc[2], cb);
     957                    pbDst += cb;
     958                    pbSrc += 3;
     959                }
     960                break;
     961            }
     962
     963
     964            /*
     965             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
     966             *  type  |  |  |     |  |                       |
     967             *        ----  -------  -------------------------
     968             *        cb1   cb2 - 3          offset            <cb1 bytes of data>
     969             *
     970             * Two bytes layed out as described above, followed by cb1 bytes of data to be copied.
     971             * The cb2(+3) and offset describes an amount of data to be copied from the expanded
     972             * data relative to the current position. The data copied as you would expect it to be.
     973             */
     974            case 1:
     975            {
     976                cbSrc -= 2;
     977                if (cbSrc < 0)
     978                    return KLDR_ERR_LX_BAD_ITERDATA2;
     979                else
     980                {
     981                    const unsigned  off = ((unsigned)pbSrc[1] << 1) | (*pbSrc >> 7);
     982                    const int       cb1 = (*pbSrc >> 2) & 3;
     983                    const int       cb2 = ((*pbSrc >> 4) & 7) + 3;
     984
     985                    pbSrc += 2;
     986                    cbSrc -= cb1;
     987                    if (cbSrc < 0)
     988                        return KLDR_ERR_LX_BAD_ITERDATA2;
     989                    cbDst -= cb1;
     990                    if (cbDst < 0)
     991                        return KLDR_ERR_LX_BAD_ITERDATA2;
     992                    kLdrHlpMemCopy(pbDst, pbSrc, cb1);
     993                    pbDst += cb1;
     994
     995                    if (off > OBJPAGELEN - cbDst)
     996                        return KLDR_ERR_LX_BAD_ITERDATA2;
     997                    cbDst -= cb2;
     998                    if (cbDst < 0)
     999                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1000                    kLdrHlpMemMove(pbDst, pbDst - off, cb2);
     1001                    pbDst += cb2;
     1002                }
     1003                break;
     1004            }
     1005
     1006
     1007            /*
     1008             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15
     1009             *  type  |  |  |                                |
     1010             *        ----  ----------------------------------
     1011             *       cb-3               offset
     1012             *
     1013             * Two bytes layed out as described above.
     1014             * The cb(+3) and offset describes an amount of data to be copied from the expanded
     1015             * data relative to the current position.
     1016             *
     1017             * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
     1018             */
     1019            case 2:
     1020            {
     1021                cbSrc -= 2;
     1022                if (cbSrc < 0)
     1023                    return KLDR_ERR_LX_BAD_ITERDATA2;
     1024                else
     1025                {
     1026                    const unsigned  off = ((unsigned)pbSrc[2] << 4) | (*pbSrc >> 4);
     1027                    const int       cb = ((*pbSrc >> 2) & 3) + 3;
     1028
     1029                    pbSrc += 2;
     1030                    if (off > OBJPAGELEN - cbDst)
     1031                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1032                    cbDst -= cb;
     1033                    if (cbDst < 0)
     1034                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1035                    kLdrModLXMemCopyW(pbDst, pbDst - off, cb);
     1036                    pbDst += cb;
     1037                }
     1038                break;
     1039            }
     1040
     1041
     1042            /*
     1043             *  0  1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
     1044             *  type  |        |  |              |  |                                |
     1045             *        ----------  ----------------  ----------------------------------
     1046             *           cb1            cb2                      offset                <cb1 bytes of data>
     1047             *
     1048             * Three bytes layed out as described above, followed by cb1 bytes of data to be copied.
     1049             * The cb2 and offset describes an amount of data to be copied from the expanded
     1050             * data relative to the current position.
     1051             *
     1052             * If offset == 1 the data is not copied as expected, but in the memcpyw manner.
     1053             */
     1054            case 3:
     1055            {
     1056                cbSrc -= 3;
     1057                if (cbSrc < 0)
     1058                    return KLDR_ERR_LX_BAD_ITERDATA2;
     1059                else
     1060                {
     1061                    const int       cb1 = (*pbSrc >> 2) & 0xf;
     1062                    const int       cb2 = ((pbSrc[1] & 0xf) << 2) | (*pbSrc >> 6);
     1063                    const unsigned  off = ((unsigned)pbSrc[2] << 4) | (pbSrc[1] >> 4);
     1064
     1065                    pbSrc += 3;
     1066                    cbSrc -= cb1;
     1067                    if (cbSrc < 0)
     1068                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1069                    cbDst -= cb1;
     1070                    if (cbDst < 0)
     1071                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1072                    kLdrHlpMemCopy(pbDst, pbSrc, cb1);
     1073                    pbDst += cb1;
     1074
     1075                    if (off > OBJPAGELEN - cbDst)
     1076                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1077                    cbDst -= cb2;
     1078                    if (cbDst < 0)
     1079                        return KLDR_ERR_LX_BAD_ITERDATA2;
     1080                    kLdrModLXMemCopyW(pbDst, pbDst - off, cb2);
     1081                    pbDst += cb2;
     1082                }
     1083                break;
     1084            }
     1085        } /* type switch. */
     1086    } /* unpack loop */
     1087
     1088l_endloop:
     1089
     1090
     1091    /*
     1092     * Zero remainder of the page.
     1093     */
     1094    if (cbDst > 0)
     1095        kLdrHlpMemSet(pbDst, 0, cbDst);
     1096
     1097    return 0;
     1098}
     1099
     1100
     1101/**
     1102 * Special memcpy employed by the iterdata2 algorithm.
     1103 *
     1104 * Emulate a 16-bit memcpy (copying 16-bit at a time) and the effects this
     1105 * has if src is very close to the destination.
     1106 *
     1107 * @param   pbDst   Destination pointer.
     1108 * @param   pbSrc   Source pointer. Will always be <= pbDst.
     1109 * @param   cb      Amount of data to be copied.
     1110 * @remark  This assumes that unaligned word and dword access is fine.
     1111 */
     1112static void kLdrModLXMemCopyW(uint8_t *pbDst, const uint8_t *pbSrc, int cb)
     1113{
     1114    switch (pbDst - pbSrc)
     1115    {
     1116        case 0:
     1117        case 1:
     1118        case 2:
     1119        case 3:
     1120            /* 16-bit copy (unaligned) */
     1121            if (cb & 1)
     1122                *pbDst++ = *pbDst++;
     1123            for (cb >>= 1; cb > 0; cb--, pbDst += 2, pbSrc += 2)
     1124                *(uint16_t *)pbDst = *(const uint16_t *)pbSrc;
     1125            break;
     1126
     1127        default:
     1128            /* 32-bit copy (unaligned) */
     1129            if (cb & 1)
     1130                *pbDst++ = *pbDst++;
     1131            if (cb & 2)
     1132            {
     1133                *(uint16_t *)pbDst = *(const uint16_t *)pbSrc;
     1134                pbDst += 2;
     1135                pbSrc += 2;
     1136            }
     1137            for (cb >>= 2; cb > 0; cb--, pbDst += 4, pbSrc += 4)
     1138                *(uint32_t *)pbDst = *(const uint32_t *)pbSrc;
     1139            break;
     1140    }
    7251141}
    7261142
Note: See TracChangeset for help on using the changeset viewer.