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

📄 p_mach.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* p_mach.cpp -- pack Mach Object executable   This file is part of the UPX executable compressor.   Copyright (C) 2004-2007 John 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.   John Reiser   jreiser@users.sourceforge.net */#include "conf.h"#include "file.h"#include "filter.h"#include "linker.h"#include "packer.h"#include "p_mach.h"#include "ui.h"static const#include "stub/powerpc-darwin.macho-entry.h"static const#include "stub/powerpc-darwin.macho-fold.h"static const#include "stub/i386-darwin.macho-entry.h"static const#include "stub/i386-darwin.macho-fold.h"template <class T>PackMachBase<T>::PackMachBase(InputFile *f, unsigned cputype, unsigned flavor,        unsigned count, unsigned size) :    super(f), my_cputype(cputype), my_thread_flavor(flavor),    my_thread_state_word_count(count), my_thread_command_size(size),    n_segment(0), rawmseg(NULL), msegcmd(NULL){    MachClass::compileTimeAssertions();    bele = N_BELE_CTP::getRTP<BeLePolicy>();}template <class T>PackMachBase<T>::~PackMachBase(){    delete [] rawmseg;    delete [] msegcmd;}template <class T>const int *PackMachBase<T>::getCompressionMethods(int method, int level) const{    // There really is no LE bias.    return Packer::getDefaultCompressionMethods_le32(method, level);}const int *PackMachPPC32::getFilters() const{    static const int filters[] = { 0xd0, FT_END };    return filters;}int const *PackMachI386::getFilters() const{    static const int filters[] = { 0x49, FT_END };    return filters;}Linker *PackMachPPC32::newLinker() const{    return new ElfLinkerPpc32;}Linker *PackMachI386::newLinker() const{    return new ElfLinkerX86;}template <class T>voidPackMachBase<T>::addStubEntrySections(Filter const *){    addLoader("MACOS000", NULL);   //addLoader(getDecompressorSections(), NULL);    addLoader(        ( M_IS_NRV2E(ph.method) ? "NRV_HEAD,NRV2E,NRV_TAIL"        : M_IS_NRV2D(ph.method) ? "NRV_HEAD,NRV2D,NRV_TAIL"        : M_IS_NRV2B(ph.method) ? "NRV_HEAD,NRV2B,NRV_TAIL"        : M_IS_LZMA(ph.method)  ? "LZMA_ELF00,LZMA_DEC20,LZMA_DEC30"        : NULL), NULL);    addLoader("ELFMAINY,IDENTSTR,+40,ELFMAINZ,FOLDEXEC", NULL);}void PackMachI386::addStubEntrySections(Filter const *ft){    int const n_mru = ft->n_mru;  // FIXME: belongs to filter? packerf?            // entry to stub    addLoader("LEXEC000", NULL);    if (ft->id) {        { // decompr, unfilter are separate            addLoader("LXUNF000", NULL);            addLoader("LXUNF002", NULL);                if (0x80==(ft->id & 0xF0)) {                    if (256==n_mru) {                        addLoader("MRUBYTE0", NULL);                    }                    else if (n_mru) {                        addLoader("LXMRU005", NULL);                    }                    if (n_mru) {                        addLoader("LXMRU006", NULL);                    }                    else {                        addLoader("LXMRU007", NULL);                    }            }            else if (0x40==(ft->id & 0xF0)) {                addLoader("LXUNF008", NULL);            }            addLoader("LXUNF010", NULL);        }        if (n_mru) {            addLoader("LEXEC009", NULL);        }    }    addLoader("LEXEC010", NULL);    addLoader(getDecompressorSections(), NULL);    addLoader("LEXEC015", NULL);    if (ft->id) {        {  // decompr, unfilter are separate            if (0x80!=(ft->id & 0xF0)) {                addLoader("LXUNF042", NULL);            }        }        addFilter32(ft->id);        { // decompr, unfilter are separate            if (0x80==(ft->id & 0xF0)) {                if (0==n_mru) {                    addLoader("LXMRU058", NULL);                }            }            addLoader("LXUNF035", NULL);        }    }    else {        addLoader("LEXEC017", NULL);    }    addLoader("IDENTSTR", NULL);    addLoader("LEXEC020", NULL);    addLoader("FOLDEXEC", NULL);}template <class T>void PackMachBase<T>::defineSymbols(Filter const *){    // empty}template <class T>voidPackMachBase<T>::buildMachLoader(    upx_byte const *const proto,    unsigned        const szproto,    upx_byte const *const fold,    unsigned        const szfold,    Filter const *ft){    initLoader(proto, szproto);    struct b_info h; memset(&h, 0, sizeof(h));    unsigned fold_hdrlen = 0;  if (0 < szfold) {    h.sz_unc = (szfold < fold_hdrlen) ? 0 : (szfold - fold_hdrlen);    h.b_method = (unsigned char) ph.method;    h.b_ftid = (unsigned char) ph.filter;    h.b_cto8 = (unsigned char) ph.filter_cto;  }    unsigned char const *const uncLoader = fold_hdrlen + fold;    unsigned char *const cprLoader = new unsigned char[sizeof(h) + h.sz_unc];  if (0 < szfold) {    unsigned sz_cpr = 0;    int r = upx_compress(uncLoader, h.sz_unc, sizeof(h) + cprLoader, &sz_cpr,        NULL, ph.method, 10, NULL, NULL );    h.sz_cpr = sz_cpr;    if (r != UPX_E_OK || h.sz_cpr >= h.sz_unc)        throwInternalError("loader compression failed");  }    memcpy(cprLoader, &h, sizeof(h));    // This adds the definition to the "library", to be used later.    linker->addSection("FOLDEXEC", cprLoader, sizeof(h) + h.sz_cpr, 0);    delete [] cprLoader;    int const GAP = 128;  // must match stub/l_mac_ppc.S    segcmdo.vmsize += h.sz_unc - h.sz_cpr + GAP + 64;    addStubEntrySections(ft);    defineSymbols(ft);    relocateLoader();}voidPackMachPPC32::buildLoader(const Filter *ft){    buildMachLoader(        stub_powerpc_darwin_macho_entry, sizeof(stub_powerpc_darwin_macho_entry),        stub_powerpc_darwin_macho_fold,  sizeof(stub_powerpc_darwin_macho_fold),  ft );}voidPackMachI386::buildLoader(const Filter *ft){    buildMachLoader(        stub_i386_darwin_macho_entry, sizeof(stub_i386_darwin_macho_entry),        stub_i386_darwin_macho_fold,  sizeof(stub_i386_darwin_macho_fold),  ft );}template <class T>void PackMachBase<T>::patchLoader() { }template <class T>void PackMachBase<T>::updateLoader(OutputFile *) {}template <class T>void PackMachBase<T>::patchLoaderChecksum(){    unsigned char *const ptr = getLoader();    l_info *const lp = &linfo;    // checksum for loader; also some PackHeader info    lp->l_checksum = 0;    lp->l_magic = UPX_MAGIC_LE32;  // LE32 always    lp->l_lsize = (unsigned short) lsize;    lp->l_version = (unsigned char) ph.version;    lp->l_format  = (unsigned char) ph.format;    // INFO: lp->l_checksum is currently unused    lp->l_checksum = upx_adler32(ptr, lsize);}template <class T>int __acc_cdecl_qsortPackMachBase<T>::compare_segment_command(void const *const aa, void const *const bb){    Mach_segment_command const *const a = (Mach_segment_command const *)aa;    Mach_segment_command const *const b = (Mach_segment_command const *)bb;    unsigned const xa = a->cmd - Mach_segment_command::LC_SEGMENT;    unsigned const xb = b->cmd - Mach_segment_command::LC_SEGMENT;           if (xa < xb)        return -1;  // LC_SEGMENT first           if (xa > xb)        return  1;    if (a->vmaddr < b->vmaddr) return -1;  // ascending by .vmaddr    if (a->vmaddr > b->vmaddr) return  1;                               return  0;}void PackMachPPC32::pack4(OutputFile *fo, Filter &ft)  // append PackHeader{    // offset of p_info in compressed file    overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo);    super::pack4(fo, ft);    segcmdo.filesize = fo->getBytesWritten();    segcmdo.vmsize += segcmdo.filesize;    fo->seek(sizeof(mhdro), SEEK_SET);    fo->rewrite(&segcmdo, sizeof(segcmdo));    fo->rewrite(&threado, sizeof(threado));    fo->rewrite(&linfo, sizeof(linfo));}void PackMachI386::pack4(OutputFile *fo, Filter &ft)  // append PackHeader{    // offset of p_info in compressed file    overlay_offset = sizeof(mhdro) + sizeof(segcmdo) + sizeof(threado) + sizeof(linfo);    super::pack4(fo, ft);    segcmdo.filesize = fo->getBytesWritten();    segcmdo.vmsize += segcmdo.filesize;    fo->seek(sizeof(mhdro), SEEK_SET);    fo->rewrite(&segcmdo, sizeof(segcmdo));    fo->rewrite(&threado, sizeof(threado));    fo->rewrite(&linfo, sizeof(linfo));}void PackMachPPC32::pack3(OutputFile *fo, Filter &ft)  // append loader{    BE32 disp;    unsigned const zero = 0;    unsigned len = fo->getBytesWritten();    fo->write(&zero, 3& (0u-len));    len += (3& (0u-len)) + sizeof(disp);    disp = 4+ len - sz_mach_headers;  // 4: sizeof(instruction)    fo->write(&disp, sizeof(disp));    threado.state.srr0 = len + segcmdo.vmaddr;  /* entry address */    super::pack3(fo, ft);}void PackMachI386::pack3(OutputFile *fo, Filter &ft)  // append loader{    LE32 disp;    unsigned const zero = 0;    unsigned len = fo->getBytesWritten();    fo->write(&zero, 3& (0u-len));    len += (3& (0u-len));    disp = len - sz_mach_headers;    fo->write(&disp, sizeof(disp));    threado.state.eip = len + sizeof(disp) + segcmdo.vmaddr;  /* entry address */    super::pack3(fo, ft);}// Determine length of gap between PT_LOAD phdri[k] and closest PT_LOAD// which follows in the file (or end-of-file).  Optimize for common case// where the PT_LOAD are adjacent ascending by .p_offset.  Assume no overlap.template <class T>unsigned PackMachBase<T>::find_SEGMENT_gap(    unsigned const k){    if (Mach_segment_command::LC_SEGMENT!=msegcmd[k].cmd    ||  0==msegcmd[k].filesize ) {        return 0;    }    unsigned const hi = msegcmd[k].fileoff + msegcmd[k].filesize;    unsigned lo = ph.u_file_size;    unsigned j = k;    for (;;) { // circular search, optimize for adjacent ascending        ++j;        if (n_segment==j) {            j = 0;        }        if (k==j) {            break;        }        if (Mach_segment_command::LC_SEGMENT==msegcmd[j].cmd        &&  0!=msegcmd[j].filesize ) {            unsigned const t = msegcmd[j].fileoff;            if ((t - hi) < (lo - hi)) {                lo = t;                if (hi==lo) {                    break;                }            }        }    }    return lo - hi;}template <class T>void PackMachBase<T>::pack4(OutputFile *fo, Filter &ft){    PackUnix::pack4(fo, ft);  // FIXME  super() does not work?}template <class T>void PackMachBase<T>::pack3(OutputFile *fo, Filter &ft){    PackUnix::pack3(fo, ft);  // FIXME  super() does not work?}template <class T>void PackMachBase<T>::pack2(OutputFile *fo, Filter &ft)  // append compressed body{    Extent x;    unsigned k;    // count passes, set ptload vars    uip->ui_total_passes = 0;    for (k = 0; k < n_segment; ++k) {        if (Mach_segment_command::LC_SEGMENT==msegcmd[k].cmd        &&  0!=msegcmd[k].filesize ) {            uip->ui_total_passes++;            if (find_SEGMENT_gap(k)) {                uip->ui_total_passes++;            }        }    }    // compress extents    unsigned total_in = 0;    unsigned total_out = 0;    unsigned hdr_u_len = mhdri.sizeofcmds;    uip->ui_pass = 0;    ft.addvalue = 0;    // Packer::compressWithFilters chooses a filter for us, and the stubs    // can handle only one filter, and most filters are for executable    // instructions.  So filter only the largest executable segment.    unsigned exe_filesize_max = 0;    for (k = 0; k < n_segment; ++k)    if (Mach_segment_command::LC_SEGMENT==msegcmd[k].cmd    &&  0!=(Mach_segment_command::VM_PROT_EXECUTE & msegcmd[k].initprot)

⌨️ 快捷键说明

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