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

📄 packer.cpp

📁 UPX 源代码
💻 CPP
📖 第 1 页 / 共 4 页
字号:
        //patchPackHeader(p, lsize);        ph.putPackHeader(p);    }#endif}/*************************************************************************// Try compression with several methods and filters, choose the best/  or first working one. Needs buildLoader().//// Required inputs://   this->ph//     ulen//   parm_ft//     clevel//     addvalue//     buf_len (optional)//// - updates this->ph// - updates *ft// - i_ptr[] is restored to the original unfiltered version// - o_ptr[] contains the best compressed version//// filter_strategy://   n:  try the first N filters, use best one//  -1:  try all filters, use first working one//  -2:  try only the opt->filter filter//  -3:  use no filter at all//// This has been prepared for generalization into class Packer so that// opt->all_methods and/or opt->all_filters are available for all// executable formats.//// It will replace the tryFilters() / compress() call sequence.//// 2006-02-15: hdr_buf and hdr_u_len are default empty input "header" array// to fix a 2-pass problem with Elf headers.  As of today there can be// only one decompression method per executable output file, and that method// is the one that gives best compression for .text and loader.  However,// the Elf headers precede .text in the output file, and are written first.// "--brute" compression often compressed the Elf headers using nrv2b// but the .text (and loader) with nrv2e.  This often resulted in SIGSEGV// during decompression.// The workaround is for hdr_buf and hdr_u_len to describe the Elf headers// (typically less than 512 bytes) when .text is passed in, and include// them in the calculation of shortest output.  Then the result// this->ph.method  will say which [single] method to use for everything.// The Elf headers are never filtered.  They are short enough (< 512 bytes)// that compressing them more than once per method (once here when choosing,// once again just before writing [because compressWithFilters discards])// is OK because of the simplicity of not having two output arrays.**************************************************************************/static int prepareMethods(int *methods, int ph_method, const int *all_methods){    int nmethods = 0;    if (!opt->all_methods || all_methods == NULL)    {        methods[nmethods++] = ph_method;        return nmethods;    }    for (int mm = 0; all_methods[mm] != M_END; ++mm)    {        int method = all_methods[mm];        if (method == M_ULTRA_BRUTE && !opt->ultra_brute)            break;        if (method == M_SKIP || method == M_ULTRA_BRUTE)            continue;        if (opt->all_methods && !opt->all_methods_use_lzma && M_IS_LZMA(method))            continue;        // use this method        assert(Packer::isValidCompressionMethod(method));        methods[nmethods++] = method;    }    return nmethods;}static int prepareFilters(int *filters, int &filter_strategy,                          const int *all_filters){    int nfilters = 0;    // setup filter filter_strategy    if (filter_strategy == 0)    {        if (opt->all_filters)            // choose best from all available filters            filter_strategy = INT_MAX;        else if (opt->filter >= 0 && Filter::isValidFilter(opt->filter, all_filters))            // try opt->filter            filter_strategy = -2;        else            // try the first working filter            filter_strategy = -1;    }    assert(filter_strategy != 0);    if (filter_strategy == -3)        goto done;    if (filter_strategy == -2)    {        if (opt->filter >= 0 && Filter::isValidFilter(opt->filter, all_filters))        {            filters[nfilters++] = opt->filter;            goto done;        }        filter_strategy = -1;    }    assert(filter_strategy >= -1);    while (all_filters && *all_filters != FT_END)    {        int filter_id = *all_filters++;        if (filter_id == FT_ULTRA_BRUTE && !opt->ultra_brute)            break;        if (filter_id == FT_SKIP || filter_id == FT_ULTRA_BRUTE)            continue;        if (filter_id == 0)            continue;        // use this filter        assert(Filter::isValidFilter(filter_id));        filters[nfilters++] = filter_id;        if (filter_strategy >= 0 && nfilters >= filter_strategy)            break;    }done:    // filter_strategy now only means "stop after first successful filter"    filter_strategy = (filter_strategy < 0) ? -1 : 0;    // make sure that we have a "no filter" fallback    for (int i = 0; i < nfilters; i++)        if (filters[i] == 0)            return nfilters;    filters[nfilters++] = 0;    return nfilters;}void Packer::compressWithFilters(upx_bytep i_ptr, unsigned i_len,                                 upx_bytep o_ptr,                                 upx_bytep f_ptr, unsigned f_len,                                 const upx_bytep hdr_ptr, unsigned hdr_len,                                 Filter *parm_ft,                                 const unsigned overlap_range,                                 const upx_compress_config_t *cconf,                                 int filter_strategy){    parm_ft->buf_len = f_len;    // struct copies    const PackHeader orig_ph = this->ph;          PackHeader best_ph = this->ph;    const Filter orig_ft = *parm_ft;          Filter best_ft = *parm_ft;    //    best_ph.c_len = i_len;    best_ph.overlap_overhead = 0;    unsigned best_ph_lsize = 0;    unsigned best_hdr_c_len = 0;    // preconditions    assert(orig_ph.filter == 0);    assert(orig_ft.id == 0);    // prepare methods and filters    int methods[256];    int nmethods = prepareMethods(methods, ph.method, getCompressionMethods(M_ALL, ph.level));    assert(nmethods > 0); assert(nmethods < 256);    int filters[256];    int nfilters = prepareFilters(filters, filter_strategy, getFilters());    assert(nfilters > 0); assert(nfilters < 256);#if 0    printf("compressWithFilters: m(%d):", nmethods);    for (int i = 0; i < nmethods; i++) printf(" %d", methods[i]);    printf(" f(%d):", nfilters);    for (int i = 0; i < nfilters; i++) printf(" %d", filters[i]);    printf("\n");#endif    // update total_passes; previous (ui_total_passes > 0) means incremental    if (uip->ui_total_passes > 0)        uip->ui_total_passes -= 1;    if (filter_strategy < 0)        uip->ui_total_passes += nmethods;    else        uip->ui_total_passes += nfilters * nmethods;    // Working buffer for compressed data. Don't waste memory and allocate as needed.    upx_bytep o_tmp = o_ptr;    MemBuffer o_tmp_buf;    // compress using all methods/filters    int nfilters_success_total = 0;    for (int mm = 0; mm < nmethods; mm++) // for all methods    {        assert(isValidCompressionMethod(methods[mm]));        unsigned hdr_c_len = 0;        if (hdr_ptr != NULL && hdr_len)        {            if (nfilters_success_total != 0 && o_tmp == o_ptr)            {                // do not overwrite o_ptr                o_tmp_buf.allocForCompression(UPX_MAX(hdr_len, i_len));                o_tmp = o_tmp_buf;            }            int r = upx_compress(hdr_ptr, hdr_len, o_tmp, &hdr_c_len,                                 NULL, methods[mm], 10, NULL, NULL);            if (r != UPX_E_OK)                throwInternalError("header compression failed");            if (hdr_c_len >= hdr_len)                throwInternalError("header compression size increase");        }        int nfilters_success_mm = 0;        for (int ff = 0; ff < nfilters; ff++) // for all filters        {            assert(isValidFilter(filters[ff]));            // get fresh packheader            ph = orig_ph;            ph.method = methods[mm];            ph.filter = filters[ff];            ph.overlap_overhead = 0;            // get fresh filter            Filter ft = orig_ft;            ft.init(ph.filter, orig_ft.addvalue);            // filter            optimizeFilter(&ft, f_ptr, f_len);            bool success = ft.filter(f_ptr, f_len);            if (ft.id != 0 && ft.calls == 0)            {                // filter did not do anything - no need to call ft.unfilter()                success = false;            }            if (!success)            {                // filter failed or was useless                if (filter_strategy >= 0)                {                    // adjust ui passes                    if (uip->ui_pass >= 0)                        uip->ui_pass++;                }                continue;            }            // filter success#if 0            printf("filter: id 0x%02x size %6d, calls %5d/%5d/%3d/%5d/%5d, cto 0x%02x\n",                   ft.id, ft.buf_len, ft.calls, ft.noncalls, ft.wrongcalls, ft.firstcall, ft.lastcall, ft.cto);#endif            if (nfilters_success_total != 0 && o_tmp == o_ptr)            {                o_tmp_buf.allocForCompression(i_len);                o_tmp = o_tmp_buf;            }            nfilters_success_total++;            nfilters_success_mm++;            ph.filter_cto = ft.cto;            ph.n_mru = ft.n_mru;            // compress            if (compress(i_ptr, i_len, o_tmp, cconf))            {                unsigned lsize = 0;                // findOverlapOperhead() might be slow; omit if already too big.                if (ph.c_len + lsize + hdr_c_len <= best_ph.c_len + best_ph_lsize + best_hdr_c_len)                {                    // get results                    ph.overlap_overhead = findOverlapOverhead(o_tmp, i_ptr, overlap_range);                    buildLoader(&ft);                    lsize = getLoaderSize();                    assert(lsize > 0);                }#if 0                printf("\n%2d %02x: %d +%4d +%3d = %d  (best: %d +%4d +%3d = %d)\n", ph.method, ph.filter,                       ph.c_len, lsize, hdr_c_len, ph.c_len + lsize + hdr_c_len,                       best_ph.c_len, best_ph_lsize, best_hdr_c_len, best_ph.c_len + best_ph_lsize + best_hdr_c_len);#endif                bool update = false;                if (ph.c_len + lsize + hdr_c_len < best_ph.c_len + best_ph_lsize + best_hdr_c_len)                    update = true;                else if (ph.c_len + lsize + hdr_c_len == best_ph.c_len + best_ph_lsize + best_hdr_c_len)                {                    // prefer smaller loaders                    if (lsize  + hdr_c_len < best_ph_lsize + best_hdr_c_len)                        update = true;                    else if (lsize + hdr_c_len == best_ph_lsize + best_hdr_c_len)                    {                        // prefer less overlap_overhead                        if (ph.overlap_overhead < best_ph.overlap_overhead)                            update = true;                    }                }                if (update)                {                    assert((int)ph.overlap_overhead > 0);                    // update o_ptr[] with best version                    if (o_tmp != o_ptr)                        memcpy(o_ptr, o_tmp, ph.c_len);                    // save compression results                    best_ph = ph;                    best_ph_lsize = lsize;                    best_hdr_c_len = hdr_c_len;                    best_ft = ft;                }            }            // restore - unfilter with verify            ft.unfilter(f_ptr, f_len, true);            if (filter_strategy < 0)                break;        }        assert(nfilters_success_mm > 0);    }    // postconditions 1)    assert(nfilters_success_total > 0);    assert(best_ph.u_len == orig_ph.u_len);    assert(best_ph.filter == best_ft.id);    assert(best_ph.filter_cto == best_ft.cto);    // FIXME  assert(best_ph.n_mru == best_ft.n_mru);    // copy back results    this->ph = best_ph;    *parm_ft = best_ft;    // finally check compression ratio    if (best_ph.c_len + best_ph_lsize >= best_ph.u_len)        throwNotCompressible();    if (!checkCompressionRatio(best_ph.u_len, best_ph.c_len))        throwNotCompressible();    // postconditions 2)    assert(best_ph.overlap_overhead > 0);    // convenience    buildLoader(&best_ft);}/*************************************************************************//**************************************************************************/void Packer::compressWithFilters(Filter *ft,                                 const unsigned overlap_range,                                 const upx_compress_config_t *cconf,                                 int filter_strategy){    compressWithFilters(ft, overlap_range, cconf, filter_strategy,                        0, 0, 0, NULL, 0);}void Packer::compressWithFilters(Filter *ft,                                 const unsigned overlap_range,                                 const upx_compress_config_t *cconf,                                 int filter_strategy,                                 unsigned filter_off,                                 unsigned ibuf_off,                                 unsigned obuf_off,                                 const upx_bytep hdr_ptr, unsigned hdr_len){    ibuf.checkState(); obuf.checkState();    upx_bytep i_ptr = ibuf + ibuf_off;    unsigned  i_len = ph.u_len;    upx_bytep o_ptr = obuf + obuf_off;    upx_bytep f_ptr = ibuf + filter_off;    unsigned  f_len = ft->buf_len ? ft->buf_len : i_len;    assert(f_ptr + f_len <= i_ptr + i_len);    compressWithFilters(i_ptr, i_len,                        o_ptr,                        f_ptr, f_len,                        hdr_ptr, hdr_len,                        ft, overlap_range, cconf, filter_strategy);    ibuf.checkState(); obuf.checkState();}/*vi:ts=4:et:nowrap*/

⌨️ 快捷键说明

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