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

📄 p_ps1.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* p_ps1.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   Copyright (C) 2002-2007 Jens Medoch   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>   Jens Medoch   <jssg@users.sourceforge.net> */#include "conf.h"#include "file.h"#include "filter.h"#include "packer.h"#include "p_ps1.h"#include "linker.h"static const#include "stub/mipsel.r3000-ps1.h"#define CD_SEC          2048#define PS_HDR_SIZE     CD_SEC#define PS_RAM_SIZE     ram_size#define PS_MIN_SIZE     (PS_HDR_SIZE*3)#define PS_MAX_SIZE     ((PS_RAM_SIZE*95) / 100)#define PS_STACK_SIZE   (PS_RAM_SIZE / 256)#define SZ_IH_BKUP      (10 * sizeof(LE32))#define HD_CODE_OFS     (sizeof(ps1_exe_t) + sz_cbh)#define K0_BS           (0x80000000)#define K1_BS           (0xa0000000)#define EXE_BS          (ih.epc & K0_BS)#define FIX_PSVR        ((K1_BS - EXE_BS) + (PS_HDR_SIZE - HD_CODE_OFS))// lui / addiu#define MIPS_HI(a)      (((a) >> 16) + (((a) & 0x8000) >> 15))#define MIPS_LO(a)      ((a) & 0xffff)#define MIPS_PC16(a)    ((a) >> 2)#define MIPS_PC26(a)    (((a) & 0x0fffffff) >> 2)/*************************************************************************// ps1 exe looks like this:// 1. <header>  2048 bytes// 2. <body>    plain binary//// header:  contains the ps1_exe_t structure 188 bytes at offset zero//          rest is filled with zeros to reach the required//          cd mode 2 data sector size of 2048 bytes// body:    contains the binary data / code of the executable//          reqiures: executable code must be aligned to 4//                    must be aligned to 2048 to run from a CD//          optional: not aligned to 2048 (for console run only)**************************************************************************/PackPs1::PackPs1(InputFile *f) :    super(f),    isCon(!opt->ps1_exe.boot_only), is32Bit(!opt->ps1_exe.do_8bit),    buildPart2(0), foundBss(0), sa_cnt(0), overlap(0), sz_lunc(0), sz_lcpr(0),    pad_code(0), bss_start(0), bss_end(0){    bele = &N_BELE_RTP::le_policy;    COMPILE_TIME_ASSERT(sizeof(ps1_exe_t) == 136)    COMPILE_TIME_ASSERT(sizeof(ps1_exe_hb_t) == 44)    COMPILE_TIME_ASSERT(sizeof(ps1_exe_chb_t) == 5)    COMPILE_TIME_ASSERT_ALIGNED1(ps1_exe_t)    COMPILE_TIME_ASSERT_ALIGNED1(ps1_exe_hb_t)    COMPILE_TIME_ASSERT_ALIGNED1(ps1_exe_chb_t)    COMPILE_TIME_ASSERT(PS_HDR_SIZE > sizeof(ps1_exe_t))    COMPILE_TIME_ASSERT(SZ_IH_BKUP == 40)    fdata_size = file_size - PS_HDR_SIZE;    ram_size = !opt->ps1_exe.do_8mb ? 0x200000 : 0x800000;}const int *PackPs1::getCompressionMethods(int method, int level) const{    if (is32Bit)        return Packer::getDefaultCompressionMethods_le32(method, level);    else        return Packer::getDefaultCompressionMethods_8(method, level);}const int *PackPs1::getFilters() const{    return NULL;}Linker* PackPs1::newLinker() const{    return new ElfLinkerMipsLE;}/*************************************************************************// util//   readFileHeader() reads ih and checks for illegal values//   checkFileHeader() checks ih for legal but unsupported values**************************************************************************/int PackPs1::readFileHeader(){    fi->seek(0, SEEK_SET);    fi->readx(&ih, sizeof(ih));    if (memcmp(&ih.id, "PS-X EXE", 8) != 0 &&        memcmp(&ih.id, "EXE X-SP", 8) != 0)        return 0;    if (ih.text != 0 || ih.data != 0)        return 0;    return UPX_F_PS1_EXE;}bool PackPs1::readBkupHeader(){    fi->seek(sizeof(ps1_exe_t)+8, SEEK_SET);    fi->readx(&bh, sizeof(bh));    if (bh.ih_csum != upx_adler32(&bh, SZ_IH_BKUP))    {        unsigned char buf[sizeof(bh)];        fi->seek(sizeof(ps1_exe_t), SEEK_SET);        fi->readx(buf, sizeof(bh));        if (!getBkupHeader(buf, (unsigned char *)&bh))            return false;    }    return true;}#define INIT_BH_BKUP(p, l)  {(p)->id = '1'; (p)->len = l;}#define ADLER16(a)          (((a) >> 16) ^ ((a) & 0xffff))void PackPs1::putBkupHeader(const unsigned char *src, unsigned char *dst, unsigned *len){    unsigned sz_cbh = MemBuffer::getSizeForCompression(SZ_IH_BKUP);    if (src && dst)    {        unsigned char *cpr_bh = new unsigned char[sz_cbh];        memset(cpr_bh, 0, sizeof(bh));        ps1_exe_chb_t * p = (ps1_exe_chb_t * )cpr_bh;        int r = upx_compress(src, SZ_IH_BKUP,                             &p->ih_bkup, &sz_cbh, NULL, M_NRV2E_8, 10, NULL, NULL );        if (r != UPX_E_OK || sz_cbh >= SZ_IH_BKUP)            throwInternalError("header compression failed");        INIT_BH_BKUP(p, sz_cbh);        *len = ALIGN_UP(sz_cbh + (unsigned) sizeof(ps1_exe_chb_t) - 1, 4u);        p->ih_csum = ADLER16(upx_adler32(&ih.epc, SZ_IH_BKUP));        memcpy(dst, cpr_bh, SZ_IH_BKUP);        delete [] cpr_bh;    }    else        throwInternalError("header compression failed");}#define ADLER16_HI(a, b)    ((((a) & 0xffff) ^ (b)) << 16)#define ADLER16_LO(a, b)    (((a) >> 16) ^ (b))#define RE_ADLER16(a, b)    (ADLER16_HI(a,b) | ADLER16_LO(a,b))bool PackPs1::getBkupHeader(unsigned char *p, unsigned char *dst){    ps1_exe_chb_t *src = (ps1_exe_chb_t*)p;    if (src && (src->id == '1' && src->len < SZ_IH_BKUP) && dst)    {        unsigned char *unc_bh = new unsigned char[MemBuffer::getSizeForUncompression(SZ_IH_BKUP)];        unsigned sz_bh = SZ_IH_BKUP;        int r = upx_decompress((const unsigned char *)&src->ih_bkup, src->len,                               unc_bh, &sz_bh, M_NRV2E_8, NULL );        if (r == UPX_E_OUT_OF_MEMORY)            throwOutOfMemoryException();        if (r != UPX_E_OK || sz_bh != SZ_IH_BKUP)            throwInternalError("header decompression failed");        unsigned ad = upx_adler32(unc_bh, SZ_IH_BKUP);        unsigned ch = src->ih_csum;        if (ad != RE_ADLER16(ad,ch))            throwInternalError("backup header damaged");        memcpy(dst, unc_bh, SZ_IH_BKUP);        delete [] unc_bh;    }    else        return false;    return true;}bool PackPs1::checkFileHeader(){    if (fdata_size != ih.tx_len || (ih.tx_len & 3))    {        if (!opt->force)            throwCantPack("file size entry damaged (try --force)");        else        {            opt->info_mode += !opt->info_mode ? 1 : 0;            infoWarning("fixing damaged header, keeping backup file");            opt->backup = 1;            ih.tx_len = fdata_size;        }    }    if (!opt->force &&       (ih.da_ptr != 0 || ih.da_len != 0 ||        ih.bs_ptr != 0 || ih.bs_len != 0))    {        infoWarning("unsupported header field entry");        return false;    }    if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE)))    {        if (!opt->force)            return false;        else            infoWarning("%s: stack pointer offset low", fi->getName());    }    return true;}/*************************************************************************//**************************************************************************/bool PackPs1::canPack(){    unsigned char buf[PS_HDR_SIZE - sizeof(ps1_exe_t)];    if (!readFileHeader())        return false;    fi->readx(buf, sizeof(buf));    checkAlreadyPacked(buf, sizeof(buf));    for (size_t i = 0; i < sizeof(buf); i++)        if (buf[i] != 0)        {            if (!opt->force)                throwCantPack("unknown data in header (try --force)");            else            {                opt->info_mode += !opt->info_mode ? 1 : 0;                infoWarning("clearing header, keeping backup file");                opt->backup = 1;                break;            }        }    if (!checkFileHeader())        throwCantPack("unsupported header flags (try --force)");    if (!opt->force && file_size < PS_MIN_SIZE)        throwCantPack("file is too small (try --force)");    if (!opt->force && file_size > (off_t) PS_MAX_SIZE)        throwCantPack("file is too big (try --force)");    return true;}/*************************************************************************//**************************************************************************/void PackPs1::buildLoader(const Filter *){    const char *method = NULL;    if (ph.method == M_NRV2B_8)        method = isCon ? "nrv2b.small,8bit.sub,nrv.done" :                    "nrv2b.8bit,nrv.done";    else if (ph.method == M_NRV2D_8)        method = isCon ? "nrv2d.small,8bit.sub,nrv.done" :                    "nrv2d.8bit,nrv.done";    else if (ph.method == M_NRV2E_8)        method = isCon ? "nrv2e.small,8bit.sub,nrv.done" :                    "nrv2e.8bit,nrv.done";    else if (ph.method == M_NRV2B_LE32)        method = isCon ? "nrv2b.small,32bit.sub,nrv.done" :                    "nrv2b.32bit,nrv.done";    else if (ph.method == M_NRV2D_LE32)        method = isCon ? "nrv2d.small,32bit.sub,nrv.done" :                    "nrv2d.32bit,nrv.done";    else if (ph.method == M_NRV2E_LE32)        method = isCon ? "nrv2e.small,32bit.sub,nrv.done" :                    "nrv2e.32bit,nrv.done";    else if (M_IS_LZMA(ph.method))        method = "nrv2b.small,8bit.sub,nrv.done,lzma.prep";    else        throwInternalError("unknown compression method");    unsigned sa_tmp = sa_cnt;    if (ph.overlap_overhead > sa_cnt)    {        if (!opt->force)        {            infoWarning("not in-place decompressible");            throwCantPack("packed data overlap (try --force)");        }        else            sa_tmp += overlap = ALIGN_UP((ph.overlap_overhead - sa_tmp), 4u);    }    if (isCon || M_IS_LZMA(ph.method))        foundBss = findBssSection();    if (M_IS_LZMA(ph.method) && !buildPart2)    {        initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1));        addLoader("decompressor.start",                  isCon ? "LZMA_DEC20" : "LZMA_DEC10", "lzma.init", NULL);        addLoader(sa_tmp > (0x10000 << 2) ? "memset.long" : "memset.short",                  !foundBss ? "con.exit" : "bss.exit", NULL);    }    else    {        if (M_IS_LZMA(ph.method) && buildPart2)        {            sz_lcpr = MemBuffer::getSizeForCompression(sz_lunc);            unsigned char *cprLoader = new unsigned char[sz_lcpr];            int r = upx_compress(getLoader(), sz_lunc, cprLoader, &sz_lcpr,                                 NULL, M_NRV2B_8, 10, NULL, NULL );            if (r != UPX_E_OK || sz_lcpr >= sz_lunc)                throwInternalError("loader compression failed");            initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1),                      isCon || !M_IS_LZMA(ph.method) ? 0 : 1);            linker->addSection("lzma.exec", cprLoader, sz_lcpr, 0);            delete [] cprLoader;        }        else            initLoader(stub_mipsel_r3000_ps1, sizeof(stub_mipsel_r3000_ps1));        pad_code = ALIGN_GAP((ph.c_len + (isCon ? sz_lcpr : 0)), 4u);        assert(pad_code < 4);        static const unsigned char pad_buffer[4] = { 0, 0, 0, 0 };        linker->addSection("pad.code", pad_buffer, pad_code, 0);        if (isCon)        {            if (M_IS_LZMA(ph.method))                addLoader(!foundBss ? "con.start" : "bss.con.start",                          method,                          ih.tx_ptr & 0xffff ?  "dec.ptr" : "dec.ptr.hi",                          "con.entry", "pad.code", "lzma.exec", NULL);            else                addLoader(!foundBss ? "con.start" : "bss.con.start", "con.mcpy",                          ph.c_len & 3 ? "con.padcd" : "",                          ih.tx_ptr & 0xffff ?  "dec.ptr" : "dec.ptr.hi",                          "con.entry", method,                          sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "",                          !foundBss ? "con.exit" : "bss.exit",                          "pad.code", NULL);

⌨️ 快捷键说明

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