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

📄 powerpc-darwin.macho-main.c

📁 UPX 源代码
💻 C
字号:
/* powerpc-darwin.macho-main.c -- loader stub for Mach-o PowerPC32   This file is part of the UPX executable compressor.   Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer   Copyright (C) 1996-2007 Laszlo Molnar   Copyright (C) 2000-2007 John F. Reiser   All Rights Reserved.   UPX and the UCL library are free software; you can redistribute them   and/or modify them under the terms of the GNU General Public License as   published by the Free Software Foundation; either version 2 of   the License, or (at your option) any later version.   This program is distributed in the hope that it will be useful,   but WITHOUT ANY WARRANTY; without even the implied warranty of   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the   GNU General Public License for more details.   You should have received a copy of the GNU General Public License   along with this program; see the file COPYING.   If not, write to the Free Software Foundation, Inc.,   59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.   Markus F.X.J. Oberhumer              Laszlo Molnar   <mfx@users.sourceforge.net>          <ml1050@users.sourceforge.net>   John F. Reiser   <jreiser@users.sourceforge.net> */#include "include/darwin.h"/*************************************************************************// configuration section**************************************************************************/// In order to make it much easier to move this code at runtime and execute// it at an address different from it load address:  there must be no// static data, and no string constants./*************************************************************************// "file" util**************************************************************************/typedef struct {    size_t size;  // must be first to match size[0] uncompressed size    char *buf;} Extent;static voidxread(Extent *x, char *buf, size_t count){    char *p=x->buf, *q=buf;    size_t j;    if (x->size < count) {        exit(127);    }    for (j = count; 0!=j--; ++p, ++q) {        *q = *p;    }    x->buf  += count;    x->size -= count;}/*************************************************************************// util**************************************************************************/#if 1  //{  save space#define ERR_LAB error: exit(127);#define err_exit(a) goto error#else  //}{  save debugging time#define ERR_LABstatic voiderr_exit(int a){    (void)a;  // debugging convenience    exit(127);}#endif  //}/*************************************************************************// UPX & NRV stuff**************************************************************************/struct l_info { // 12-byte trailer for loader (after macho headers)    unsigned l_checksum;    unsigned l_magic;  // UPX_MAGIC_LE32    unsigned short l_lsize;    unsigned char l_version;    unsigned char l_format;};struct p_info { // 12-byte packed program header    unsigned p_progid;    unsigned p_filesize;    unsigned p_blocksize;};struct b_info { // 12-byte header before each compressed block    unsigned sz_unc;  // uncompressed_size    unsigned sz_cpr;  //   compressed_size    unsigned char b_method;  // compression algorithm    unsigned char b_ftid;  // filter id    unsigned char b_cto8;  // filter parameter    unsigned char b_unused;};typedef void f_unfilter(    nrv_byte *,  // also addvalue    nrv_uint,    unsigned cto8, // junk in high 24 bits    unsigned ftid);typedef int f_expand(    const nrv_byte *, nrv_uint,          nrv_byte *, nrv_uint *, unsigned );static voidunpackExtent(    Extent *const xi,  // input    Extent *const xo,  // output    f_expand *const f_decompress,    f_unfilter *f_unf){    while (xo->size) {        struct b_info h;        //   Note: if h.sz_unc == h.sz_cpr then the block was not        //   compressible and is stored in its uncompressed form.        // Read and check block sizes.        xread(xi, (char *)&h, sizeof(h));        if (h.sz_unc == 0) {                     // uncompressed size 0 -> EOF            if (h.sz_cpr != UPX_MAGIC_LE32)      // h.sz_cpr must be h->magic                err_exit(2);            if (xi->size != 0)                 // all bytes must be written                err_exit(3);            break;        }        if (h.sz_cpr <= 0) {            err_exit(4);ERR_LAB        }        if (h.sz_cpr > h.sz_unc        ||  h.sz_unc > xo->size ) {            err_exit(5);        }        // Now we have:        //   assert(h.sz_cpr <= h.sz_unc);        //   assert(h.sz_unc > 0 && h.sz_unc <= blocksize);        //   assert(h.sz_cpr > 0 && h.sz_cpr <= blocksize);        if (h.sz_cpr < h.sz_unc) { // Decompress block            nrv_uint out_len = h.sz_unc;  // EOF for lzma            int const j = (*f_decompress)(xi->buf, h.sz_cpr,                xo->buf, &out_len, h.b_method);            if (j != 0 || out_len != (nrv_uint)h.sz_unc)                err_exit(7);            if (h.b_ftid!=0 && f_unf) {  // have filter                (*f_unf)(xo->buf, out_len, h.b_cto8, h.b_ftid);            }            xi->buf  += h.sz_cpr;            xi->size -= h.sz_cpr;        }        else { // copy literal block            xread(xi, xo->buf, h.sz_cpr);        }        xo->buf  += h.sz_unc;        xo->size -= h.sz_unc;    }}static voidupx_bzero(char *p, size_t len){    if (len) do {        *p++= 0;    } while (--len);}#define bzero upx_bzero// The PF_* and PROT_* bits are {1,2,4}; the conversion table fits in 32 bits.#define REP8(x) \    ((x)|((x)<<4)|((x)<<8)|((x)<<12)|((x)<<16)|((x)<<20)|((x)<<24)|((x)<<28))#define EXP8(y) \    ((1&(y)) ? 0xf0f0f0f0 : (2&(y)) ? 0xff00ff00 : (4&(y)) ? 0xffff0000 : 0)#define PF_TO_PROT(pf) \    ((PROT_READ|PROT_WRITE|PROT_EXEC) & ( \        ( (REP8(PROT_EXEC ) & EXP8(PF_X)) \         |(REP8(PROT_READ ) & EXP8(PF_R)) \         |(REP8(PROT_WRITE) & EXP8(PF_W)) \        ) >> ((pf & (PF_R|PF_W|PF_X))<<2) ))typedef struct {    unsigned magic;    unsigned nfat_arch;} Fat_header;typedef struct {    unsigned cputype;    unsigned cpusubtype;    unsigned offset;    unsigned size;    unsigned align;  /* power of 2 */} Fat_arch;    enum e8 {        FAT_MAGIC = 0xcafebabe    };    enum e9 {        CPU_TYPE_I386      =          7,        CPU_TYPE_POWERPC   = 0x00000012,        CPU_TYPE_POWERPC64 = 0x01000012    };typedef struct {    unsigned magic;    unsigned cputype;    unsigned cpysubtype;    unsigned filetype;    unsigned ncmds;    unsigned sizeofcmds;    unsigned flags;} Mach_header;        enum e0 {            MH_MAGIC = 0xfeedface        };        enum e2 {            MH_EXECUTE = 2        };        enum e3 {            MH_NOUNDEFS = 1        };typedef struct {    unsigned cmd;    unsigned cmdsize;} Mach_load_command;        enum e4 {            LC_SEGMENT       = 0x1,            LC_THREAD        = 0x4,            LC_UNIXTHREAD    = 0x5,            LC_LOAD_DYLINKER = 0xe        };typedef struct {    unsigned cmd;    unsigned cmdsize;    char segname[16];    unsigned vmaddr;    unsigned vmsize;    unsigned fileoff;    unsigned filesize;    unsigned maxprot;    unsigned initprot;    unsigned nsects;    unsigned flags;} Mach_segment_command;        enum e5 {            VM_PROT_READ = 1,            VM_PROT_WRITE = 2,            VM_PROT_EXECUTE = 4        };typedef struct {    unsigned srr0;      /* Instruction address register (PC; entry addr) */    unsigned srr1;      /* Machine state register (supervisor) */    unsigned  r0, r1, r2, r3, r4, r5, r6, r7;    unsigned  r8, r9,r10,r11,r12,r13,r14,r15;    unsigned r16,r17,r18,r19,r20,r21,r22,r23;    unsigned r24,r25,r26,r27,r28,r29,r30,r31;    unsigned cr;        /* Condition register */    unsigned xer;       /* User's integer exception register */    unsigned lr;        /* Link register */    unsigned ctr;       /* Count register */    unsigned mq;        /* MQ register (601 only) */    unsigned vrsave;    /* Vector Save Register */} Mach_ppc_thread_state;typedef struct {    unsigned cmd;            /* LC_THREAD or  LC_UNIXTHREAD */    unsigned cmdsize;        /* total size of this command */    unsigned flavor;    unsigned count;          /* sizeof(following_thread_state)/4 */    Mach_ppc_thread_state state;} Mach_thread_command;        enum e6 {            PPC_THREAD_STATE = 1        };        enum e7 {            PPC_THREAD_STATE_COUNT = sizeof(Mach_ppc_thread_state)/4        };typedef union {    unsigned long offset;  /* from start of load command to string */    char *ptr;} Mach_lc_str;#define MAP_FIXED     0x10#define MAP_PRIVATE   0x02#define MAP_ANON    0x1000#define PROT_READ      1#define PROT_WRITE     2#define PROT_EXEC      4/* bug in crosstool/powerpc-750-linux-gnu/gcc-3.4.1-glibc-20040827:   unsigned long long off_t goes into registers (9,10) instead of (8,9).   Adjust in mmap().*/extern char *mmap(char *, size_t, unsigned, unsigned, int, /*off_t*/size_t);ssize_t pread(int, void *, size_t, /*off_t*/unsigned);  // FIXME?static Mach_ppc_thread_state const *do_xmap(    Mach_header const *const mhdr,    unsigned const fat_offset,    Extent *const xi,    int const fdi,    Mach_header **mhdrpp,    f_expand *const f_decompress,    f_unfilter *const f_unf){    Mach_segment_command const *sc = (Mach_segment_command const *)(1+ mhdr);    Mach_ppc_thread_state const *entry = 0;    unsigned j;    for ( j=0; j < mhdr->ncmds; ++j,        (sc = (Mach_segment_command const *)(sc->cmdsize + (char const *)sc))    ) if (LC_SEGMENT==sc->cmd) {        Extent xo;        size_t mlen = xo.size = sc->filesize;        char  *addr = xo.buf  =                 (char *)sc->vmaddr;        char *haddr =           sc->vmsize +                  addr;        size_t frag = (int)addr &~ PAGE_MASK;        addr -= frag;        mlen += frag;        if (0!=mlen && addr != mmap(addr, mlen, VM_PROT_READ | VM_PROT_WRITE,                MAP_FIXED | MAP_PRIVATE |                    ((xi || 0==sc->filesize) ? MAP_ANON : 0),                ((0==sc->filesize) ? -1 : fdi), sc->fileoff + fat_offset) ) {            err_exit(8);        }        if (xi && 0!=sc->filesize) {            if (0==sc->fileoff /*&& 0!=mhdrpp*/) {                *mhdrpp = (Mach_header *)addr;            }            unpackExtent(xi, &xo, f_decompress, f_unf);        }        /*bzero(addr, frag);*/  // fragment at lo end        frag = (-mlen) &~ PAGE_MASK;  // distance to next page boundary        bzero(mlen+addr, frag);  // fragment at hi end        if (0!=mlen && 0!=mprotect(addr, mlen, sc->initprot)) {            err_exit(10);ERR_LAB        }        addr += mlen + frag;  /* page boundary on hi end */        if (addr < haddr) { // need pages for .bss            if (addr != mmap(addr, haddr - addr, sc->initprot,                    MAP_FIXED | MAP_PRIVATE | MAP_ANON, -1, 0 ) ) {                err_exit(9);            }        }    }    else if (LC_UNIXTHREAD==sc->cmd || LC_THREAD==sc->cmd) {        Mach_thread_command const *const thrc = (Mach_thread_command const *)sc;        if (PPC_THREAD_STATE      ==thrc->flavor        &&  PPC_THREAD_STATE_COUNT==thrc->count ) {            entry = &thrc->state;        }    }    return entry;}/*************************************************************************// upx_main - called by our entry code//**************************************************************************/Mach_ppc_thread_state const *upx_main(    struct l_info const *const li,    size_t volatile sz_compressed,  // total length    Mach_header *const mhdr,  // temp char[sz_mhdr] for decompressing    size_t const sz_mhdr,    f_expand *const f_decompress,    f_unfilter *const f_unf,    Mach_header **const mhdrpp  // Out: *mhdrpp= &real Mach_header){    Mach_ppc_thread_state const *entry;    unsigned fat_offset = 0;    Extent xi, xo, xi0;    xi.buf  = CONST_CAST(char *, 1+ (struct p_info const *)(1+ li));  // &b_info    xi.size = sz_compressed - (sizeof(struct l_info) + sizeof(struct p_info));    xo.buf  = (char *)mhdr;    xo.size = ((struct b_info const *)xi.buf)->sz_unc;    xi0 = xi;    // Uncompress Macho headers    unpackExtent(&xi, &xo, f_decompress, 0);  // never filtered?    entry = do_xmap(mhdr, fat_offset, &xi0, -1, mhdrpp, f_decompress, f_unf);  { // Map dyld dynamic loader    Mach_load_command const *lc = (Mach_load_command const *)(1+ mhdr);    unsigned j;    for (j=0; j < mhdr->ncmds; ++j,        (lc = (Mach_load_command const *)(lc->cmdsize + (char const *)lc))    ) if (LC_LOAD_DYLINKER==lc->cmd) {        char const *const dyld_name = ((Mach_lc_str const *)(1+ lc))->offset +            (char const *)lc;        int const fdi = open(dyld_name, O_RDONLY, 0);        if (0 > fdi) {            err_exit(18);        }fat:        if ((ssize_t)sz_mhdr!=pread(fdi, (void *)mhdr, sz_mhdr, fat_offset)) {ERR_LAB            err_exit(19);        }        switch (mhdr->magic) {        case MH_MAGIC: break;        case FAT_MAGIC: {            // stupid Apple: waste code and a page fault on EVERY execve            Fat_header const *const fh = (Fat_header const *)mhdr;            Fat_arch const *fa = (Fat_arch const *)(1+ fh);            for (j= 0; j < fh->nfat_arch; ++j, ++fa) {                if (CPU_TYPE_POWERPC==fa->cputype) {                    fat_offset= fa->offset;                    goto fat;                }            }        } break;        } // switch        entry = do_xmap(mhdr, fat_offset, 0, fdi, 0, 0, 0);        close(fdi);        break;    }  }    return entry;}/*vi:ts=4:et:nowrap*/

⌨️ 快捷键说明

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