📄 p_ps1.cpp
字号:
} else { if (M_IS_LZMA(ph.method)) addLoader(!foundBss ? "cdb.start.lzma" : "bss.cdb.start.lzma", "pad.code", !foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma", method, "cdb.lzma.cpr", ih.tx_ptr & 0xffff ? "dec.ptr" : "dec.ptr.hi", "lzma.exec", NULL); else { assert(foundBss != true); addLoader("cdb.start", "pad.code", "cdb.entry", ih.tx_ptr & 0xffff ? "cdb.dec.ptr" : "cdb.dec.ptr.hi", method, sa_cnt ? sa_cnt > (0x10000 << 2) ? "memset.long" : "memset.short" : "", "cdb.exit", NULL); } } addLoader("UPX1HEAD", "IDENTSTR", NULL); }}#define OPTYPE(x) (((x) >> 13) & 0x7)#define OPCODE(x) (((x) >> 10) & 0x7)#define REG1(x) (((x) >> 5) & 0x1f)#define REG2(x) ((x) & 0x1f)#define MIPS_IMM(a,b) ((((a) - (((b) & 0x8000) >> 15)) << 16) | (b))// Type#define REGIMM 1#define STORE 5// Op#define LUI 7#define ADDIU 1#define SW 3#define IS_LUI(a) ((OPTYPE(a) == REGIMM && OPCODE(a) == LUI))#define IS_ADDIU(a) ((OPTYPE(a) == REGIMM && OPCODE(a) == ADDIU))#define IS_SW_ZERO(a) ((OPTYPE(a) == STORE && OPCODE(a) == SW) && REG2(a) == 0)#define BSS_CHK_LIMIT (18)bool PackPs1::findBssSection(){ unsigned char reg; LE32 *p1 = (LE32 *)(ibuf + (ih.epc - ih.tx_ptr)); if ((ih.epc - ih.tx_ptr + (BSS_CHK_LIMIT * 4)) > fdata_size) return false; // check 18 opcodes for sw zero,0(x) for (signed i = BSS_CHK_LIMIT; i >= 0; i--) { unsigned short op = p1[i] >> 16; if (IS_SW_ZERO(op)) { // found! get reg (x) for bss_start reg = REG1(op); for (; i >= 0; i--) { bss_nfo *p = (bss_nfo *)&p1[i]; unsigned short op1 = p->op1, op2 = p->op2; // check for la (x),bss_start if ((IS_LUI(op1) && REG2(op1) == reg) && (IS_ADDIU(op2) && REG1(op2) == reg)) { op1 = p->op3, op2 = p->op4; // check for la (y),bss_end if (IS_LUI(op1) && IS_ADDIU(op2)) { // bss section info found! bss_start = MIPS_IMM(p->hi1, p->lo1); bss_end = MIPS_IMM(p->hi2, p->lo2); if (0 < ALIGN_DOWN(bss_end - bss_start, 4u)) { unsigned wkmem_sz = M_IS_LZMA(ph.method) ? 32768 : 800; unsigned end_offs = ih.tx_ptr + fdata_size + overlap; if (bss_end > (end_offs + wkmem_sz)) return isCon || (!isCon && M_IS_LZMA(ph.method)); else return false; } } else return false; } } } } return false;}/*************************************************************************//**************************************************************************/void PackPs1::pack(OutputFile *fo){ ibuf.alloc(fdata_size); obuf.allocForCompression(fdata_size); const upx_byte *p_scan = ibuf + fdata_size; // read file fi->seek(PS_HDR_SIZE,SEEK_SET); fi->readx(ibuf,fdata_size); // scan EOF for 2048 bytes sector alignment // the removed space will secure in-place decompression while (!(*--p_scan)) { if (sa_cnt++ > (0x10000 << 5) || sa_cnt >= fdata_size - 1024) break; } if (sa_cnt > (0x10000 << 2)) sa_cnt = ALIGN_DOWN(sa_cnt, 32u); else sa_cnt = ALIGN_DOWN(sa_cnt, 4u); // prepare packheader ph.u_len = (fdata_size - sa_cnt); ph.filter = 0; Filter ft(ph.level); // compress (max_match = 65535) upx_compress_config_t cconf; cconf.reset(); cconf.conf_ucl.max_match = 65535; cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack compressWithFilters(&ft, sa_cnt, &cconf); if (overlap) { opt->info_mode += !opt->info_mode ? 1 : 0; infoWarning("overlap - relocating load address (+%d bytes)", overlap); sa_cnt += overlap; }/* if (bss_start && bss_end && !foundBss) infoWarning("%s: .bss section too small - use stack", fi->getName());*/ unsigned lzma_init = 0; if (M_IS_LZMA(ph.method)) { sz_lunc = getLoaderSize(); lzma_init = 0u - (sz_lunc - linker->getSymbolOffset("lzma.init")); defineDecompressorSymbols(); linker->defineSymbol("entry", ih.epc); linker->defineSymbol("SC", sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2); relocateLoader(); buildPart2 = true; buildLoader(&ft); } memcpy(&oh, &ih, sizeof(ih)); unsigned sz_cbh; putBkupHeader((const unsigned char *)&ih.epc, (unsigned char *)&bh, &sz_cbh); if (ih.is_ptr < (EXE_BS | (PS_RAM_SIZE - PS_STACK_SIZE))) oh.is_ptr = (EXE_BS | (PS_RAM_SIZE - 16)); if (ih.da_ptr != 0 || ih.da_len != 0 || ih.bs_ptr != 0 || ih.bs_len != 0) oh.da_ptr = oh.da_len = oh.bs_ptr = oh.bs_len = 0; const int lsize = getLoaderSize(); unsigned filelen = ALIGN_UP(ih.tx_len, 4); const unsigned decomp_data_start = ih.tx_ptr; const unsigned comp_data_start = (decomp_data_start + filelen + overlap) - ph.c_len; const int h_len = lsize - getLoaderSectionStart("UPX1HEAD"); int d_len = 0; int e_len = 0; if (isCon) { e_len = lsize - h_len; d_len = e_len - getLoaderSectionStart("con.entry"); } else { const char* entry_lzma = !foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma"; d_len = (lsize - h_len) - getLoaderSectionStart(M_IS_LZMA(ph.method) ? entry_lzma : "cdb.entry"); e_len = (lsize - d_len) - h_len; } linker->defineSymbol("entry", ih.epc); linker->defineSymbol("SC", MIPS_LO(sa_cnt > (0x10000 << 2) ? sa_cnt >> 5 : sa_cnt >> 2)); linker->defineSymbol("DECO", decomp_data_start); linker->defineSymbol("ldr_sz", M_IS_LZMA(ph.method) ? sz_lunc + 16 : (d_len-pad_code)); if (foundBss) { if (M_IS_LZMA(ph.method)) linker->defineSymbol("wrkmem", bss_end - 160 - getDecompressorWrkmemSize() - (sz_lunc + 16)); else linker->defineSymbol("wrkmem", bss_end - 16 - (d_len - pad_code)); } const unsigned entry = comp_data_start - e_len; oh.epc = oh.tx_ptr = entry; oh.tx_len = ph.c_len + e_len; unsigned pad = 0; if (!opt->ps1_exe.no_align || !isCon) { pad = oh.tx_len; oh.tx_len = ALIGN_UP(oh.tx_len, CD_SEC); pad = oh.tx_len - pad; oh.tx_ptr -= pad; } ibuf.clear(0,fdata_size); upx_bytep paddata = ibuf; if (M_IS_LZMA(ph.method)) { linker->defineSymbol("lzma_init_off", lzma_init); linker->defineSymbol("gb_e", linker->getSymbolOffset("gb8_e")); } else if (isCon) linker->defineSymbol("gb_e", linker->getSymbolOffset(is32Bit ? "gb32_e" : "gb8_e")); if (isCon) { linker->defineSymbol("PAD", pad_code); if (M_IS_LZMA(ph.method)) linker->defineSymbol("DCRT", (entry + getLoaderSectionStart("lzma.exec"))); else linker->defineSymbol("DCRT", (entry + (e_len - d_len))); } else { linker->defineSymbol("PSVR", FIX_PSVR); linker->defineSymbol("CPDO", comp_data_start); if (M_IS_LZMA(ph.method)) { unsigned entry_lzma = getLoaderSectionStart( !foundBss ? "cdb.entry.lzma" : "bss.cdb.entry.lzma"); linker->defineSymbol("lzma_cpr", getLoaderSectionStart("lzma.exec") - entry_lzma); } } relocateLoader(); //linker->dumpSymbols(); MemBuffer loader(lsize); assert(lsize == getLoaderSize()); memcpy(loader, getLoader(), lsize); patchPackHeader(loader, lsize); if (!isCon && M_IS_LZMA(ph.method) && (HD_CODE_OFS + d_len + h_len) > CD_SEC) throwInternalError("lzma --boot-only loader > 2048"); // ps1_exe_t structure fo->write(&oh, sizeof(oh)); fo->write(&bh, sz_cbh); // decompressor fo->write(loader + e_len, isCon ? h_len : (d_len + h_len)); // header size is 2048 bytes + sector alignment fo->write(paddata, (pad + PS_HDR_SIZE) - fo->getBytesWritten()); // entry fo->write(loader, e_len); // compressed body fo->write(obuf, ph.c_len); verifyOverlappingDecompression(); if (!checkFinalCompressionRatio(fo)) throwNotCompressible();#if 0 printf("%-13s: uncompressed : %8ld bytes\n", getName(), (long) ph.u_len); printf("%-13s: compressed : %8ld bytes\n", getName(), (long) ph.c_len); printf("%-13s: decompressor : %8ld bytes\n", getName(), (long) lsize - h_len - pad_code); printf("%-13s: header comp : %8ld bytes\n", getName(), (long) sz_cbh); printf("%-13s: overlap : %8ld bytes\n", getName(), (long) overlap); printf("%-13s: load address : %08X bytes\n", getName(), (unsigned int) oh.tx_ptr); printf("%-13s: code entry : %08X bytes\n", getName(), (unsigned int) oh.epc); printf("%-13s: bbs start : %08X bytes\n", getName(), (unsigned int) bss_start); printf("%-13s: bbs end : %08X bytes\n", getName(), (unsigned int) bss_end); printf("%-13s: eof in mem IF : %08X bytes\n", getName(), (unsigned int) ih.tx_ptr + ih.tx_len); printf("%-13s: eof in mem OF : %08X bytes\n", getName(), (unsigned int) oh.tx_ptr + oh.tx_len); unsigned char i = 0; if (isCon) { if (foundBss) i = 1; } else { i = 2; if (M_IS_LZMA(ph.method)) { if (!foundBss) i = 3; else i = 4; } } const char *loader_method[] = { "con/stack", "con/bss", "cdb", "cdb/stack", "cdb/bss" }; char method_name[32+1]; set_method_name(method_name, sizeof(method_name), ph.method, ph.level); printf("%-13s: methods : %s, %s\n", getName(), method_name, loader_method[i]);#endif}/*************************************************************************//**************************************************************************/int PackPs1::canUnpack(){ if (!readFileHeader()) return false; if (!readPackHeader(CD_SEC)) return false; // check header as set by packer if (!readBkupHeader() || ph.c_len >= fdata_size) throwCantUnpack("header damaged"); // generic check if (!checkFileHeader()) throwCantUnpack("unsupported header flags"); return true;}/*************************************************************************//**************************************************************************/void PackPs1::unpack(OutputFile *fo){ // restore orig exec hdr memcpy(&oh, &ih, sizeof(ih)); memcpy(&oh.epc, &bh, SZ_IH_BKUP); // check for removed sector alignment assert(oh.tx_len >= ph.u_len); const unsigned pad = oh.tx_len - ph.u_len; ibuf.alloc(fdata_size > PS_HDR_SIZE ? fdata_size : PS_HDR_SIZE); obuf.allocForUncompression(ph.u_len, pad); fi->seek(PS_HDR_SIZE, SEEK_SET); fi->readx(ibuf, fdata_size); // decompress decompress(ibuf + (fdata_size - ph.c_len), obuf); // write decompressed file if (fo) { // write header fo->write(&oh, sizeof(oh)); // align the ps exe header (mode 2 sector data size) ibuf.clear(); fo->write(ibuf, PS_HDR_SIZE - fo->getBytesWritten()); // write uncompressed data + pad obuf.clear(ph.u_len, pad); fo->write(obuf, ph.u_len + pad); }}/*vi:ts=4:et:nowrap*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -