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

📄 peal.c

📁 wince下著名的视频播放器源码
💻 C
📖 第 1 页 / 共 2 页
字号:
    ptrdiff_t rw_slide;    unsigned int i;    uint32_t max_align = 1;    // find extent of r/w memory    rw_sh_addr   = 0xffffffff;    rw_sh_end    = 0;    for (i = 0; (shdr = section_for_index(m->ehdr, i)); i++) {        uint32_t sh_flags = swap32(shdr->sh_flags);        uint32_t sh_addr = swap32(shdr->sh_addr);        uint32_t sh_size = swap32(shdr->sh_size);        uint32_t sh_type = swap32(shdr->sh_type);        uint32_t sh_addralign = swap32(shdr->sh_addralign);        if ((sh_flags & SHF_ALLOC) &&             (sh_type == SHT_PROGBITS || sh_type == SHT_NOBITS))         {            if ((sh_flags & SHF_WRITE)  &&  sh_addr < rw_sh_addr) {                rw_sh_addr = sh_addr;            }            if ((sh_flags & SHF_WRITE)  &&  sh_addr + sh_size > rw_sh_end) {                rw_sh_end = sh_addr + sh_size;            }            if (sh_addralign > max_align) {                max_align = sh_addralign;            }        }    }    // allocate r/w memory    if (rw_sh_addr == 0xffffffff  ||  rw_sh_addr == rw_sh_end) {        m->rw_block = 0;        m->rw_start = 0;        rw_slide = 0;    } else {        // add leading pad to fix alignment in case first rw section        // is less aligned than other rw sections.        rw_sh_addr -= rw_sh_addr % max_align;        // add leading pad to heap block in case max_align is         // more aligned than MemGluePtrNew's result.        m->rw_block = (uintptr_t)MemGluePtrNew(rw_sh_end - rw_sh_addr + max_align);        if (!m->rw_block) return false;        m->rw_start = m->rw_block + (max_align - m->rw_block % max_align);        if (m->rw_start % max_align) return false;        rw_slide = m->rw_start - rw_sh_addr;    }    // populate r/w memory    for (i = 0; (shdr = section_for_index(m->ehdr, i)); i++) {        uint32_t sh_flags = swap32(shdr->sh_flags);        uint32_t sh_addr = swap32(shdr->sh_addr);        uint32_t sh_size = swap32(shdr->sh_size);        uint32_t sh_type = swap32(shdr->sh_type);        void *vm_addr = (void *)(sh_addr + rw_slide);        if ((sh_flags & SHF_ALLOC)  &&  (sh_flags & SHF_WRITE)  &&              (sh_type == SHT_NOBITS  ||  sh_type == SHT_PROGBITS))         {            if (sh_type == SHT_NOBITS) {                MemSet(vm_addr, sh_size, 0);  // .bss section            } else {                MemMove(vm_addr, (void *)m->sinfo[i].vm_addr, sh_size);            }            // use r/w location instead of r/o location from now on            // If this section was in a large resource, block is a             // temporary heap buffer that is now freed.            // fixme large temporary buffers suck            if (m->sinfo[i].resource) {                MemHandleUnlock(m->sinfo[i].resource);                DmReleaseResource(m->sinfo[i].resource);            } else if (m->sinfo[i].is_ftr) {				FtrPtrFree(m->prgId,m->ftrId+i);
            }            m->sinfo[i].block = m->rw_block;            m->sinfo[i].vm_addr = (uintptr_t)vm_addr;            m->sinfo[i].resource = 0;            m->sinfo[i].is_ftr = false;        }    }    // find symtab and string sections (both unique)    m->syms = NULL;    m->symcount = 0;    m->strings = 0;    for (i = 0; (shdr = section_for_index(m->ehdr, i)); i++) {        if (swap32(shdr->sh_type) == SHT_SYMTAB) {            m->syms = (Elf32_Sym *)m->sinfo[i].vm_addr;            m->symcount = swap32(shdr->sh_size) / sizeof(Elf32_Sym);        }        if (swap32(shdr->sh_type) == SHT_STRTAB) {            m->strings = (char *)m->sinfo[i].vm_addr;        }    }    // find GOT using section named .got    // This must be done AFTER the symtab, strtab, and slides are available    // This must be done BEFORE relocations are performed    m->got = 0;    for (i = 0; (shdr = section_for_index(m->ehdr, i)); i++) {        const char *name = section_name(m, shdr);        if (0 == StrNCompareAscii(name, ".got", 5)) {            m->got = m->sinfo[i].vm_addr;        }        if (0 == StrNCompareAscii(name, ".lib", 4)) {
            m->sinfo[i].is_lib = true;
        }
    }
	if (m->is_memsemaphore)
		MemSemaphoreReserve(1);

    // perform relocations    // Don't use Thumb interworkable addresses for any relocation.     // All of these symbols should be section symbols, and any     // interwork mangling should have been done by peal-postlink.    for (i = 0; (shdr = section_for_index(m->ehdr, i)); i++) {        uint32_t sh_size = swap32(shdr->sh_size);        uint32_t sh_type = swap32(shdr->sh_type);        Elf32_Rela *rel, *relend;        uint32_t dst_base;        uintptr_t dst_block;        size_t dst_size;        uint32_t dst_index;        uintptr_t dst_thunks;        if (sh_type != SHT_RELA) continue;        free_thunk_descs();        rel = (Elf32_Rela *)m->sinfo[i].vm_addr;        relend = rel + sh_size / sizeof(Elf32_Rela);                dst_index = swap32(shdr->sh_info);        dst_base = m->sinfo[dst_index].vm_addr;        dst_block = m->sinfo[dst_index].block;        dst_size = swap32(section_for_index(m->ehdr, dst_index)->sh_size);        dst_thunks = dst_base + dst_size;  // assume postlinker aligned this
        for ( ; rel < relend; rel++) {            uint32_t dst_offset;            uint32_t sym_index;            uintptr_t dst;            uint32_t addend;
			uintptr_t symbol;            dst_offset = swap32(rel->r_offset);            sym_index = ELF32_R_SYM(swap32(rel->r_info));            addend = swap32(rel->r_addend);            symbol = symbol_address(m, m->syms + sym_index, 0, common);
			if (!symbol) goto fail;
            // *dst is ARM-swapped, and may be in storage memory.             // Use poke32() to change it.            dst = dst_base + dst_offset;            switch (ELF32_R_TYPE(swap32(rel->r_info))) {            case R_ARM_PC24: {                // *dst[0-23] = ((symbol + addend - dst) - 8) / 4                // value must be SIGNED!                int32_t value = symbol + addend - (uintptr_t)dst;                if (value % 4) goto fail;                value = (value - 8) / 4;                if (value != ((value << 8) >> 8)) {                    // Relocation no longer fits in 24 bits. Use a thunk.                    uintptr_t thunk =                         generate_thunk(m, &dst_thunks, dst_block, dst,                                        symbol + addend, 0);                    if (thunk == 0) goto fail;                    // Re-aim value at the thunk.                    value = thunk - (uintptr_t)dst;                    if (value % 4) goto fail;                    value = (value - 8) / 4;                    if (value != ((value << 8) >> 8)) goto fail;                }                poke32(m,dst_block, dst,                        (value & 0x00ffffff) |                        (peek32(dst_block, dst) & 0xff000000));                break;            }            case R_ARM_THM_PC22: {                // *(dst+0)[0-10] = (((symbol + addend - dst) - 4) / 2)[11-21]                // *(dst+2)[0-10] = (((symbol + addend - dst) - 4) / 2)[0-10]                // value must be SIGNED!                int32_t value = symbol + addend - (uintptr_t)dst;                if (value % 2) goto fail;                value = (value - 4) / 2;                if (value != ((value << 10) >> 10)) {                    // Relocation no longer fits in 22 bits. Use a thunk.                    uintptr_t thunk =                         generate_thunk(m, &dst_thunks, dst_block, dst,                                        (symbol+addend) & 0xfffffffe, thumb);                    if (thunk == 0) goto fail;                    // Re-aim value at the thunk.                    value = thunk - (uintptr_t)dst;                    if (value % 2) goto fail;                    value = (value - 4) / 2;                    if (value != ((value << 10) >> 10)) goto fail;                }                poke16(m,dst_block, dst+0,                        ((value >> 11) & 0x07ff) |                        (peek16(dst_block, dst+0) & 0xf800));                poke16(m,dst_block, dst+2,                        ((value >>  0) & 0x07ff) |                        (peek16(dst_block, dst+2) & 0xf800));                break;            }            case R_ARM_ABS32:                // *dst = symbol + addend                poke32(m,dst_block, dst,                        symbol + addend);                break;            case R_ARM_REL32:                // *dst = symbol + addend - dst                 poke32(m,dst_block, dst,                        symbol + addend - (uintptr_t)dst);                break;            case R_ARM_GOTOFF:                // *dst = symbol + addend - GOT                if (!m->got) goto fail;                poke32(m,dst_block, dst,                        symbol + addend - m->got);                break;            default:                break;            }        }    }

	if (m->is_memsemaphore)
		MemSemaphoreRelease(1);
    // find ARM-side stub function    stub_sym = symbol_lookup(m, "PealArmStub", 0);    if (stub_sym) {        // Don't use a Thumb interworkable address for the stub,         // because PceNativeCall can't handle it.        m->stub = symbol_address(m, stub_sym, 0, NULL);    } else {        m->stub = 0;    }    // fixme call initializers and C++ constructors here    free_thunk_descs();    return true;

fail:
	if (m->is_memsemaphore)
		MemSemaphoreRelease(1);
	return false;}PealModule *PealLoad(void *mem){    int i;    const Elf32_Shdr *shdr;    const Elf32_Ehdr *ehdr;    PealModule *m;    ehdr = (const Elf32_Ehdr *)mem;
    m = allocate(ehdr);    if (!m) return NULL;    // find sections (contiguous version)    for (i = 0; (shdr = section_for_index(ehdr, i)); i++) {        m->sinfo[i].block = (uintptr_t)mem;        m->sinfo[i].vm_addr = ((uintptr_t)mem) + swap32(shdr->sh_offset);    }
    if (load(m,NULL)) {        return m;    } else {        cleanup(m);        return NULL;     }}Boolean isCodeSection(const Elf32_Shdr* shdr)
{
	uint32_t sh_flags = swap32(shdr->sh_flags);
	uint32_t sh_type = swap32(shdr->sh_type);

    if (sh_type == SHT_SYMTAB ||
		sh_type == SHT_STRTAB ||
		sh_type == SHT_RELA)
		return false;

    if ((sh_flags & SHF_ALLOC)  &&  (sh_flags & SHF_WRITE)  &&  
        (sh_type == SHT_NOBITS  ||  sh_type == SHT_PROGBITS))
		return false;

	return true;
}
PealModule *PealLoadFromResources(DmResType type, DmResID baseID, const PealModule *common, UInt32 prgId, UInt16 ftrId, Boolean memDup, Boolean onlyFtr, Boolean memSema){    int i;    int resID;    PealModule *m;    const Elf32_Shdr *shdr;
	Boolean rom;    MemHandle rsrcH;
    const Elf32_Ehdr *ehdr;

    rsrcH = DmGet1Resource(type, baseID);    if (!rsrcH) return NULL;    ehdr = (Elf32_Ehdr *)MemHandleLock(rsrcH);
    m = allocate(ehdr);    if (!m) {        MemHandleUnlock(rsrcH);        DmReleaseResource(rsrcH);        return NULL;    }

	m->is_memsemaphore = memSema;
	rom = DmWriteCheck((void*)ehdr,0,4) != errNone;

    // find sections (resource version)    // resource baseID+0 is ehdr+shdrs    // additional sections are in consecutive resources    // sections bigger than 65400 bytes are split into multiple resources    // section 0 (SHT_NULL) has no resource    // Use section 0's sinfo to stash ehdr's resource    resID = baseID+1;
	m->ftrId = ++ftrId;
	m->prgId = prgId;    m->sinfo[0].block = (uintptr_t)ehdr;    m->sinfo[0].vm_addr = 0;    m->sinfo[0].resource = rsrcH;

	if (memDup)
	{
		// duplicate first section (header)
		size_t resSize;
		resSize = MemHandleSize(rsrcH);

		if (FtrPtrNew(prgId,ftrId,resSize,(void**)&m->sinfo[0].block)!=errNone) {
            cleanup(m);
            return NULL;
        }
		m->ehdr = (Elf32_Ehdr *)m->sinfo[0].block;
        m->sinfo[0].vm_addr = m->sinfo[0].block;
		m->sinfo[0].is_ftr = 1;
		m->sinfo[0].resource = 0;

		DmWrite((void*)m->ehdr,0,ehdr,resSize);
        MemHandleUnlock(rsrcH);
        DmReleaseResource(rsrcH);
	}
    for (i = 1; (shdr = section_for_index(m->ehdr, i)); i++) {        uint32_t sh_type = swap32(shdr->sh_type);        uint32_t sh_size = swap32(shdr->sh_size);        size_t offset = 0;        size_t left = sh_size;        if (sh_size==0 || sh_type==SHT_NULL || sh_type==SHT_NOBITS) {            // empty section or .bss section - no resource expected            // m->sinfo[i] already zeroed            continue;        }
        do {            size_t resSize;            MemHandle rsrcH = DmGet1Resource(type, resID++);            if (!rsrcH) {                // no resource - bail                cleanup(m);                return NULL;            }            resSize = MemHandleSize(rsrcH);            if (resSize > left) {                // resource too big - bail                DmReleaseResource(rsrcH);                cleanup(m);                return NULL;            } else if (resSize == sh_size && !memDup && (!rom || !isCodeSection(shdr))) {                // resource just right - keep it                if (m->sinfo[i].block) {                    // oops, already concatenating                    DmReleaseResource(rsrcH);                    cleanup(m);                    return NULL;                }                m->sinfo[i].block = (uintptr_t)MemHandleLock(rsrcH);                m->sinfo[i].vm_addr = m->sinfo[i].block;                m->sinfo[i].resource = rsrcH;            } else {                // concatenate multiple resources                if (!m->sinfo[i].block) {
					if (i>=FTRID_STEP-1 || FtrPtrNew(prgId,ftrId+i,sh_size,(void**)&m->sinfo[i].block)!=errNone) {
                        DmReleaseResource(rsrcH);                        cleanup(m);                        return NULL;                    }                    m->sinfo[i].vm_addr = m->sinfo[i].block;                    m->sinfo[i].is_ftr = true;                }
				DmWrite((void*)m->sinfo[i].block,offset,MemHandleLock(rsrcH), resSize);                MemHandleUnlock(rsrcH);                DmReleaseResource(rsrcH);                offset += resSize;            }            left -= resSize;        } while (left > 0);    }    if (load(m,common)) {

		PealModule *m2;
		if (onlyFtr && FtrPtrNew(prgId,ftrId-1,m->size,(void**)&m2)==errNone) {
			m->is_ftr = 1;
			DmWrite(m2,0,m,m->size);
			MemPtrFree(m);
			m = m2;
		}
        return m;    } else {        cleanup(m);  // this cleanup includes rsrcH        return NULL;     }}void *PealLookupSymbol(const PealModule *m, char *query){    const Elf32_Sym *sym = symbol_lookup(m, query, 0);    // Do return Thumb interworkable addresses to client code    return sym ? (void *)symbol_address(m, sym, thumb, NULL) : NULL;}uint32_t PealCall(PealModule *m, void *addr, void *arg){    // args does not have to be aligned; ARM side handles misalignment and swap    PealArgs args;    args.fn = addr;    args.arg = arg;    args.got = (void *)m->got;    return PceNativeCall((NativeFuncType *)m->stub, &args);}void PealUnload(PealModule *m){    if (m) {        // fixme call terminators and C++ destructors here        cleanup(m);    }}

⌨️ 快捷键说明

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