diff --git a/src/compress.cpp b/src/compress.cpp index 750762d0..c6260523 100644 --- a/src/compress.cpp +++ b/src/compress.cpp @@ -76,11 +76,11 @@ int upx_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, - const struct upx_compress_config_t *conf, - struct upx_compress_result_t *result ) + const upx_compress_config_t *cconf, + upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; - upx_compress_result_t result_buffer; + upx_compress_result_t cresult_buffer; assert(method > 0); assert(level > 0); @@ -95,43 +95,33 @@ int upx_compress ( const upx_bytep src, unsigned src_len, // for UPX, we always require a reasonably sized outbut buffer assert(*dst_len >= MemBuffer::getSizeForCompression(src_len)); - if (!result) - result = &result_buffer; - memset(result, 0, sizeof(*result)); + if (!cresult) + cresult = &cresult_buffer; + memset(cresult, 0, sizeof(*cresult)); #if 1 // debug - result->method = method; - result->level = level; - result->u_len = src_len; - result->c_len = 0; + cresult->method = method; + cresult->level = level; + cresult->u_len = src_len; + cresult->c_len = 0; #endif - // assume no info available - fill in worst case results - ucl_uint *res = result->result_ucl.result; - //res[0] = 1; // min_offset_found - NOT USED - res[1] = src_len - 1; // max_offset_found - //res[2] = 2; // min_match_found - NOT USED - res[3] = src_len - 1; // max_match_found - //res[4] = 1; // min_run_found - NOT USED - res[5] = src_len; // max_run_found - res[6] = 1; // first_offset_found - //res[7] = 999999; // same_match_offsets_found - NOT USED if (method < 0) { } #if defined(WITH_LZMA) else if (M_IS_LZMA(method)) r = upx_lzma_compress(src, src_len, dst, dst_len, - cb, method, level, conf, result); + cb, method, level, cconf, cresult); #endif #if defined(WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_nrv_compress(src, src_len, dst, dst_len, - cb, method, level, conf, result); + cb, method, level, cconf, cresult); #endif #if defined(WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) r = upx_ucl_compress(src, src_len, dst, dst_len, - cb, method, level, conf, result); + cb, method, level, cconf, cresult); #endif else { throwInternalError("unknown compression method"); @@ -139,7 +129,7 @@ int upx_compress ( const upx_bytep src, unsigned src_len, #if 1 // debug - result->c_len = *dst_len; + cresult->c_len = *dst_len; #endif return r; } @@ -152,29 +142,29 @@ int upx_compress ( const upx_bytep src, unsigned src_len, int upx_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ) + const upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; assert(*dst_len > 0); assert(src_len < *dst_len); // must be compressed - if (result && result->method == 0) - result = NULL; + if (cresult && cresult->method == 0) + cresult = NULL; if (method < 0) { } #if defined(WITH_LZMA) else if (M_IS_LZMA(method)) - r = upx_lzma_decompress(src, src_len, dst, dst_len, method, result); + r = upx_lzma_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if defined(WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) - r = upx_nrv_decompress(src, src_len, dst, dst_len, method, result); + r = upx_nrv_decompress(src, src_len, dst, dst_len, method, cresult); #endif #if defined(WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) - r = upx_ucl_decompress(src, src_len, dst, dst_len, method, result); + r = upx_ucl_decompress(src, src_len, dst, dst_len, method, cresult); #endif else { throwInternalError("unknown decompression method"); @@ -191,12 +181,12 @@ int upx_decompress ( const upx_bytep src, unsigned src_len, int upx_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ) + const upx_compress_result_t *cresult ) { int r = UPX_E_ERROR; - if (result && result->method == 0) - result = NULL; + if (cresult && cresult->method == 0) + cresult = NULL; assert(*dst_len > 0); assert(src_len < *dst_len); // must be compressed @@ -207,15 +197,15 @@ int upx_test_overlap ( const upx_bytep buf, unsigned src_off, } #if defined(WITH_LZMA) else if (M_IS_LZMA(method)) - r = upx_lzma_test_overlap(buf, src_off, src_len, dst_len, method, result); + r = upx_lzma_test_overlap(buf, src_off, src_len, dst_len, method, cresult); #endif #if defined(WITH_NRV) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) - r = upx_nrv_test_overlap(buf, src_off, src_len, dst_len, method, result); + r = upx_nrv_test_overlap(buf, src_off, src_len, dst_len, method, cresult); #endif #if defined(WITH_UCL) else if (M_IS_NRV2B(method) || M_IS_NRV2D(method) || M_IS_NRV2E(method)) - r = upx_ucl_test_overlap(buf, src_off, src_len, dst_len, method, result); + r = upx_ucl_test_overlap(buf, src_off, src_len, dst_len, method, cresult); #endif else { throwInternalError("unknown decompression method"); diff --git a/src/compress.h b/src/compress.h index 82ab9d30..305bcab1 100644 --- a/src/compress.h +++ b/src/compress.h @@ -39,16 +39,16 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, - const struct upx_compress_config_t *conf, - struct upx_compress_result_t *result ); + const upx_compress_config_t *cconf, + upx_compress_result_t *cresult ); int upx_lzma_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); int upx_lzma_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); #endif @@ -57,16 +57,16 @@ int upx_nrv_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, - const struct upx_compress_config_t *conf, - struct upx_compress_result_t *result ); + const upx_compress_config_t *cconf, + upx_compress_result_t *cresult ); int upx_nrv_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); int upx_nrv_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); #endif @@ -75,16 +75,16 @@ int upx_ucl_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, - const struct upx_compress_config_t *conf, - struct upx_compress_result_t *result ); + const upx_compress_config_t *cconf, + upx_compress_result_t *cresult ); int upx_ucl_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); int upx_ucl_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); #endif diff --git a/src/compress_lzma.cpp b/src/compress_lzma.cpp index c11bca16..7df885db 100644 --- a/src/compress_lzma.cpp +++ b/src/compress_lzma.cpp @@ -155,16 +155,15 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, - const struct upx_compress_config_t *conf_parm, - struct upx_compress_result_t *result ) + const upx_compress_config_t *cconf_parm, + upx_compress_result_t *cresult ) { assert(method == M_LZMA); - assert(level > 0); assert(result != NULL); - UNUSED(conf_parm); + assert(level > 0); assert(cresult != NULL); int r = UPX_E_ERROR; HRESULT rh; - lzma_compress_result_t *res = &result->result_lzma; + lzma_compress_result_t *res = &cresult->result_lzma; MyLzma::InStreamRam is; is.AddRef(); MyLzma::OutStreamRam os; os.AddRef(); @@ -189,13 +188,20 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len, pr[4].vt = pr[5].vt = pr[6].vt = VT_UI4; // setup defaults - pr[0].uintVal = 2; - pr[1].uintVal = 0; - pr[2].uintVal = 3; + pr[0].uintVal = 2; // 0..4 + pr[1].uintVal = 0; // 0..4 + pr[2].uintVal = 3; // 0..8 pr[3].uintVal = 1024 * 1024; pr[4].uintVal = 2; - pr[5].uintVal = 64; + pr[5].uintVal = 64; // 5.. pr[6].uintVal = 0; +#if 0 + // DEBUG - set sizes so that we use a maxmimum amount of stack. + // These settings cause res->num_probs == 3147574, i.e. we will + // need about 6 MB of stack during runtime decompression. + pr[1].uintVal = 4; + pr[2].uintVal = 8; +#endif // FIXME: tune these settings according to level switch (level) @@ -228,9 +234,33 @@ int upx_lzma_compress ( const upx_bytep src, unsigned src_len, goto error; } + // limit dictionary size if (pr[3].uintVal > src_len) pr[3].uintVal = src_len; + // limit num_probs + if (cconf_parm && cconf_parm->conf_lzma.max_num_probs) + { + for (;;) + { + unsigned n = 1846 + (768 << (pr[2].uintVal + pr[1].uintVal)); + if (n <= cconf_parm->conf_lzma.max_num_probs) + break; + if (pr[1].uintVal > pr[2].uintVal) + { + if (pr[1].uintVal == 0) + goto error; + pr[1].uintVal -= 1; + } + else + { + if (pr[2].uintVal == 0) + goto error; + pr[2].uintVal -= 1; + } + } + } + res->pos_bits = pr[0].uintVal; res->lit_pos_bits = pr[1].uintVal; res->lit_context_bits = pr[2].uintVal; @@ -320,7 +350,7 @@ error: int upx_lzma_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ) + const upx_compress_result_t *cresult ) { assert(method == M_LZMA); // see res->num_probs above @@ -354,13 +384,13 @@ int upx_lzma_decompress ( const upx_bytep src, unsigned src_len, src += 2; src_len -= 2; #endif - if (result) + if (cresult) { - assert(result->method == method); - assert(result->result_lzma.pos_bits == (unsigned) s.Properties.pb); - assert(result->result_lzma.lit_pos_bits == (unsigned) s.Properties.lp); - assert(result->result_lzma.lit_context_bits == (unsigned) s.Properties.lc); - assert(result->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties)); + assert(cresult->method == method); + assert(cresult->result_lzma.pos_bits == (unsigned) s.Properties.pb); + assert(cresult->result_lzma.lit_pos_bits == (unsigned) s.Properties.lp); + assert(cresult->result_lzma.lit_context_bits == (unsigned) s.Properties.lc); + assert(cresult->result_lzma.num_probs == (unsigned) LzmaGetNumProbs(&s.Properties)); } s.Probs = (CProb *) malloc(sizeof(CProb) * LzmaGetNumProbs(&s.Properties)); if (!s.Probs) @@ -382,7 +412,7 @@ error: *dst_len = dst_out; free(s.Probs); - UNUSED(result); + UNUSED(cresult); return r; } @@ -394,7 +424,7 @@ error: int upx_lzma_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ) + const upx_compress_result_t *cresult ) { assert(method == M_LZMA); @@ -408,7 +438,7 @@ int upx_lzma_test_overlap ( const upx_bytep buf, unsigned src_off, if ((int)overlap_overhead >= 256) return UPX_E_OK; - UNUSED(result); + UNUSED(cresult); return UPX_E_ERROR; } diff --git a/src/compress_ucl.cpp b/src/compress_ucl.cpp index 87f0e866..705e558b 100644 --- a/src/compress_ucl.cpp +++ b/src/compress_ucl.cpp @@ -101,11 +101,11 @@ int upx_ucl_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb_parm, int method, int level, - const struct upx_compress_config_t *conf_parm, - struct upx_compress_result_t *result ) + const upx_compress_config_t *cconf_parm, + upx_compress_result_t *cresult ) { int r; - assert(level > 0); assert(result != NULL); + assert(level > 0); assert(cresult != NULL); ucl_progress_callback_t cb; cb.callback = 0; @@ -115,20 +115,29 @@ int upx_ucl_compress ( const upx_bytep src, unsigned src_len, cb.user = cb_parm; } - ucl_compress_config_t conf; - memset(&conf, 0xff, sizeof(conf)); - if (conf_parm) - conf = conf_parm->conf_ucl; // struct copy + ucl_compress_config_t cconf; + memset(&cconf, 0xff, sizeof(cconf)); + if (cconf_parm) + cconf = cconf_parm->conf_ucl; // struct copy - ucl_uint *res = result->result_ucl.result; + ucl_uint *res = cresult->result_ucl.result; + // assume no info available - fill in worst case results + //res[0] = 1; // min_offset_found - NOT USED + res[1] = src_len - 1; // max_offset_found + //res[2] = 2; // min_match_found - NOT USED + res[3] = src_len - 1; // max_match_found + //res[4] = 1; // min_run_found - NOT USED + res[5] = src_len; // max_run_found + res[6] = 1; // first_offset_found + //res[7] = 999999; // same_match_offsets_found - NOT USED // prepare bit-buffer settings - conf.bb_endian = 0; - conf.bb_size = 0; + cconf.bb_endian = 0; + cconf.bb_size = 0; if (method >= M_NRV2B_LE32 && method <= M_CL1B_LE16) { - static const unsigned char sizes[3]={32,8,16}; - conf.bb_size = sizes[(method - M_NRV2B_LE32) % 3]; + static const unsigned char sizes[3] = {32, 8, 16}; + cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3]; } else { throwInternalError("unknown compression method"); @@ -136,20 +145,20 @@ int upx_ucl_compress ( const upx_bytep src, unsigned src_len, } // optimize compression parms - if (level <= 3 && conf.max_offset == UCL_UINT_MAX) - conf.max_offset = 8*1024-1; - else if (level == 4 && conf.max_offset == UCL_UINT_MAX) - conf.max_offset = 32*1024-1; + if (level <= 3 && cconf.max_offset == UCL_UINT_MAX) + cconf.max_offset = 8*1024-1; + else if (level == 4 && cconf.max_offset == UCL_UINT_MAX) + cconf.max_offset = 32*1024-1; if M_IS_NRV2B(method) r = ucl_nrv2b_99_compress(src, src_len, dst, dst_len, - &cb, level, &conf, res); + &cb, level, &cconf, res); else if M_IS_NRV2D(method) r = ucl_nrv2d_99_compress(src, src_len, dst, dst_len, - &cb, level, &conf, res); + &cb, level, &cconf, res); else if M_IS_NRV2E(method) r = ucl_nrv2e_99_compress(src, src_len, dst, dst_len, - &cb, level, &conf, res); + &cb, level, &cconf, res); else { throwInternalError("unknown compression method"); return UPX_E_ERROR; @@ -166,7 +175,7 @@ int upx_ucl_compress ( const upx_bytep src, unsigned src_len, int upx_ucl_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ) + const upx_compress_result_t *cresult ) { int r; @@ -204,7 +213,7 @@ int upx_ucl_decompress ( const upx_bytep src, unsigned src_len, return UPX_E_ERROR; } - UNUSED(result); + UNUSED(cresult); return convert_errno_from_ucl(r); } @@ -216,7 +225,7 @@ int upx_ucl_decompress ( const upx_bytep src, unsigned src_len, int upx_ucl_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ) + const upx_compress_result_t *cresult ) { int r; @@ -254,7 +263,7 @@ int upx_ucl_test_overlap ( const upx_bytep buf, unsigned src_off, return UPX_E_ERROR; } - UNUSED(result); + UNUSED(cresult); return convert_errno_from_ucl(r); } diff --git a/src/conf.h b/src/conf.h index e91a8f24..7fc18dd4 100644 --- a/src/conf.h +++ b/src/conf.h @@ -199,25 +199,28 @@ typedef void (__acc_cdecl *upx_progress_func_t) struct upx_callback_t { +#if 0 upx_alloc_func_t nalloc; upx_free_func_t nfree; +#endif upx_progress_func_t nprogress; void * user1; +#if 0 unsigned user2; unsigned user3; +#endif }; struct lzma_compress_config_t { + unsigned max_num_probs; #if 0 unsigned pos_bits; // pb unsigned lit_pos_bits; // lp unsigned lit_context_bits; // lc unsigned dict_size; unsigned mf_passes; -#else - int dummy; #endif void reset() { memset(this, 0, sizeof(*this)); } }; @@ -634,16 +637,16 @@ int upx_compress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, upx_callback_p cb, int method, int level, - const struct upx_compress_config_t *conf, - struct upx_compress_result_t *result ); + const upx_compress_config_t *cconf, + upx_compress_result_t *cresult ); int upx_decompress ( const upx_bytep src, unsigned src_len, upx_bytep dst, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); int upx_test_overlap ( const upx_bytep buf, unsigned src_off, unsigned src_len, unsigned* dst_len, int method, - const struct upx_compress_result_t *result ); + const upx_compress_result_t *cresult ); #endif /* __cplusplus */ diff --git a/src/options.h b/src/options.h index 0511fde0..5b7d5c00 100644 --- a/src/options.h +++ b/src/options.h @@ -86,6 +86,13 @@ struct options_t { // compression runtime parameters - see struct ucl_compress_config_t struct crp_lzma_t { int dummy; +#if 0 + unsigned pos_bits; // pb + unsigned lit_pos_bits; // lp + unsigned lit_context_bits; // lc + unsigned dict_size; + unsigned mf_passes; +#endif void reset() { memset(this, 0, sizeof(*this)); } }; struct crp_ucl_t { diff --git a/src/p_armpe.cpp b/src/p_armpe.cpp index 8e20f8a6..c0ab79a6 100644 --- a/src/p_armpe.cpp +++ b/src/p_armpe.cpp @@ -1904,7 +1904,7 @@ void PackArmPe::pack(OutputFile *fo) } compressWithFilters(&ft, 2048, strategy, - NULL, 0, 0, ih.codebase, rvamin); + NULL, NULL, ih.codebase, rvamin); // info: see buildLoader() newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) diff --git a/src/p_djgpp2.cpp b/src/p_djgpp2.cpp index 7bec0ad8..17258ef1 100644 --- a/src/p_djgpp2.cpp +++ b/src/p_djgpp2.cpp @@ -293,7 +293,12 @@ void PackDjgpp2::pack(OutputFile *fo) ft.buf_len = usize - data->size; ft.addvalue = text->vaddr - hdrsize; // compress - compressWithFilters(&ft, 512); + upx_compress_config_t cconf; cconf.reset(); +#if 1 + // limit stack size needed for runtime decompression + cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ~28 kB stack +#endif + compressWithFilters(&ft, 512, 0, NULL, &cconf); // patch coff header #2 const unsigned lsize = getLoaderSize(); diff --git a/src/p_exe.cpp b/src/p_exe.cpp index 9bee665e..0ae390fe 100644 --- a/src/p_exe.cpp +++ b/src/p_exe.cpp @@ -412,8 +412,10 @@ void PackExe::pack(OutputFile *fo) ph.u_len = ih_imagesize + relocsize; // prepare filter Filter ft(ph.level); - // compress - compressWithFilters(&ft, 32, 0, NULL, 0, MAXMATCH); + // compress (max_match = 8192) + upx_compress_config_t cconf; cconf.reset(); + cconf.conf_ucl.max_match = MAXMATCH; + compressWithFilters(&ft, 32, 0, NULL, &cconf); if (ph.max_run_found + ph.max_match_found > 0x8000) throwCantPack("decompressor limit exceeded, send a bugreport"); diff --git a/src/p_ps1.cpp b/src/p_ps1.cpp index fdf4f8d0..bb4a5bab 100644 --- a/src/p_ps1.cpp +++ b/src/p_ps1.cpp @@ -302,7 +302,9 @@ void PackPs1::pack(OutputFile *fo) Filter ft(ph.level); // compress (max_match = 65535) - compressWithFilters(&ft, 512, 0, NULL, 0, 65535); + upx_compress_config_t cconf; cconf.reset(); + cconf.conf_ucl.max_match = 65535; + compressWithFilters(&ft, 512, 0, NULL, &cconf); if (ph.overlap_overhead > sa_cnt) { diff --git a/src/p_tos.cpp b/src/p_tos.cpp index 6c26144e..e77e1d4d 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -489,7 +489,9 @@ void PackTos::pack(OutputFile *fo) // prepare filter Filter ft(ph.level); // compress (max_match = 65535) - compressWithFilters(&ft, 512, 0, NULL, 0, 65535); + upx_compress_config_t cconf; cconf.reset(); + cconf.conf_ucl.max_match = 65535; + compressWithFilters(&ft, 512, 0, NULL, &cconf); // get loader const unsigned lsize = getLoaderSize(); diff --git a/src/p_unix.cpp b/src/p_unix.cpp index 9e5fa839..ebb2d3b4 100644 --- a/src/p_unix.cpp +++ b/src/p_unix.cpp @@ -348,7 +348,7 @@ void PackUnix::packExtent( ft->cto = 0; compressWithFilters(ft, OVERHEAD, strategy, - NULL, 0, 0, 0, 0, // those 5 args are the defaults + NULL, NULL, 0, 0, // those 4 args are the defaults hdr_ibuf, hdr_u_len); } else { diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index 9e791f75..68651376 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -1924,7 +1924,7 @@ void PackW32Pe::pack(OutputFile *fo) } compressWithFilters(&ft, 2048, strategy, - NULL, 0, 0, ih.codebase, rvamin); + NULL, NULL, ih.codebase, rvamin); // info: see buildLoader() newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1; if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4) diff --git a/src/packer.cpp b/src/packer.cpp index a9f66a7d..ef96c87c 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -154,15 +154,18 @@ bool Packer::skipVerify() const /************************************************************************* -// compress +// compress - wrap call to low-level upx_compress() **************************************************************************/ bool Packer::compress(upx_bytep in, upx_bytep out, - unsigned max_offset, unsigned max_match) + const upx_compress_config_t *cconf_parm) { ph.c_len = 0; assert(ph.level >= 1); assert(ph.level <= 10); + // Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp. + unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64; + // save current checksums ph.saved_u_adler = ph.u_adler; ph.saved_c_adler = ph.c_adler; @@ -170,31 +173,27 @@ bool Packer::compress(upx_bytep in, upx_bytep out, ph.u_adler = upx_adler32(in, ph.u_len, ph.u_adler); // set compression paramters - upx_compress_config_t conf; - conf.reset(); - // arguments - if (max_offset != 0) - conf.conf_ucl.max_offset = max_offset; - if (max_match != 0) - conf.conf_ucl.max_match = max_match; - // options - if (opt->crp.crp_ucl.c_flags != -1) - conf.conf_ucl.c_flags = opt->crp.crp_ucl.c_flags; - if (opt->crp.crp_ucl.p_level != -1) - conf.conf_ucl.p_level = opt->crp.crp_ucl.p_level; - if (opt->crp.crp_ucl.h_level != -1) - conf.conf_ucl.h_level = opt->crp.crp_ucl.h_level; - if (opt->crp.crp_ucl.max_offset != UINT_MAX && opt->crp.crp_ucl.max_offset < conf.conf_ucl.max_offset) - conf.conf_ucl.max_offset = opt->crp.crp_ucl.max_offset; - if (opt->crp.crp_ucl.max_match != UINT_MAX && opt->crp.crp_ucl.max_match < conf.conf_ucl.max_match) - conf.conf_ucl.max_match = opt->crp.crp_ucl.max_match; - - // Avoid too many progress bar updates. 64 is s->bar_len in ui.cpp. - unsigned step = (ph.u_len < 64*1024) ? 0 : ph.u_len / 64; + upx_compress_config_t cconf; cconf.reset(); + if (cconf_parm) + cconf = *cconf_parm; + // cconf options + if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method)) + { + if (opt->crp.crp_ucl.c_flags != -1) + cconf.conf_ucl.c_flags = opt->crp.crp_ucl.c_flags; + if (opt->crp.crp_ucl.p_level != -1) + cconf.conf_ucl.p_level = opt->crp.crp_ucl.p_level; + if (opt->crp.crp_ucl.h_level != -1) + cconf.conf_ucl.h_level = opt->crp.crp_ucl.h_level; + if (opt->crp.crp_ucl.max_offset != UINT_MAX && opt->crp.crp_ucl.max_offset < cconf.conf_ucl.max_offset) + cconf.conf_ucl.max_offset = opt->crp.crp_ucl.max_offset; + if (opt->crp.crp_ucl.max_match != UINT_MAX && opt->crp.crp_ucl.max_match < cconf.conf_ucl.max_match) + cconf.conf_ucl.max_match = opt->crp.crp_ucl.max_match; #if defined(WITH_NRV) - if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512*1024)) - step = 0; + if (ph.level >= 7 || (ph.level >= 4 && ph.u_len >= 512*1024)) + step = 0; #endif + } if (ui_pass >= 0) ui_pass++; uip->startCallback(ph.u_len, step, ui_pass, ui_total_passes); @@ -205,7 +204,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out, // compress int r = upx_compress(in, ph.u_len, out, &ph.c_len, uip->getCallback(), - ph.method, ph.level, &conf, &ph.compress_result); + ph.method, ph.level, &cconf, &ph.compress_result); //uip->finalCallback(ph.u_len, ph.c_len); uip->endCallback(); @@ -215,17 +214,23 @@ bool Packer::compress(upx_bytep in, upx_bytep out, if (r != UPX_E_OK) throwInternalError("compression failed"); - ucl_uint *res = ph.compress_result.result_ucl.result; - //ph.min_offset_found = res[0]; - ph.max_offset_found = res[1]; - //ph.min_match_found = res[2]; - ph.max_match_found = res[3]; - //ph.min_run_found = res[4]; - ph.max_run_found = res[5]; - ph.first_offset_found = res[6]; - //ph.same_match_offsets_found = res[7]; - assert(max_offset == 0 || max_offset >= ph.max_offset_found); - assert(max_match == 0 || max_match >= ph.max_match_found); + if (M_IS_NRV2B(ph.method) || M_IS_NRV2D(ph.method) || M_IS_NRV2E(ph.method)) + { + ucl_uint *res = ph.compress_result.result_ucl.result; + //ph.min_offset_found = res[0]; + ph.max_offset_found = res[1]; + //ph.min_match_found = res[2]; + ph.max_match_found = res[3]; + //ph.min_run_found = res[4]; + ph.max_run_found = res[5]; + ph.first_offset_found = res[6]; + //ph.same_match_offsets_found = res[7]; + if (cconf_parm) + { + assert(cconf.conf_ucl.max_offset == 0 || cconf.conf_ucl.max_offset >= ph.max_offset_found); + assert(cconf.conf_ucl.max_match == 0 || cconf.conf_ucl.max_match >= ph.max_match_found); + } + } //printf("\nPacker::compress: %d/%d: %7d -> %7d\n", ph.method, ph.level, ph.u_len, ph.c_len); if (!checkCompressionRatio(ph.u_len, ph.c_len)) @@ -1140,7 +1145,7 @@ int Packer::getLoaderSectionStart(const char *name, int *slen) const void Packer::compressWithFilters(Filter *parm_ft, const unsigned overlap_range, int strategy, const int *parm_filters, - unsigned max_offset, unsigned max_match, + const upx_compress_config_t *cconf, unsigned filter_off, unsigned compress_buf_off, unsigned char *hdr_buf, unsigned hdr_u_len) @@ -1323,7 +1328,7 @@ void Packer::compressWithFilters(Filter *parm_ft, ph.filter_cto = ft.cto; ph.n_mru = ft.n_mru; // compress - if (compress(ibuf + compress_buf_off, *otemp, max_offset, max_match)) + if (compress(ibuf + compress_buf_off, *otemp, cconf)) { unsigned lsize = 0; if (ph.c_len + lsize + hdr_c_len <= best_ph.c_len + best_ph_lsize + best_hdr_c_len) diff --git a/src/packer.h b/src/packer.h index 0be2250a..45cdc42b 100644 --- a/src/packer.h +++ b/src/packer.h @@ -165,7 +165,7 @@ public: protected: // main compression drivers virtual bool compress(upx_bytep in, upx_bytep out, - unsigned max_offset = 0, unsigned max_match = 0); + const upx_compress_config_t *cconf = NULL); virtual void decompress(const upx_bytep in, upx_bytep out, bool verify_checksum = true, Filter *ft = NULL); virtual bool checkCompressionRatio(unsigned u_len, unsigned c_len) const; @@ -176,7 +176,7 @@ protected: const unsigned overlap_range, int strategy = 0, const int *filters = NULL, - unsigned max_offset = 0, unsigned max_match = 0, + const upx_compress_config_t *cconf = NULL, unsigned filter_buf_off = 0, unsigned compress_buf_off = 0, unsigned char *header_buffer = 0, diff --git a/src/stub/src/arch/i386/lzma_d.ash b/src/stub/src/arch/i386/lzma_d.ash index 865e52e9..72de8604 100644 --- a/src/stub/src/arch/i386/lzma_d.ash +++ b/src/stub/src/arch/i386/lzma_d.ash @@ -127,7 +127,7 @@ LZMA_LIT_SIZE equ 768 mov [ ebx],al ; store lit_context_bits shr cl,4 mov [1+ ebx],cl ; store lit_pos_bits - + push edx ; inSize -2 push esi ; in push ebx ; &CLzmaDecoderState