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

📄 p_unix.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* p_unix.cpp --   This file is part of the UPX executable compressor.   Copyright (C) 1996-2007 Markus Franz Xaver Johannes Oberhumer   Copyright (C) 1996-2007 Laszlo Molnar   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   markus@oberhumer.com      ml1050@users.sourceforge.net */#include "conf.h"#include "file.h"#include "filter.h"#include "packer.h"#include "p_unix.h"#include "p_elf.h"// do not change#define BLOCKSIZE       (512*1024)/*************************************************************************//**************************************************************************/PackUnix::PackUnix(InputFile *f) :    super(f), exetype(0), blocksize(0), overlay_offset(0), lsize(0){    COMPILE_TIME_ASSERT(sizeof(Elf32_Ehdr) == 52);    COMPILE_TIME_ASSERT(sizeof(Elf32_Phdr) == 32);    COMPILE_TIME_ASSERT(sizeof(b_info) == 12);    COMPILE_TIME_ASSERT(sizeof(l_info) == 12);    COMPILE_TIME_ASSERT(sizeof(p_info) == 12);}// common part of canPack(), enhanced by subclassesbool PackUnix::canPack(){    if (exetype == 0)        return false;#if defined(__unix__)    // must be executable by owner    if ((fi->st.st_mode & S_IXUSR) == 0)        throwCantPack("file not executable; try 'chmod +x'");#endif    if (file_size < 4096)        throwCantPack("file is too small");    // info: currently the header is 36 (32+4) bytes before EOF    unsigned char buf[256];    fi->seek(-(off_t)sizeof(buf), SEEK_END);    fi->readx(buf, sizeof(buf));    checkAlreadyPacked(buf, sizeof(buf));    return true;}void PackUnix::writePackHeader(OutputFile *fo){    unsigned char buf[32];    memset(buf, 0, sizeof(buf));    const int hsize = ph.getPackHeaderSize();    assert((unsigned)hsize <= sizeof(buf));    // note: magic constants are always le32    set_le32(buf+0, UPX_MAGIC_LE32);    set_le32(buf+4, UPX_MAGIC2_LE32);    checkPatch(NULL, 0, 0, 0);  // reset    patchPackHeader(buf, hsize);    checkPatch(NULL, 0, 0, 0);  // reset    fo->write(buf, hsize);}/*************************************************************************// Generic Unix pack(). Subclasses must provide patchLoader().//// A typical compressed Unix executable looks like this://   - loader stub//   - 12 bytes header info//   - the compressed blocks, each with a 8 byte header for block sizes//   - 4 bytes block end marker (uncompressed size 0)//   - 32 bytes UPX packheader//   - 4 bytes overlay offset (needed for decompression)**************************************************************************/// see note below and Packer::compress()bool PackUnix::checkCompressionRatio(unsigned, unsigned) const{    return true;}void PackUnix::pack1(OutputFile * /*fo*/, Filter & /*ft*/){    // derived class usually provides this}int PackUnix::getStrategy(Filter &/*ft*/){    // Called just before reading and compressing each block.    // Might want to adjust blocksize, etc.    // If user specified the filter, then use it (-2==filter_strategy).    // Else try the first two filters, and pick the better (2==filter_strategy).    return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));}void PackUnix::pack2(OutputFile *fo, Filter &ft){    // compress blocks    unsigned total_in = 0;    unsigned total_out = 0;// FIXME: ui_total_passes is not correct with multiple blocks...//    ui_total_passes = (file_size + blocksize - 1) / blocksize;//    if (ui_total_passes == 1)//        ui_total_passes = 0;    unsigned remaining = file_size;    while (remaining > 0)    {        // FIXME: disable filters if we have more than one block.        // FIXME: There is only 1 un-filter in the stub [as of 2002-11-10].        // So the next block really has no choice!        // This merely prevents an assert() in compressWithFilters(),        // which assumes it has free choice on each call [block].        // And if the choices aren't the same on each block,        // then un-filtering will give incorrect results.        int filter_strategy = getStrategy(ft);        if (file_size > (off_t)blocksize)            filter_strategy = -3;      // no filters        int l = fi->readx(ibuf, UPX_MIN(blocksize, remaining));        remaining -= l;        // Note: compression for a block can fail if the        //       file is e.g. blocksize + 1 bytes long        // compress        ph.overlap_overhead = 0;        ph.c_len = ph.u_len = l;        ft.buf_len = l;        // compressWithFilters() updates u_adler _inside_ compress();        // that is, AFTER filtering.  We want BEFORE filtering,        // so that decompression checks the end-to-end checksum.        unsigned const end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);        compressWithFilters(&ft, OVERHEAD, NULL_cconf, filter_strategy);        if (ph.c_len < ph.u_len) {            const upx_bytep tbuf = NULL;            if (ft.id == 0) tbuf = ibuf;            ph.overlap_overhead = OVERHEAD;            if (!testOverlappingDecompression(obuf, tbuf, ph.overlap_overhead)) {                // not in-place compressible                ph.c_len = ph.u_len;            }        }        if (ph.c_len >= ph.u_len) {            // block is not compressible            ph.c_len = ph.u_len;            // must manually update checksum of compressed data            ph.c_adler = upx_adler32(ibuf, ph.u_len, ph.saved_c_adler);        }        // write block header        b_info blk_info;        memset(&blk_info, 0, sizeof(blk_info));        set_native32(&blk_info.sz_unc, ph.u_len);        set_native32(&blk_info.sz_cpr, ph.c_len);        if (ph.c_len < ph.u_len) {            blk_info.b_method = (unsigned char) ph.method;            blk_info.b_ftid = (unsigned char) ph.filter;            blk_info.b_cto8 = (unsigned char) ph.filter_cto;        }        fo->write(&blk_info, sizeof(blk_info));        b_len += sizeof(b_info);        // write compressed data        if (ph.c_len < ph.u_len) {            fo->write(obuf, ph.c_len);            verifyOverlappingDecompression();  // uses ph.u_adler        }        else {            fo->write(ibuf, ph.u_len);        }        ph.u_adler = end_u_adler;        total_in += ph.u_len;        total_out += ph.c_len;    }    // update header with totals    ph.u_len = total_in;    ph.c_len = total_out;    if ((off_t)total_in != file_size) {        throwEOFException();    }}voidPackUnix::patchLoaderChecksum(){    unsigned char *const ptr = getLoader();    l_info *const lp = &linfo;    // checksum for loader; also some PackHeader info    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);}void PackUnix::pack3(OutputFile *fo, Filter &/*ft*/){    upx_byte *p = getLoader();    lsize = getLoaderSize();    updateLoader(fo);    patchLoaderChecksum();    fo->write(p, lsize);}void PackUnix::pack4(OutputFile *fo, Filter &){    writePackHeader(fo);    unsigned tmp;    set_native32(&tmp, overlay_offset);    fo->write(&tmp, sizeof(tmp));}void PackUnix::pack(OutputFile *fo){    Filter ft(ph.level);    ft.addvalue = 0;    b_len = 0;    progid = 0;    // set options    blocksize = opt->o_unix.blocksize;    if (blocksize <= 0)        blocksize = BLOCKSIZE;    if ((off_t)blocksize > file_size)        blocksize = file_size;    // init compression buffers    ibuf.alloc(blocksize);    obuf.allocForCompression(blocksize);    fi->seek(0, SEEK_SET);    pack1(fo, ft);  // generate Elf header, etc.    p_info hbuf;    set_native32(&hbuf.p_progid, progid);    set_native32(&hbuf.p_filesize, file_size);    set_native32(&hbuf.p_blocksize, blocksize);    fo->write(&hbuf, sizeof(hbuf));    pack2(fo, ft);  // append the compressed body    // write block end marker (uncompressed size 0)    b_info hdr; memset(&hdr, 0, sizeof(hdr));    set_le32(&hdr.sz_cpr, UPX_MAGIC_LE32);    fo->write(&hdr, sizeof(hdr));    pack3(fo, ft);  // append loader    pack4(fo, ft);  // append PackHeader and overlay_offset; update Elf header    // finally check the compression ratio    if (!checkFinalCompressionRatio(fo))        throwNotCompressible();}void PackUnix::packExtent(    const Extent &x,    unsigned &total_in,    unsigned &total_out,    Filter *ft,    OutputFile *fo,    unsigned hdr_u_len){    unsigned const init_u_adler = ph.u_adler;    unsigned const init_c_adler = ph.c_adler;    MemBuffer hdr_ibuf;    if (hdr_u_len) {        hdr_ibuf.alloc(hdr_u_len);        fi->seek(0, SEEK_SET);        int l = fi->readx(hdr_ibuf, hdr_u_len);        (void)l;    }    fi->seek(x.offset, SEEK_SET);    for (off_t rest = x.size; 0 != rest; ) {        int const filter_strategy = getStrategy(*ft);

⌨️ 快捷键说明

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