⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 loader.c

📁 WinCE5.0部分核心源码
💻 C
📖 第 1 页 / 共 5 页
字号:
    ulong blocksize;
    LPDWORD FixupAddress;
#ifndef x86
    LPWORD FixupAddressHi;
    BOOL MatchedReflo=FALSE;
#endif
    DWORD FixupValue;
    LPWORD currptr;
    DWORD offset;

#if defined(x86)
#define RELOC_LIMIT 8192
#else
#define RELOC_LIMIT 4096
#endif

    DWORD reloc_limit = RELOC_LIMIT;

#ifdef MIPS
    if (IsMIPS16Supported)
        reloc_limit = 8192;
#endif

    LeaveCriticalSection(&PagerCS);
    if (!(blocksize = eptr->e32_unit[FIX].size)) { // No relocations
        EnterCriticalSection(&PagerCS);
        return TRUE;
    }
    blockstart = blockptr = (struct info *)(ZeroPtr(BasePtr)+BaseAdj+eptr->e32_unit[FIX].rva);
    if (BaseAdj != ProcArray[0].dwVMBase)
        BaseAdj = 0;    // for processes
    DEBUGMSG(ZONE_LOADER1,(TEXT("Relocations: BasePtr = %8.8lx, BaseAdj = %8.8lx, VBase = %8.8lx, pMem = %8.8lx, pData = %8.8lx\r\n"),
        BasePtr,BaseAdj, eptr->e32_vbase, pMem, pData));
    if (!(offset = BasePtr - BaseAdj - eptr->e32_vbase)) {
        EnterCriticalSection(&PagerCS);
        DEBUGMSG(ZONE_LOADER1,(TEXT("Relocations: No Relocation Required\r\n")));
        return TRUE;                                                    // no adjustment needed
    }
    DEBUGMSG(ZONE_LOADER1,(TEXT("RelocatePage: Offset is %8.8lx\r\n"),offset));
    if ((ZeroPtr(pMem) >= ZeroPtr(BasePtr+eptr->e32_unit[FIX].rva)) &&
        (ZeroPtr(pMem) < ZeroPtr(BasePtr+eptr->e32_unit[FIX].rva+eptr->e32_unit[FIX].size))) {
        EnterCriticalSection(&PagerCS);
        return TRUE;
    }
    while (((ulong)blockptr < (ulong)blockstart + blocksize) && blockptr->size) {
        currptr = (LPWORD)(((ulong)blockptr)+sizeof(struct info));
        if ((ulong)currptr >= ((ulong)blockptr+blockptr->size)) {
            blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
            continue;
        }
        if ((ZeroPtr(BasePtr+blockptr->rva) > ZeroPtr(pMem)) || (ZeroPtr(BasePtr+blockptr->rva)+reloc_limit <= ZeroPtr(pMem))) {
            blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
            continue;
        }
        goto fixuppage;
    }
    EnterCriticalSection(&PagerCS);
    return TRUE;
fixuppage:
    DEBUGMSG(ZONE_LOADER1,(L"Fixing up %8.8lx %8.8lx, %8.8lx\r\n",blockptr->rva,optr->o32_rva,optr->o32_realaddr));
    while ((ulong)currptr < ((ulong)blockptr+blockptr->size)) {
#ifdef x86
        Comp1 = ZeroPtr(pMem);
        Comp2 = ZeroPtr(BasePtr + blockptr->rva);
        Comp1 = (Comp2 + 0x1000 == Comp1) ? 1 : 0;
#else
        Comp1 = ZeroPtr(pMem) - ZeroPtr(BasePtr + blockptr->rva);
        Comp2 = (DWORD)(*currptr&0xfff);
#if defined(MIPS)
        // Comp1 is relative start of page being relocated
        // Comp2 is relative address of fixup
        // For MIPS16 jump, deal with fixups on this page or the preceding page
        // For all other fixups, deal with this page only
        if (IsMIPS16Supported && (*currptr>>12 == IMAGE_REL_BASED_MIPS_JMPADDR16)) {
            if ((Comp1 > Comp2 + PAGE_SIZE) || (Comp1 + PAGE_SIZE <= Comp2)) {
                currptr++;
                continue;
            }
            // PrevPage: is fixup located on the page preceding the one being relocated?
            PrevPage = (Comp1 > Comp2);
            // Comp1: is fixup located in the block preceding the one that contains the current page?
            Comp1 = PrevPage && ((Comp1 & 0xfff) == 0);
        } else {
#endif
            if ((Comp1 > Comp2) || (Comp1 + PAGE_SIZE <= Comp2)) {
                if (*currptr>>12 == IMAGE_REL_BASED_HIGHADJ)
                    currptr++;
                currptr++;
                continue;
            }
#if defined(MIPS)
            // Comp1: is fixup located in the block preceding the one that contains the current page? (No.)
            if (IsMIPS16Supported)
                Comp1 = 0;
        }
#endif
#endif
#if defined(x86)
        FixupAddress = (LPDWORD)(((pData&0xfffff000) + (*currptr&0xfff)) - 4096*Comp1);
#else
        FixupAddress = (LPDWORD)((pData&0xfffff000) + (*currptr&0xfff));
#ifdef MIPS
        if (IsMIPS16Supported)
            FixupAddress = (LPDWORD) (FixupAddress - 4096*Comp1);
#endif
#endif
        DEBUGMSG(ZONE_LOADER2,(TEXT("type %d, low %8.8lx, page %8.8lx, addr %8.8lx\r\n"),
            (*currptr>>12)&0xf, (*currptr)&0x0fff,blockptr->rva,FixupAddress));
        switch (*currptr>>12) {
            case IMAGE_REL_BASED_ABSOLUTE: // Absolute - no fixup required.
                break;
#ifdef x86
            case IMAGE_REL_BASED_HIGHLOW: // Word - (32-bits) relocate the entire address.
                if (Comp1 && (((DWORD)FixupAddress & 0xfff) > 0xffc)) {
                    switch ((DWORD)FixupAddress & 0x3) {
                        case 1:
                            FixupValue = (prevdw>>8) + (*((LPBYTE)FixupAddress+3) <<24 ) + offset;
                            *((LPBYTE)FixupAddress+3) = (BYTE)(FixupValue >> 24);
                            break;
                        case 2:
                            FixupValue = (prevdw>>16) + (*((LPWORD)FixupAddress+1) << 16) + offset;
                            *((LPWORD)FixupAddress+1) = (WORD)(FixupValue >> 16);
                            break;
                        case 3:
                            FixupValue = (prevdw>>24) + ((*(LPDWORD)((LPBYTE)FixupAddress+1)) << 8) + offset;
                            *(LPWORD)((LPBYTE)FixupAddress+1) = (WORD)(FixupValue >> 8);
                            *((LPBYTE)FixupAddress+3) = (BYTE)(FixupValue >> 24);
                            break;
                    }
                } else if (!Comp1) {
                    if (((DWORD)FixupAddress & 0xfff) > 0xffc) {
                        switch ((DWORD)FixupAddress & 0x3) {
                            case 1:
                                FixupValue = *(LPWORD)FixupAddress + (((DWORD)*((LPBYTE)FixupAddress+2))<<16) + offset;
                                *(LPWORD)FixupAddress = (WORD)FixupValue;
                                *((LPBYTE)FixupAddress+2) = (BYTE)(FixupValue>>16);
                                break;
                            case 2:
                                *(LPWORD)FixupAddress += (WORD)offset;
                                break;
                            case 3:
                                *(LPBYTE)FixupAddress += (BYTE)offset;
                                break;
                        }
                    } else
                        *FixupAddress += offset;
                }
                break;
#else
            case IMAGE_REL_BASED_HIGH: // Save the address and go to get REF_LO paired with this one
                FixupAddressHi = (LPWORD)FixupAddress;
                MatchedReflo = TRUE;
                break;
            case IMAGE_REL_BASED_LOW: // Low - (16-bit) relocate high part too.
                if (MatchedReflo) {
                    FixupValue = (DWORD)(long)((*FixupAddressHi) << 16) +
                        *(LPWORD)FixupAddress + offset;
                    *FixupAddressHi = (short)((FixupValue + 0x8000) >> 16);
                    MatchedReflo = FALSE;
                } else
                    FixupValue = *(short *)FixupAddress + offset;
                *(LPWORD)FixupAddress = (WORD)(FixupValue & 0xffff);
                break;
            case IMAGE_REL_BASED_HIGHLOW: // Word - (32-bits) relocate the entire address.
                    if ((DWORD)FixupAddress & 0x3)
                        *(UNALIGNED DWORD *)FixupAddress += (DWORD)offset;
                    else
                        *FixupAddress += (DWORD)offset;
                break;
            case IMAGE_REL_BASED_HIGHADJ: // 32 bit relocation of 16 bit high word, sign extended
                DEBUGMSG(ZONE_LOADER2,(TEXT("Grabbing extra data %8.8lx\r\n"),*(currptr+1)));
                *(LPWORD)FixupAddress += (WORD)((*(short *)(++currptr)+offset+0x8000)>>16);
                break;
            case IMAGE_REL_BASED_MIPS_JMPADDR: // jump to 26 bit target (shifted left 2)
                FixupValue = ((*FixupAddress)&0x03ffffff) + (offset>>2);
                *FixupAddress = (*FixupAddress & 0xfc000000) | (FixupValue & 0x03ffffff);
                break;
#if defined(MIPS)
            case IMAGE_REL_BASED_MIPS_JMPADDR16: // MIPS16 jal/jalx to 26 bit target (shifted left 2)
                if (IsMIPS16Supported) {
                    if (PrevPage && (((DWORD)FixupAddress & (PAGE_SIZE-1)) == PAGE_SIZE-2)) {
                        // Relocation is on previous page, crossing into the current one
                        // Do this page's portion == last 2 bytes of jal/jalx == least-signif 16 bits of address
                        *((LPWORD)FixupAddress+1) += (WORD)(offset >> 2);
                        break;
                    } else if (!PrevPage) {
                        // Relocation is on this page. Put the most-signif bits in FixupValue
                        FixupValue = (*(LPWORD)FixupAddress) & 0x03ff;
                        FixupValue = ((FixupValue >> 5) | ((FixupValue & 0x1f) << 5)) << 16;
                        if (((DWORD)FixupAddress & (PAGE_SIZE-1)) == PAGE_SIZE-2) {
                            // We're at the end of the page. prevdw has the 2 bytes we peeked at on the next page,
                            // so use them instead of loading them from FixupAddress+1
                            FixupValue |= (WORD)prevdw;
                            FixupValue += offset >> 2;
                        } else {
                            // All 32 bits are on this page. Go ahead and fixup last 2 bytes
                            FixupValue |= *((LPWORD)FixupAddress+1);
                            FixupValue += offset >> 2;
                            *((LPWORD)FixupAddress+1) = (WORD)(FixupValue & 0xffff);
                        }
                        // In either case, we now have the right bits for the upper part of the address
                        // Rescramble them and put them in the first 2 bytes of the fixup
                        FixupValue = (FixupValue >> 16) & 0x3ff;
                        *(LPWORD)FixupAddress = (WORD)((*(LPWORD)FixupAddress & 0xfc00) | (FixupValue >> 5) | ((FixupValue & 0x1f) << 5));
                    }
                }
                break;
#endif
#endif
            default :
                DEBUGMSG(ZONE_LOADER1,(TEXT("Not doing fixup type %d\r\n"),*currptr>>12));
                DEBUGCHK(0);
                break;
        }
        //DEBUGMSG(ZONE_LOADER2,(TEXT("reloc complete, new op %8.8lx\r\n"),*FixupAddress));
        currptr++;
    }
#ifdef MIPS
    if (IsMIPS16Supported) {
#endif
#if defined(x86) || defined(MIPS)
    if (Comp1) {
        blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
        if (((ulong)blockptr < (ulong)blockstart + blocksize) && blockptr->size) {
            currptr = (LPWORD)(((ulong)blockptr)+sizeof(struct info));
            if ((ulong)currptr < ((ulong)blockptr+blockptr->size))
                if ((ZeroPtr(BasePtr+blockptr->rva) <= ZeroPtr(pMem)) && (ZeroPtr(BasePtr+blockptr->rva)+4096 > ZeroPtr(pMem)))
                    goto fixuppage;
        }
    }
#endif
#ifdef MIPS
    }
#endif
    EnterCriticalSection(&PagerCS);
    return TRUE;
}



//------------------------------------------------------------------------------
// Relocate a DLL or EXE
//------------------------------------------------------------------------------
#pragma prefast(disable: 11, "if dataptr is NULL, we'll except anyway")
BOOL
Relocate(
    e32_lite *eptr,
    o32_lite *oarry,
    ulong BasePtr,
    ulong BaseAdj
    )
{
    o32_lite *dataptr;
    struct info *blockptr, *blockstart;
    ulong blocksize;
    LPDWORD FixupAddress;
    LPWORD FixupAddressHi, currptr;
    WORD curroff;
    DWORD FixupValue, offset;
    BOOL MatchedReflo=FALSE;
    int loop;
    BOOL fRet = TRUE;

    DEBUGMSG(ZONE_LOADER1,(TEXT("Relocations: BasePtr = %8.8lx, BaseAdj = %8.8lx, VBase = %8.8lx\r\n"),
            BasePtr,BaseAdj, eptr->e32_vbase));
    __try {
        if ((blocksize = eptr->e32_unit[FIX].size)                         // has relocations, and
            && (offset = BasePtr - BaseAdj - eptr->e32_vbase)) {           // adjustment needed

            DEBUGMSG(ZONE_LOADER1,(TEXT("Relocate: Offset is %8.8lx\r\n"),offset));
            blockstart = blockptr = (struct info *)(BasePtr+eptr->e32_unit[FIX].rva);
            while (((ulong)blockptr < (ulong)blockstart + blocksize) && blockptr->size) {
                currptr = (LPWORD)(((ulong)blockptr)+sizeof(struct info));
                if ((ulong)currptr >= ((ulong)blockptr+blockptr->size)) {
                    blockptr = (struct info *)(((ulong)blockptr)+blockptr->size);
                    continue;
                }
                dataptr = 0;
                while ((ulong)currptr < ((ulong)blockptr+blockptr->size)) {
                    curroff = *currptr&0xfff;
                    if (!curroff && !blockptr->rva) {
                        currptr++;
                        continue;
                    }
                    if (!dataptr || (dataptr->o32_rva > blockptr->rva + curroff) ||
                            (dataptr->o32_rva + dataptr->o32_vsize <= blockptr->rva + curroff)) {
                        for (loop = 0; loop < eptr->e32_objcnt; loop++) {
                            dataptr = &oarry[loop];
                            if ((dataptr->o32_rva <= blockptr->rva + curroff) &&
                                (dataptr->o32_rva+dataptr->o32_vsize > blockptr->rva + curroff))
                                break;
                        }
                    }
                    DEBUGCHK(loop != eptr->e32_objcnt);
                    FixupAddress = (LPDWORD)(blockptr->rva - dataptr->o32_rva + curroff + dataptr->o32_realaddr);
                    DEBUGMSG(ZONE_LOADER2,(TEXT("type %d, low %8.8lx, page %8.8lx, addr %8.8lx, op %8.8lx\r\n"),
                        (*currptr>>12)&0xf, (*currptr)&0x0fff,blockptr->rva,FixupAddress,*FixupAddress));
                    switch (*currptr>>12) {
                        case IMAGE_REL_BASED_ABSOLUTE: // Absolute - no fixup required.
                            break;
                        case IMAGE_REL_BASED_HIGH: // Save the address and go to get REF_LO paired with this one
                            FixupAddressHi = (LPWORD)FixupAddress;
                            MatchedReflo = TRUE;
                            break;
                        case IMAGE_REL_BASED_LOW: // Low - (16-bit) relocate high part too.
                            if (MatchedReflo) {
                                FixupValue = (DWORD)(long)((*FixupAddressHi) << 16) +
                                    *(LPWORD)FixupAddress + offset;
                                *FixupAddressHi = (short)((FixupValue + 0x8000) >> 16);
                                MatchedReflo = FALSE;
                            } else
                                FixupValue = *(short *)FixupAddress + offset;
                            *(LPWORD)FixupAddress = (WORD)(FixupValue & 0xffff);
                            break;
                        case IMAGE_REL_BASED_HIGHLOW: // Word - (32-bits) relocate the entire address.
                            if ((DWORD)FixupAddress & 0x3)
                                *(UNALIGNED DWORD *)FixupAddress += (DWORD)offset;
                            else
                                *FixupAddress += (DWORD)offset;
                            break;
                        case IMAGE_REL_BASED_HIGHADJ: // 32 bit relocation of 16 bit high word, sign extended
                            DEBUGMSG(ZONE_LOADER2,(TEXT("Grabbing extra data %8.8lx\r\n"),*(currptr+1)));
                            *(LPWORD)FixupAddress += (WORD)((*(short *)(++currptr)+offset+0x8000)>>16);
                            break;
                        case IMAGE_REL_BASED_MIPS_JMPADDR: // jump to 26 bit target (shifted left 2)
                            FixupValue = ((*FixupAddress)&0x03ffffff) + (offset>>2);
                            *FixupAddress = (*FixupAddress & 0xfc000000) | (FixupValue & 0x03ffffff);
                            break;
#if defined(MIPS)
                        case IMAGE_REL_BASED_MIPS_JMPADDR16: // MIPS16 jal/jalx to 26 bit target (shifted left 2)
                            if (IsMIPS16Supported) {
                                FixupValue = (*(LPWORD)FixupAddress) & 0x03ff;
                                FixupValue = (((FixupValue >> 5) | ((FixupValue & 0x1f) << 5)) << 16) | *((LPWORD)FixupAddress+1);
                                FixupValue += offset >> 2;
                                *((LPWORD

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -