mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
Refactored compressWithFilters().
This commit is contained in:
parent
6e52364bcb
commit
8875470b37
|
@ -135,7 +135,7 @@ int upx_ucl_compress ( const upx_bytep src, unsigned src_len,
|
||||||
// prepare bit-buffer settings
|
// prepare bit-buffer settings
|
||||||
cconf.bb_endian = 0;
|
cconf.bb_endian = 0;
|
||||||
cconf.bb_size = 0;
|
cconf.bb_size = 0;
|
||||||
if (method >= M_NRV2B_LE32 && method <= M_CL1B_LE16)
|
if (method >= M_NRV2B_LE32 && method <= M_NRV2E_LE16)
|
||||||
{
|
{
|
||||||
static const unsigned char sizes[3] = {32, 8, 16};
|
static const unsigned char sizes[3] = {32, 8, 16};
|
||||||
cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3];
|
cconf.bb_size = sizes[(method - M_NRV2B_LE32) % 3];
|
||||||
|
|
127
src/conf.h
127
src/conf.h
|
@ -187,34 +187,6 @@
|
||||||
|
|
||||||
#define upx_byte unsigned char
|
#define upx_byte unsigned char
|
||||||
#define upx_bytep upx_byte *
|
#define upx_bytep upx_byte *
|
||||||
#define UPX_E_OK (0)
|
|
||||||
#define UPX_E_ERROR (-1)
|
|
||||||
#define UPX_E_OUT_OF_MEMORY (-2)
|
|
||||||
#define UPX_E_NOT_COMPRESSIBLE (-3)
|
|
||||||
#define UPX_E_INPUT_OVERRUN (-4)
|
|
||||||
#define UPX_E_OUTPUT_OVERRUN (-5)
|
|
||||||
#define UPX_E_LOOKBEHIND_OVERRUN (-6)
|
|
||||||
#define UPX_E_EOF_NOT_FOUND (-7)
|
|
||||||
#define UPX_E_INPUT_NOT_CONSUMED (-8)
|
|
||||||
#define UPX_E_NOT_YET_IMPLEMENTED (-9)
|
|
||||||
#define UPX_E_INVALID_ARGUMENT (-10)
|
|
||||||
|
|
||||||
struct upx_callback_t;
|
|
||||||
#define upx_callback_p upx_callback_t *
|
|
||||||
typedef void* (__acc_cdecl *upx_alloc_func_t)
|
|
||||||
(upx_callback_p self, unsigned items, unsigned size);
|
|
||||||
typedef void (__acc_cdecl *upx_free_func_t)
|
|
||||||
(upx_callback_p self, void* ptr);
|
|
||||||
typedef void (__acc_cdecl *upx_progress_func_t)
|
|
||||||
(upx_callback_p, unsigned, unsigned);
|
|
||||||
|
|
||||||
struct upx_callback_t
|
|
||||||
{
|
|
||||||
upx_progress_func_t nprogress;
|
|
||||||
void *user;
|
|
||||||
|
|
||||||
void reset() { memset(this, 0, sizeof(*this)); }
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -414,31 +386,23 @@ private:
|
||||||
#define EXIT_INTERNAL 1
|
#define EXIT_INTERNAL 1
|
||||||
|
|
||||||
|
|
||||||
// compression methods - DO NOT CHANGE
|
// magic constants for patching
|
||||||
#define M_SKIP (-2)
|
#define UPX_MAGIC_LE32 0x21585055 /* "UPX!" */
|
||||||
#define M_END (-1)
|
#define UPX_MAGIC2_LE32 0xD5D0D8A1
|
||||||
#define M_ULTRA_BRUTE (-3)
|
|
||||||
#define M_NRV2B_LE32 2
|
|
||||||
#define M_NRV2B_8 3
|
|
||||||
#define M_NRV2B_LE16 4
|
|
||||||
#define M_NRV2D_LE32 5
|
|
||||||
#define M_NRV2D_8 6
|
|
||||||
#define M_NRV2D_LE16 7
|
|
||||||
#define M_NRV2E_LE32 8
|
|
||||||
#define M_NRV2E_8 9
|
|
||||||
#define M_NRV2E_LE16 10
|
|
||||||
#define M_CL1B_LE32 11
|
|
||||||
#define M_CL1B_8 12
|
|
||||||
#define M_CL1B_LE16 13
|
|
||||||
#define M_LZMA 14
|
|
||||||
#define M_DEFLATE 15 /* zlib */
|
|
||||||
|
|
||||||
#define M_IS_NRV2B(x) ((x) >= M_NRV2B_LE32 && (x) <= M_NRV2B_LE16)
|
|
||||||
#define M_IS_NRV2D(x) ((x) >= M_NRV2D_LE32 && (x) <= M_NRV2D_LE16)
|
// upx_compress() error codes
|
||||||
#define M_IS_NRV2E(x) ((x) >= M_NRV2E_LE32 && (x) <= M_NRV2E_LE16)
|
#define UPX_E_OK (0)
|
||||||
#define M_IS_CL1B(x) ((x) >= M_CL1B_LE32 && (x) <= M_CL1B_LE16)
|
#define UPX_E_ERROR (-1)
|
||||||
#define M_IS_LZMA(x) (((x) & 255) == M_LZMA)
|
#define UPX_E_OUT_OF_MEMORY (-2)
|
||||||
#define M_IS_DEFLATE(x) ((x) == M_DEFLATE)
|
#define UPX_E_NOT_COMPRESSIBLE (-3)
|
||||||
|
#define UPX_E_INPUT_OVERRUN (-4)
|
||||||
|
#define UPX_E_OUTPUT_OVERRUN (-5)
|
||||||
|
#define UPX_E_LOOKBEHIND_OVERRUN (-6)
|
||||||
|
#define UPX_E_EOF_NOT_FOUND (-7)
|
||||||
|
#define UPX_E_INPUT_NOT_CONSUMED (-8)
|
||||||
|
#define UPX_E_NOT_YET_IMPLEMENTED (-9)
|
||||||
|
#define UPX_E_INVALID_ARGUMENT (-10)
|
||||||
|
|
||||||
|
|
||||||
// Executable formats. Note: big endian types are >= 128.
|
// Executable formats. Note: big endian types are >= 128.
|
||||||
|
@ -478,8 +442,61 @@ private:
|
||||||
#define UPX_F_LINUX_ELF32_ARMBE 133
|
#define UPX_F_LINUX_ELF32_ARMBE 133
|
||||||
|
|
||||||
|
|
||||||
#define UPX_MAGIC_LE32 0x21585055 /* "UPX!" */
|
// compression methods - DO NOT CHANGE
|
||||||
#define UPX_MAGIC2_LE32 0xD5D0D8A1
|
#define M_END (-1)
|
||||||
|
#define M_SKIP (-2)
|
||||||
|
#define M_ULTRA_BRUTE (-3)
|
||||||
|
#define M_NRV2B_LE32 2
|
||||||
|
#define M_NRV2B_8 3
|
||||||
|
#define M_NRV2B_LE16 4
|
||||||
|
#define M_NRV2D_LE32 5
|
||||||
|
#define M_NRV2D_8 6
|
||||||
|
#define M_NRV2D_LE16 7
|
||||||
|
#define M_NRV2E_LE32 8
|
||||||
|
#define M_NRV2E_8 9
|
||||||
|
#define M_NRV2E_LE16 10
|
||||||
|
//#define M_CL1B_LE32 11
|
||||||
|
//#define M_CL1B_8 12
|
||||||
|
//#define M_CL1B_LE16 13
|
||||||
|
#define M_LZMA 14
|
||||||
|
#define M_DEFLATE 15 /* zlib */
|
||||||
|
|
||||||
|
#define M_IS_NRV2B(x) ((x) >= M_NRV2B_LE32 && (x) <= M_NRV2B_LE16)
|
||||||
|
#define M_IS_NRV2D(x) ((x) >= M_NRV2D_LE32 && (x) <= M_NRV2D_LE16)
|
||||||
|
#define M_IS_NRV2E(x) ((x) >= M_NRV2E_LE32 && (x) <= M_NRV2E_LE16)
|
||||||
|
//#define M_IS_CL1B(x) ((x) >= M_CL1B_LE32 && (x) <= M_CL1B_LE16)
|
||||||
|
#define M_IS_LZMA(x) (((x) & 255) == M_LZMA)
|
||||||
|
#define M_IS_DEFLATE(x) ((x) == M_DEFLATE)
|
||||||
|
|
||||||
|
|
||||||
|
// filters - DO NOT CHANGE
|
||||||
|
#define FT_END (-1)
|
||||||
|
#define FT_SKIP (-2)
|
||||||
|
#define FT_ULTRA_BRUTE (-3)
|
||||||
|
|
||||||
|
|
||||||
|
/*************************************************************************
|
||||||
|
// compression - callback_t
|
||||||
|
**************************************************************************/
|
||||||
|
|
||||||
|
struct upx_callback_t;
|
||||||
|
#define upx_callback_p upx_callback_t *
|
||||||
|
#if 0
|
||||||
|
typedef void* (__acc_cdecl *upx_alloc_func_t)
|
||||||
|
(upx_callback_p self, unsigned items, unsigned size);
|
||||||
|
typedef void (__acc_cdecl *upx_free_func_t)
|
||||||
|
(upx_callback_p self, void* ptr);
|
||||||
|
#endif
|
||||||
|
typedef void (__acc_cdecl *upx_progress_func_t)
|
||||||
|
(upx_callback_p, unsigned, unsigned);
|
||||||
|
|
||||||
|
struct upx_callback_t
|
||||||
|
{
|
||||||
|
upx_progress_func_t nprogress;
|
||||||
|
void *user;
|
||||||
|
|
||||||
|
void reset() { memset(this, 0, sizeof(*this)); }
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
@ -588,6 +605,8 @@ struct upx_compress_config_t
|
||||||
void reset() { conf_lzma.reset(); conf_ucl.reset(); conf_zlib.reset(); }
|
void reset() { conf_lzma.reset(); conf_ucl.reset(); conf_zlib.reset(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define NULL_cconf ((upx_compress_config_t *) NULL)
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// compression - result_t
|
// compression - result_t
|
||||||
|
|
|
@ -61,10 +61,10 @@ const FilterImp::FilterEntry *FilterImp::getFilter(int id)
|
||||||
memset(filter_map, 0xff, sizeof(filter_map));
|
memset(filter_map, 0xff, sizeof(filter_map));
|
||||||
for (int i = 0; i < n_filters; i++)
|
for (int i = 0; i < n_filters; i++)
|
||||||
{
|
{
|
||||||
int fid = filters[i].id;
|
int filter_id = filters[i].id;
|
||||||
assert(fid >= 0 && fid <= 255);
|
assert(filter_id >= 0 && filter_id <= 255);
|
||||||
assert(filter_map[fid] == 0xff);
|
assert(filter_map[filter_id] == 0xff);
|
||||||
filter_map[fid] = (unsigned char) i;
|
filter_map[filter_id] = (unsigned char) i;
|
||||||
}
|
}
|
||||||
done = true;
|
done = true;
|
||||||
}
|
}
|
||||||
|
@ -85,6 +85,20 @@ bool Filter::isValidFilter(int filter_id)
|
||||||
return fe != NULL;
|
return fe != NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool Filter::isValidFilter(int filter_id, const int *allowed_filters)
|
||||||
|
{
|
||||||
|
if (!isValidFilter(filter_id))
|
||||||
|
return false;
|
||||||
|
if (filter_id == 0)
|
||||||
|
return true;
|
||||||
|
if (allowed_filters == NULL)
|
||||||
|
return false;
|
||||||
|
while (*allowed_filters != FT_END)
|
||||||
|
if (*allowed_filters++ == filter_id)
|
||||||
|
return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// high level API
|
// high level API
|
||||||
|
|
|
@ -62,6 +62,7 @@ public:
|
||||||
bool scan(const upx_byte *buf, unsigned buf_len);
|
bool scan(const upx_byte *buf, unsigned buf_len);
|
||||||
|
|
||||||
static bool isValidFilter(int filter_id);
|
static bool isValidFilter(int filter_id);
|
||||||
|
static bool isValidFilter(int filter_id, const int *allowed_filters);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Will be set by each call to filter()/unfilter().
|
// Will be set by each call to filter()/unfilter().
|
||||||
|
|
|
@ -115,19 +115,18 @@ PackArmPe::~PackArmPe()
|
||||||
|
|
||||||
const int *PackArmPe::getCompressionMethods(int method, int level) const
|
const int *PackArmPe::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
static const int m_nrv2b[] = { M_NRV2B_8, M_NRV2E_8, M_LZMA, M_END };
|
static const int m_all[] = { M_NRV2B_8, M_NRV2E_8, M_LZMA, M_END };
|
||||||
static const int m_nrv2e[] = { M_NRV2E_8, M_NRV2B_8, M_LZMA, M_END };
|
|
||||||
static const int m_lzma[] = { M_LZMA, M_END };
|
static const int m_lzma[] = { M_LZMA, M_END };
|
||||||
|
static const int m_nrv2b[] = { M_NRV2B_8, M_END };
|
||||||
|
static const int m_nrv2e[] = { M_NRV2E_8, M_END };
|
||||||
|
|
||||||
if (!use_thumb_stub)
|
if (!use_thumb_stub)
|
||||||
return getDefaultCompressionMethods_8(method, level);
|
return getDefaultCompressionMethods_8(method, level);
|
||||||
|
|
||||||
if (M_IS_NRV2B(method))
|
if (method == -1) return m_all;
|
||||||
return m_nrv2b;
|
if (M_IS_LZMA(method)) return m_lzma;
|
||||||
if (M_IS_NRV2E(method))
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
return m_nrv2e;
|
if (M_IS_NRV2E(method)) return m_nrv2e;
|
||||||
if (M_IS_LZMA(method))
|
|
||||||
return m_lzma;
|
|
||||||
return m_nrv2e;
|
return m_nrv2e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -698,20 +697,20 @@ void PackArmPe::pack(OutputFile *fo)
|
||||||
ft.buf_len = ih.codesize;
|
ft.buf_len = ih.codesize;
|
||||||
ft.addvalue = ih.codebase - rvamin;
|
ft.addvalue = ih.codebase - rvamin;
|
||||||
// compress
|
// compress
|
||||||
int strategy = allow_filter ? 0 : -3;
|
int filter_strategy = allow_filter ? 0 : -3;
|
||||||
|
|
||||||
// disable filters for files with broken headers
|
// disable filters for files with broken headers
|
||||||
if (ih.codebase + ih.codesize > ph.u_len)
|
if (ih.codebase + ih.codesize > ph.u_len)
|
||||||
{
|
{
|
||||||
ft.buf_len = 1;
|
ft.buf_len = 1;
|
||||||
strategy = -3;
|
filter_strategy = -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
// limit stack size needed for runtime decompression
|
// limit stack size needed for runtime decompression
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 2048, strategy,
|
compressWithFilters(&ft, 2048, &cconf, filter_strategy,
|
||||||
NULL, &cconf, ih.codebase, rvamin);
|
ih.codebase, rvamin);
|
||||||
// info: see buildLoader()
|
// info: see buildLoader()
|
||||||
newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
|
newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -45,16 +45,11 @@ static const
|
||||||
|
|
||||||
const int *PackCom::getCompressionMethods(int method, int level) const
|
const int *PackCom::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
static const int m_nrv2b[] = { M_NRV2B_LE16, -1 };
|
static const int m_nrv2b[] = { M_NRV2B_LE16, M_END };
|
||||||
if (M_IS_NRV2B(method))
|
|
||||||
return m_nrv2b;
|
|
||||||
#if 0
|
#if 0
|
||||||
// NOT IMPLEMENTED
|
static const int m_nrv2d[] = { M_NRV2D_LE16, M_END };
|
||||||
static const int m_nrv2d[] = { M_NRV2D_LE16, -1 };
|
|
||||||
if (M_IS_NRV2D(method))
|
|
||||||
return m_nrv2d;
|
|
||||||
#endif
|
#endif
|
||||||
UNUSED(level);
|
UNUSED(method); UNUSED(level);
|
||||||
return m_nrv2b;
|
return m_nrv2b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -202,7 +197,7 @@ void PackCom::pack(OutputFile *fo)
|
||||||
ft.addvalue = getCallTrickOffset();
|
ft.addvalue = getCallTrickOffset();
|
||||||
// compress
|
// compress
|
||||||
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
||||||
compressWithFilters(&ft, overlap_range);
|
compressWithFilters(&ft, overlap_range, NULL_cconf);
|
||||||
|
|
||||||
const int lsize = getLoaderSize();
|
const int lsize = getLoaderSize();
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
|
|
|
@ -325,7 +325,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
// limit stack size needed for runtime decompression
|
// limit stack size needed for runtime decompression
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, &cconf);
|
||||||
|
|
||||||
// patch coff header #2
|
// patch coff header #2
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
|
|
|
@ -112,7 +112,7 @@ void PackElks8086::pack(OutputFile *fo)
|
||||||
ft.buf_len = ph.u_len;
|
ft.buf_len = ph.u_len;
|
||||||
ft.addvalue = kernel_entry;
|
ft.addvalue = kernel_entry;
|
||||||
// compress
|
// compress
|
||||||
compressWithFilters(&ft, overlap_range);
|
compressWithFilters(&ft, overlap_range, NULL_cconf);
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
MemBuffer loader(lsize);
|
MemBuffer loader(lsize);
|
||||||
|
|
|
@ -58,17 +58,16 @@ PackExe::PackExe(InputFile *f) :
|
||||||
|
|
||||||
const int *PackExe::getCompressionMethods(int method, int level) const
|
const int *PackExe::getCompressionMethods(int method, int level) const
|
||||||
{
|
{
|
||||||
static const int m_nrv2b[] = { M_NRV2B_8, M_NRV2D_8, M_NRV2E_8, M_END };
|
static const int m_all[] = { M_NRV2B_8, M_NRV2D_8, M_NRV2E_8, M_END };
|
||||||
static const int m_nrv2d[] = { M_NRV2D_8, M_NRV2B_8, M_NRV2E_8, M_END };
|
static const int m_nrv2b[] = { M_NRV2B_8, M_END };
|
||||||
static const int m_nrv2e[] = { M_NRV2E_8, M_NRV2B_8, M_NRV2D_8, M_END };
|
static const int m_nrv2d[] = { M_NRV2D_8, M_END };
|
||||||
|
static const int m_nrv2e[] = { M_NRV2E_8, M_END };
|
||||||
|
|
||||||
|
if (method == -1) return m_all;
|
||||||
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
|
if (M_IS_NRV2D(method)) return m_nrv2d;
|
||||||
|
if (M_IS_NRV2E(method)) return m_nrv2e;
|
||||||
bool small = ih_imagesize <= 256*1024;
|
bool small = ih_imagesize <= 256*1024;
|
||||||
if (M_IS_NRV2B(method))
|
|
||||||
return m_nrv2b;
|
|
||||||
if (M_IS_NRV2D(method))
|
|
||||||
return m_nrv2d;
|
|
||||||
if (M_IS_NRV2E(method))
|
|
||||||
return m_nrv2e;
|
|
||||||
if (level == 1 || small)
|
if (level == 1 || small)
|
||||||
return m_nrv2b;
|
return m_nrv2b;
|
||||||
return m_nrv2e;
|
return m_nrv2e;
|
||||||
|
@ -430,7 +429,7 @@ void PackExe::pack(OutputFile *fo)
|
||||||
// compress (max_match = 8192)
|
// compress (max_match = 8192)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
cconf.conf_ucl.max_match = MAXMATCH;
|
cconf.conf_ucl.max_match = MAXMATCH;
|
||||||
compressWithFilters(&ft, 32, 0, NULL, &cconf);
|
compressWithFilters(&ft, 32, &cconf);
|
||||||
if (ph.max_run_found + ph.max_match_found > 0x8000)
|
if (ph.max_run_found + ph.max_match_found > 0x8000)
|
||||||
throwCantPack("decompressor limit exceeded, send a bugreport");
|
throwCantPack("decompressor limit exceeded, send a bugreport");
|
||||||
|
|
||||||
|
|
|
@ -164,9 +164,9 @@ void PackLinuxElf32x86interp::pack3(OutputFile *fo, Filter &/*ft*/)
|
||||||
ph.method = M_NRV2E_LE32; addLoader(getDecompressorSections(), NULL);
|
ph.method = M_NRV2E_LE32; addLoader(getDecompressorSections(), NULL);
|
||||||
addLoader("LXPTI090", NULL);
|
addLoader("LXPTI090", NULL);
|
||||||
|
|
||||||
addLoader("LXPTI043", NULL);
|
//addLoader("LXPTI043", NULL);
|
||||||
ph.method = M_CL1B_LE32; addLoader(getDecompressorSections(), NULL);
|
//ph.method = M_CL1B_LE32; addLoader(getDecompressorSections(), NULL);
|
||||||
addLoader("LXPTI090", NULL);
|
//addLoader("LXPTI090", NULL);
|
||||||
|
|
||||||
addLoader("LXPTI091", NULL);
|
addLoader("LXPTI091", NULL);
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,7 @@ PackMachPPC32::~PackMachPPC32()
|
||||||
const int *PackMachPPC32::getCompressionMethods(int /*method*/, int /*level*/) const
|
const int *PackMachPPC32::getCompressionMethods(int /*method*/, int /*level*/) const
|
||||||
{
|
{
|
||||||
// There really is no LE bias in M_NRV2E_LE32.
|
// There really is no LE bias in M_NRV2E_LE32.
|
||||||
static const int m_nrv2e[] = { M_NRV2E_LE32, -1 };
|
static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
|
||||||
return m_nrv2e;
|
return m_nrv2e;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -491,7 +491,7 @@ void PackPs1::pack(OutputFile *fo)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
cconf.conf_ucl.max_match = 65535;
|
cconf.conf_ucl.max_match = 65535;
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, sa_cnt, 0, NULL, &cconf);
|
compressWithFilters(&ft, sa_cnt, &cconf);
|
||||||
|
|
||||||
if (overlap)
|
if (overlap)
|
||||||
{
|
{
|
||||||
|
|
|
@ -249,7 +249,10 @@ void PackTmt::pack(OutputFile *fo)
|
||||||
Filter ft(ph.level);
|
Filter ft(ph.level);
|
||||||
ft.buf_len = usize;
|
ft.buf_len = usize;
|
||||||
// compress
|
// compress
|
||||||
compressWithFilters(&ft, 512);
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
|
// limit stack size needed for runtime decompression
|
||||||
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
|
compressWithFilters(&ft, 512, &cconf);
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
const unsigned s_point = getLoaderSection("TMTMAIN1");
|
const unsigned s_point = getLoaderSection("TMTMAIN1");
|
||||||
|
|
|
@ -508,7 +508,7 @@ void PackTos::pack(OutputFile *fo)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
cconf.conf_ucl.max_match = 65535;
|
cconf.conf_ucl.max_match = 65535;
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, &cconf);
|
||||||
|
|
||||||
//
|
//
|
||||||
// multipass buildLoader()
|
// multipass buildLoader()
|
||||||
|
|
|
@ -125,8 +125,8 @@ int PackUnix::getStrategy(Filter &/*ft*/)
|
||||||
// Called just before reading and compressing each block.
|
// Called just before reading and compressing each block.
|
||||||
// Might want to adjust blocksize, etc.
|
// Might want to adjust blocksize, etc.
|
||||||
|
|
||||||
// If user specified the filter, then use it (-2==strategy).
|
// If user specified the filter, then use it (-2==filter_strategy).
|
||||||
// Else try the first two filters, and pick the better (2==strategy).
|
// Else try the first two filters, and pick the better (2==filter_strategy).
|
||||||
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,9 +151,9 @@ void PackUnix::pack2(OutputFile *fo, Filter &ft)
|
||||||
// which assumes it has free choice on each call [block].
|
// which assumes it has free choice on each call [block].
|
||||||
// And if the choices aren't the same on each block,
|
// And if the choices aren't the same on each block,
|
||||||
// then un-filtering will give incorrect results.
|
// then un-filtering will give incorrect results.
|
||||||
int strategy = getStrategy(ft);
|
int filter_strategy = getStrategy(ft);
|
||||||
if (file_size > (off_t)blocksize)
|
if (file_size > (off_t)blocksize)
|
||||||
strategy = -3; // no filters
|
filter_strategy = -3; // no filters
|
||||||
|
|
||||||
int l = fi->readx(ibuf, UPX_MIN(blocksize, remaining));
|
int l = fi->readx(ibuf, UPX_MIN(blocksize, remaining));
|
||||||
remaining -= l;
|
remaining -= l;
|
||||||
|
@ -170,7 +170,7 @@ void PackUnix::pack2(OutputFile *fo, Filter &ft)
|
||||||
// that is, AFTER filtering. We want BEFORE filtering,
|
// that is, AFTER filtering. We want BEFORE filtering,
|
||||||
// so that decompression checks the end-to-end checksum.
|
// so that decompression checks the end-to-end checksum.
|
||||||
unsigned const end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);
|
unsigned const end_u_adler = upx_adler32(ibuf, ph.u_len, ph.u_adler);
|
||||||
compressWithFilters(&ft, OVERHEAD, strategy);
|
compressWithFilters(&ft, OVERHEAD, NULL_cconf, filter_strategy);
|
||||||
|
|
||||||
if (ph.c_len < ph.u_len) {
|
if (ph.c_len < ph.u_len) {
|
||||||
ph.overlap_overhead = OVERHEAD;
|
ph.overlap_overhead = OVERHEAD;
|
||||||
|
@ -318,7 +318,7 @@ void PackUnix::packExtent(
|
||||||
}
|
}
|
||||||
fi->seek(x.offset, SEEK_SET);
|
fi->seek(x.offset, SEEK_SET);
|
||||||
for (off_t rest = x.size; 0 != rest; ) {
|
for (off_t rest = x.size; 0 != rest; ) {
|
||||||
int const strategy = getStrategy(*ft);
|
int const filter_strategy = getStrategy(*ft);
|
||||||
int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize));
|
int l = fi->readx(ibuf, UPX_MIN(rest, (off_t)blocksize));
|
||||||
if (l == 0) {
|
if (l == 0) {
|
||||||
break;
|
break;
|
||||||
|
@ -345,9 +345,8 @@ void PackUnix::packExtent(
|
||||||
ft->id = 0;
|
ft->id = 0;
|
||||||
ft->cto = 0;
|
ft->cto = 0;
|
||||||
|
|
||||||
compressWithFilters(ft, OVERHEAD, strategy,
|
compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
|
||||||
NULL, NULL, 0, 0, // those 4 args are the defaults
|
0, 0, hdr_ibuf, hdr_u_len);
|
||||||
hdr_ibuf, hdr_u_len);
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(void) compress(ibuf, obuf); // ignore return value
|
(void) compress(ibuf, obuf); // ignore return value
|
||||||
|
|
|
@ -78,8 +78,8 @@ int PackVmlinuxI386::getStrategy(Filter &/*ft*/)
|
||||||
// Called just before reading and compressing each block.
|
// Called just before reading and compressing each block.
|
||||||
// Might want to adjust blocksize, etc.
|
// Might want to adjust blocksize, etc.
|
||||||
|
|
||||||
// If user specified the filter, then use it (-2==strategy).
|
// If user specified the filter, then use it (-2==filter_strategy).
|
||||||
// Else try the first two filters, and pick the better (2==strategy).
|
// Else try the first two filters, and pick the better (2==filter_strategy).
|
||||||
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
return (opt->no_filter ? -3 : ((opt->filter > 0) ? -2 : 2));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,7 +309,7 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
// limit stack size needed for runtime decompression
|
// limit stack size needed for runtime decompression
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, getStrategy(ft), getFilters(), &cconf);
|
compressWithFilters(&ft, 512, &cconf, getStrategy(ft));
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
|
|
||||||
|
|
|
@ -316,7 +316,7 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
// limit stack size needed for runtime decompression
|
// limit stack size needed for runtime decompression
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, &cconf);
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
|
|
||||||
|
@ -401,7 +401,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
// limit stack size needed for runtime decompression
|
// limit stack size needed for runtime decompression
|
||||||
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
compressWithFilters(&ft, 512, 0, NULL, &cconf);
|
compressWithFilters(&ft, 512, &cconf);
|
||||||
|
|
||||||
// align everything to dword boundary - it is easier to handle
|
// align everything to dword boundary - it is easier to handle
|
||||||
unsigned c_len = ph.c_len;
|
unsigned c_len = ph.c_len;
|
||||||
|
|
|
@ -794,17 +794,17 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||||
ft.buf_len = ih.codesize;
|
ft.buf_len = ih.codesize;
|
||||||
ft.addvalue = ih.codebase - rvamin;
|
ft.addvalue = ih.codebase - rvamin;
|
||||||
// compress
|
// compress
|
||||||
int strategy = allow_filter ? 0 : -3;
|
int filter_strategy = allow_filter ? 0 : -3;
|
||||||
|
|
||||||
// disable filters for files with broken headers
|
// disable filters for files with broken headers
|
||||||
if (ih.codebase + ih.codesize > ph.u_len)
|
if (ih.codebase + ih.codesize > ph.u_len)
|
||||||
{
|
{
|
||||||
ft.buf_len = 1;
|
ft.buf_len = 1;
|
||||||
strategy = -3;
|
filter_strategy = -3;
|
||||||
}
|
}
|
||||||
|
|
||||||
compressWithFilters(&ft, 2048, strategy,
|
compressWithFilters(&ft, 2048, NULL_cconf, filter_strategy,
|
||||||
NULL, NULL, ih.codebase, rvamin);
|
ih.codebase, rvamin);
|
||||||
// info: see buildLoader()
|
// info: see buildLoader()
|
||||||
newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
|
newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
|
||||||
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)
|
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)
|
||||||
|
|
237
src/packer.cpp
237
src/packer.cpp
|
@ -1142,7 +1142,7 @@ void Packer::relocateLoader()
|
||||||
// - ibuf[] is restored to the original unfiltered version
|
// - ibuf[] is restored to the original unfiltered version
|
||||||
// - obuf[] contains the best compressed version
|
// - obuf[] contains the best compressed version
|
||||||
//
|
//
|
||||||
// strategy:
|
// filter_strategy:
|
||||||
// n: try the first N filters, use best one
|
// n: try the first N filters, use best one
|
||||||
// -1: try all filters, use first working one
|
// -1: try all filters, use first working one
|
||||||
// -2: try only the opt->filter filter
|
// -2: try only the opt->filter filter
|
||||||
|
@ -1172,19 +1172,104 @@ void Packer::relocateLoader()
|
||||||
// is OK because of the simplicity of not having two output arrays.
|
// 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);
|
||||||
|
|
||||||
|
const int *filter_list;
|
||||||
|
filter_list = all_filters;
|
||||||
|
while (filter_list && *filter_list != FT_END)
|
||||||
|
{
|
||||||
|
int filter_id = *filter_list++;
|
||||||
|
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(Filter *parm_ft,
|
void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
const unsigned overlap_range,
|
const unsigned overlap_range,
|
||||||
int strategy, const int *parm_filters,
|
|
||||||
const upx_compress_config_t *cconf,
|
const upx_compress_config_t *cconf,
|
||||||
|
int filter_strategy,
|
||||||
unsigned filter_off, unsigned compress_buf_off,
|
unsigned filter_off, unsigned compress_buf_off,
|
||||||
unsigned char *hdr_buf,
|
const upx_bytep hdr_buf, unsigned hdr_u_len)
|
||||||
unsigned hdr_u_len)
|
|
||||||
{
|
{
|
||||||
const int *f;
|
// struct copies
|
||||||
//
|
|
||||||
const PackHeader orig_ph = this->ph;
|
const PackHeader orig_ph = this->ph;
|
||||||
PackHeader best_ph = this->ph;
|
PackHeader best_ph = this->ph;
|
||||||
//
|
|
||||||
const Filter orig_ft = *parm_ft;
|
const Filter orig_ft = *parm_ft;
|
||||||
Filter best_ft = *parm_ft;
|
Filter best_ft = *parm_ft;
|
||||||
//
|
//
|
||||||
|
@ -1201,109 +1286,42 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
assert(orig_ft.id == 0);
|
assert(orig_ft.id == 0);
|
||||||
assert(filter_off + filter_len <= compress_buf_off + compress_buf_len);
|
assert(filter_off + filter_len <= compress_buf_off + compress_buf_len);
|
||||||
|
|
||||||
// setup filter strategy
|
// prepare methods and filters
|
||||||
if (strategy == 0)
|
int methods[256];
|
||||||
{
|
int nmethods = prepareMethods(methods, ph.method, getCompressionMethods(-1, ph.level));
|
||||||
if (opt->all_filters)
|
assert(nmethods > 0); assert(nmethods < 256);
|
||||||
// choose best from all available filters
|
int filters[256];
|
||||||
strategy = INT_MAX;
|
int nfilters = prepareFilters(filters, filter_strategy, getFilters());
|
||||||
else if (opt->filter >= 0 && isValidFilter(opt->filter))
|
assert(nfilters > 0); assert(nfilters < 256);
|
||||||
// try opt->filter
|
#if 1
|
||||||
strategy = -2;
|
printf("compressWithFilters: m(%d):", nmethods);
|
||||||
else
|
for (int i = 0; i < nmethods; i++) printf(" %d", methods[i]);
|
||||||
// try the first working filter
|
printf(" f(%d):", nfilters);
|
||||||
strategy = -1;
|
for (int i = 0; i < nfilters; i++) printf(" %d", filters[i]);
|
||||||
}
|
printf("\n");
|
||||||
assert(strategy != 0);
|
#endif
|
||||||
|
|
||||||
// setup raw_filters
|
// update total_passes; previous (ui_total_passes > 0) means incremental
|
||||||
int tmp_filters[] = { 0, -1 };
|
if (uip->ui_total_passes > 0)
|
||||||
const int *raw_filters = NULL;
|
uip->ui_total_passes -= 1;
|
||||||
if (strategy == -3)
|
if (filter_strategy < 0)
|
||||||
raw_filters = tmp_filters;
|
uip->ui_total_passes += nmethods;
|
||||||
else if (strategy == -2 && opt->filter >= 0)
|
|
||||||
{
|
|
||||||
tmp_filters[0] = opt->filter;
|
|
||||||
raw_filters = tmp_filters;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
uip->ui_total_passes += nfilters * nmethods;
|
||||||
raw_filters = parm_filters;
|
|
||||||
if (raw_filters == NULL)
|
|
||||||
raw_filters = getFilters();
|
|
||||||
if (raw_filters == NULL)
|
|
||||||
raw_filters = tmp_filters;
|
|
||||||
}
|
|
||||||
|
|
||||||
// first pass - count number of filters
|
|
||||||
int raw_nfilters = 0;
|
|
||||||
for (f = raw_filters; *f >= 0; f++)
|
|
||||||
{
|
|
||||||
assert(isValidFilter(*f));
|
|
||||||
raw_nfilters++;
|
|
||||||
}
|
|
||||||
|
|
||||||
// copy filters, add a 0
|
|
||||||
int nfilters = 0;
|
|
||||||
bool zero_seen = false;
|
|
||||||
Array(int, filters, raw_nfilters + 2);
|
|
||||||
for (f = raw_filters; *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == 0)
|
|
||||||
zero_seen = true;
|
|
||||||
filters[nfilters++] = *f;
|
|
||||||
if (nfilters == strategy)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (!zero_seen)
|
|
||||||
filters[nfilters++] = 0;
|
|
||||||
filters[nfilters] = -1;
|
|
||||||
|
|
||||||
// methods
|
|
||||||
int tmp_methods[] = { ph.method, M_END };
|
|
||||||
const int *methods = NULL;
|
|
||||||
if (opt->all_methods)
|
|
||||||
methods = getCompressionMethods(-1, ph.level);
|
|
||||||
if (methods == NULL)
|
|
||||||
methods = tmp_methods;
|
|
||||||
int nmethods = 0;
|
|
||||||
for (int mm = 0; methods[mm] != M_END; ++mm)
|
|
||||||
{
|
|
||||||
if (methods[mm] == M_ULTRA_BRUTE && !opt->ultra_brute)
|
|
||||||
break;
|
|
||||||
if (methods[mm] == M_SKIP || methods[mm] == M_ULTRA_BRUTE)
|
|
||||||
continue;
|
|
||||||
if (opt->all_methods && !opt->all_methods_use_lzma && M_IS_LZMA(methods[mm]))
|
|
||||||
continue;
|
|
||||||
assert(isValidCompressionMethod(methods[mm]));
|
|
||||||
nmethods++;
|
|
||||||
}
|
|
||||||
assert(nmethods > 0);
|
|
||||||
|
|
||||||
// update total_passes; previous (0 < ui_total_passes) means incremental
|
|
||||||
if (strategy < 0)
|
|
||||||
uip->ui_total_passes += 1 * nmethods - (0 < uip->ui_total_passes);
|
|
||||||
else
|
|
||||||
uip->ui_total_passes += nfilters * nmethods - (0 < uip->ui_total_passes);
|
|
||||||
|
|
||||||
// Working buffer for compressed data. Don't waste memory.
|
// Working buffer for compressed data. Don't waste memory.
|
||||||
MemBuffer *otemp = &obuf;
|
MemBuffer *otemp = &obuf;
|
||||||
MemBuffer otemp_buf;
|
MemBuffer otemp_buf;
|
||||||
|
|
||||||
// compress
|
// compress using all methods/filters
|
||||||
int nfilters_success = 0;
|
int nfilters_success_total = 0;
|
||||||
for (int mm = 0; methods[mm] != M_END; ++mm) // for all methods
|
for (int mm = 0; mm < nmethods; mm++) // for all methods
|
||||||
{
|
{
|
||||||
if (methods[mm] == M_ULTRA_BRUTE && !opt->ultra_brute)
|
assert(isValidCompressionMethod(methods[mm]));
|
||||||
break;
|
|
||||||
if (methods[mm] == M_SKIP || methods[mm] == M_ULTRA_BRUTE)
|
|
||||||
continue;
|
|
||||||
if (opt->all_methods && !opt->all_methods_use_lzma && M_IS_LZMA(methods[mm]))
|
|
||||||
continue;
|
|
||||||
unsigned hdr_c_len = 0;
|
unsigned hdr_c_len = 0;
|
||||||
if (hdr_buf && hdr_u_len)
|
if (hdr_buf && hdr_u_len)
|
||||||
{
|
{
|
||||||
if (nfilters_success != 0 && otemp == &obuf)
|
if (nfilters_success_total != 0 && otemp == &obuf)
|
||||||
{
|
{
|
||||||
// do not overwrite obuf
|
// do not overwrite obuf
|
||||||
otemp_buf.allocForCompression(compress_buf_len);
|
otemp_buf.allocForCompression(compress_buf_len);
|
||||||
|
@ -1316,21 +1334,22 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
if (hdr_c_len >= hdr_u_len)
|
if (hdr_c_len >= hdr_u_len)
|
||||||
throwInternalError("header compression size increase");
|
throwInternalError("header compression size increase");
|
||||||
}
|
}
|
||||||
for (int i = 0; i < nfilters; i++) // for all filters
|
int nfilters_success_mm = 0;
|
||||||
|
for (int ff = 0; ff < nfilters; ff++) // for all filters
|
||||||
{
|
{
|
||||||
|
assert(isValidFilter(filters[ff]));
|
||||||
ibuf.checkState();
|
ibuf.checkState();
|
||||||
obuf.checkState();
|
obuf.checkState();
|
||||||
// get fresh packheader
|
// get fresh packheader
|
||||||
ph = orig_ph;
|
ph = orig_ph;
|
||||||
ph.method = methods[mm];
|
ph.method = methods[mm];
|
||||||
ph.filter = filters[i];
|
ph.filter = filters[ff];
|
||||||
ph.overlap_overhead = 0;
|
ph.overlap_overhead = 0;
|
||||||
// get fresh filter
|
// get fresh filter
|
||||||
Filter ft = orig_ft;
|
Filter ft = orig_ft;
|
||||||
ft.init(ph.filter, orig_ft.addvalue);
|
ft.init(ph.filter, orig_ft.addvalue);
|
||||||
// filter
|
// filter
|
||||||
optimizeFilter(&ft, ibuf + filter_off, filter_len);
|
optimizeFilter(&ft, ibuf + filter_off, filter_len);
|
||||||
|
|
||||||
bool success = ft.filter(ibuf + filter_off, filter_len);
|
bool success = ft.filter(ibuf + filter_off, filter_len);
|
||||||
if (ft.id != 0 && ft.calls == 0)
|
if (ft.id != 0 && ft.calls == 0)
|
||||||
{
|
{
|
||||||
|
@ -1340,9 +1359,9 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
if (!success)
|
if (!success)
|
||||||
{
|
{
|
||||||
// filter failed or was useless
|
// filter failed or was useless
|
||||||
if (strategy > 0)
|
if (filter_strategy >= 0)
|
||||||
{
|
{
|
||||||
// adjust passes
|
// adjust ui passes
|
||||||
if (uip->ui_pass >= 0)
|
if (uip->ui_pass >= 0)
|
||||||
uip->ui_pass++;
|
uip->ui_pass++;
|
||||||
}
|
}
|
||||||
|
@ -1353,12 +1372,13 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
printf("filter: id 0x%02x size %6d, calls %5d/%5d/%3d/%5d/%5d, cto 0x%02x\n",
|
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);
|
ft.id, ft.buf_len, ft.calls, ft.noncalls, ft.wrongcalls, ft.firstcall, ft.lastcall, ft.cto);
|
||||||
#endif
|
#endif
|
||||||
if (nfilters_success != 0 && otemp == &obuf)
|
if (nfilters_success_total != 0 && otemp == &obuf)
|
||||||
{
|
{
|
||||||
otemp_buf.allocForCompression(compress_buf_len);
|
otemp_buf.allocForCompression(compress_buf_len);
|
||||||
otemp = &otemp_buf;
|
otemp = &otemp_buf;
|
||||||
}
|
}
|
||||||
nfilters_success++;
|
nfilters_success_total++;
|
||||||
|
nfilters_success_mm++;
|
||||||
ph.filter_cto = ft.cto;
|
ph.filter_cto = ft.cto;
|
||||||
ph.n_mru = ft.n_mru;
|
ph.n_mru = ft.n_mru;
|
||||||
// compress
|
// compress
|
||||||
|
@ -1413,13 +1433,14 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
obuf.checkState();
|
obuf.checkState();
|
||||||
otemp->checkState();
|
otemp->checkState();
|
||||||
//
|
//
|
||||||
if (strategy < 0)
|
if (filter_strategy < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
assert(nfilters_success_mm > 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// postconditions 1)
|
// postconditions 1)
|
||||||
assert(nfilters_success > 0);
|
assert(nfilters_success_total > 0);
|
||||||
assert(best_ph.u_len == orig_ph.u_len);
|
assert(best_ph.u_len == orig_ph.u_len);
|
||||||
assert(best_ph.filter == best_ft.id);
|
assert(best_ph.filter == best_ft.id);
|
||||||
assert(best_ph.filter_cto == best_ft.cto);
|
assert(best_ph.filter_cto == best_ft.cto);
|
||||||
|
|
|
@ -180,12 +180,11 @@ protected:
|
||||||
// high-level compression drivers
|
// high-level compression drivers
|
||||||
void compressWithFilters(Filter *ft,
|
void compressWithFilters(Filter *ft,
|
||||||
const unsigned overlap_range,
|
const unsigned overlap_range,
|
||||||
int strategy = 0,
|
const upx_compress_config_t *cconf,
|
||||||
const int *filters = NULL,
|
int filter_strategy = 0,
|
||||||
const upx_compress_config_t *cconf = NULL,
|
|
||||||
unsigned filter_buf_off = 0,
|
unsigned filter_buf_off = 0,
|
||||||
unsigned compress_buf_off = 0,
|
unsigned compress_buf_off = 0,
|
||||||
unsigned char *header_buffer = 0,
|
const upx_bytep header_buffer = NULL,
|
||||||
unsigned header_length = 0);
|
unsigned header_length = 0);
|
||||||
|
|
||||||
// util for verifying overlapping decompresion
|
// util for verifying overlapping decompresion
|
||||||
|
|
|
@ -53,25 +53,21 @@ const int *Packer::getDefaultCompressionMethods_8(int method, int level, int sma
|
||||||
{
|
{
|
||||||
#define M_LZMA_003 (M_LZMA | 0x00300)
|
#define M_LZMA_003 (M_LZMA | 0x00300)
|
||||||
#define M_LZMA_407 (M_LZMA | 0x40700)
|
#define M_LZMA_407 (M_LZMA | 0x40700)
|
||||||
static const int m_nrv2b[] = { M_NRV2B_8, M_NRV2D_8, M_NRV2E_8, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
static const int m_all[] = { M_NRV2B_8, M_NRV2D_8, M_NRV2E_8, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
||||||
static const int m_nrv2d[] = { M_NRV2D_8, M_NRV2B_8, M_NRV2E_8, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
//static const int m_cl1b[] = { M_CL1B_8, M_END };
|
||||||
static const int m_nrv2e[] = { M_NRV2E_8, M_NRV2B_8, M_NRV2D_8, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
|
||||||
static const int m_cl1b[] = { M_CL1B_8, M_END };
|
|
||||||
static const int m_lzma[] = { M_LZMA, M_END };
|
static const int m_lzma[] = { M_LZMA, M_END };
|
||||||
|
static const int m_nrv2b[] = { M_NRV2B_8, M_END };
|
||||||
|
static const int m_nrv2d[] = { M_NRV2D_8, M_END };
|
||||||
|
static const int m_nrv2e[] = { M_NRV2E_8, M_END };
|
||||||
|
|
||||||
|
if (method == -1) return m_all;
|
||||||
|
//if (M_IS_CL1B(method)) return m_cl1b;
|
||||||
|
if (M_IS_LZMA(method)) return m_lzma;
|
||||||
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
|
if (M_IS_NRV2D(method)) return m_nrv2d;
|
||||||
|
if (M_IS_NRV2E(method)) return m_nrv2e;
|
||||||
if (small < 0)
|
if (small < 0)
|
||||||
small = file_size <= 512*1024;
|
small = file_size <= 512*1024;
|
||||||
if (M_IS_NRV2B(method))
|
|
||||||
return m_nrv2b;
|
|
||||||
if (M_IS_NRV2D(method))
|
|
||||||
return m_nrv2d;
|
|
||||||
if (M_IS_NRV2E(method))
|
|
||||||
return m_nrv2e;
|
|
||||||
if (M_IS_CL1B(method))
|
|
||||||
return m_cl1b;
|
|
||||||
if (M_IS_LZMA(method))
|
|
||||||
return m_lzma;
|
|
||||||
assert(method == -1); // --all-methods
|
|
||||||
if (level == 1 || small)
|
if (level == 1 || small)
|
||||||
return m_nrv2b;
|
return m_nrv2b;
|
||||||
return m_nrv2e;
|
return m_nrv2e;
|
||||||
|
@ -80,25 +76,21 @@ const int *Packer::getDefaultCompressionMethods_8(int method, int level, int sma
|
||||||
|
|
||||||
const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int small) const
|
const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int small) const
|
||||||
{
|
{
|
||||||
static const int m_nrv2b[] = { M_NRV2B_LE32, M_NRV2D_LE32, M_NRV2E_LE32, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
static const int m_all[] = { M_NRV2B_LE32, M_NRV2D_LE32, M_NRV2E_LE32, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
||||||
static const int m_nrv2d[] = { M_NRV2D_LE32, M_NRV2B_LE32, M_NRV2E_LE32, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
//static const int m_cl1b[] = { M_CL1B_LE32, M_END };
|
||||||
static const int m_nrv2e[] = { M_NRV2E_LE32, M_NRV2B_LE32, M_NRV2D_LE32, M_LZMA, M_ULTRA_BRUTE, M_LZMA_003, M_LZMA_407, M_END };
|
|
||||||
static const int m_cl1b[] = { M_CL1B_LE32, M_END };
|
|
||||||
static const int m_lzma[] = { M_LZMA, M_END };
|
static const int m_lzma[] = { M_LZMA, M_END };
|
||||||
|
static const int m_nrv2b[] = { M_NRV2B_LE32, M_END };
|
||||||
|
static const int m_nrv2d[] = { M_NRV2D_LE32, M_END };
|
||||||
|
static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
|
||||||
|
|
||||||
|
if (method == -1) return m_all;
|
||||||
|
//if (M_IS_CL1B(method)) return m_cl1b;
|
||||||
|
if (M_IS_LZMA(method)) return m_lzma;
|
||||||
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
|
if (M_IS_NRV2D(method)) return m_nrv2d;
|
||||||
|
if (M_IS_NRV2E(method)) return m_nrv2e;
|
||||||
if (small < 0)
|
if (small < 0)
|
||||||
small = file_size <= 512*1024;
|
small = file_size <= 512*1024;
|
||||||
if (M_IS_NRV2B(method))
|
|
||||||
return m_nrv2b;
|
|
||||||
if (M_IS_NRV2D(method))
|
|
||||||
return m_nrv2d;
|
|
||||||
if (M_IS_NRV2E(method))
|
|
||||||
return m_nrv2e;
|
|
||||||
if (M_IS_CL1B(method))
|
|
||||||
return m_cl1b;
|
|
||||||
if (M_IS_LZMA(method))
|
|
||||||
return m_lzma;
|
|
||||||
assert(method == -1); // --all-methods
|
|
||||||
if (level == 1 || small)
|
if (level == 1 || small)
|
||||||
return m_nrv2b;
|
return m_nrv2b;
|
||||||
return m_nrv2e;
|
return m_nrv2e;
|
||||||
|
@ -135,6 +127,7 @@ const char *Packer::getDecompressorSections() const
|
||||||
"N2EFAS10,+80CXXXX,N2EFAS11,N2EDEC10,N2EFAS20,"
|
"N2EFAS10,+80CXXXX,N2EFAS11,N2EDEC10,N2EFAS20,"
|
||||||
"N2EDEC20,N2EFAS30,N2EDEC30,N2EFAS40,N2EFAS50,"
|
"N2EDEC20,N2EFAS30,N2EDEC30,N2EFAS40,N2EFAS50,"
|
||||||
"N2EDEC50,N2EFAS60,+40CXXXX,N2EFAS61,N2EDEC60";
|
"N2EDEC50,N2EFAS60,+40CXXXX,N2EFAS61,N2EDEC60";
|
||||||
|
#if 0
|
||||||
static const char cl1b_le32_small[] =
|
static const char cl1b_le32_small[] =
|
||||||
"CL1ENTER,CL1SMA10,CL1RLOAD,"
|
"CL1ENTER,CL1SMA10,CL1RLOAD,"
|
||||||
"CL1WID01,CL1SMA1B,"
|
"CL1WID01,CL1SMA1B,"
|
||||||
|
@ -193,6 +186,7 @@ const char *Packer::getDecompressorSections() const
|
||||||
"CL1LEN01,CL1FAS1B,"
|
"CL1LEN01,CL1FAS1B,"
|
||||||
"CL1LEN02,"
|
"CL1LEN02,"
|
||||||
"CL1COPY0";
|
"CL1COPY0";
|
||||||
|
#endif
|
||||||
static const char lzma_small[] =
|
static const char lzma_small[] =
|
||||||
"LZMA_DEC00,LZMA_DEC10,LZMA_DEC30";
|
"LZMA_DEC00,LZMA_DEC10,LZMA_DEC30";
|
||||||
static const char lzma_fast[] =
|
static const char lzma_fast[] =
|
||||||
|
@ -208,8 +202,8 @@ const char *Packer::getDecompressorSections() const
|
||||||
return opt->small ? nrv2d_le32_small : nrv2d_le32_fast;
|
return opt->small ? nrv2d_le32_small : nrv2d_le32_fast;
|
||||||
if (ph.method == M_NRV2E_LE32)
|
if (ph.method == M_NRV2E_LE32)
|
||||||
return opt->small ? nrv2e_le32_small : nrv2e_le32_fast;
|
return opt->small ? nrv2e_le32_small : nrv2e_le32_fast;
|
||||||
if (ph.method == M_CL1B_LE32)
|
// if (ph.method == M_CL1B_LE32)
|
||||||
return opt->small ? cl1b_le32_small : cl1b_le32_fast;
|
// return opt->small ? cl1b_le32_small : cl1b_le32_fast;
|
||||||
if (M_IS_LZMA(ph.method)) {
|
if (M_IS_LZMA(ph.method)) {
|
||||||
if (UPX_F_LINUX_ELF_i386 ==ph.format
|
if (UPX_F_LINUX_ELF_i386 ==ph.format
|
||||||
|| UPX_F_LINUX_ELFI_i386 ==ph.format
|
|| UPX_F_LINUX_ELFI_i386 ==ph.format
|
||||||
|
|
|
@ -37,16 +37,7 @@
|
||||||
|
|
||||||
bool Packer::isValidFilter(int filter_id) const
|
bool Packer::isValidFilter(int filter_id) const
|
||||||
{
|
{
|
||||||
if (!Filter::isValidFilter(filter_id))
|
return Filter::isValidFilter(filter_id, getFilters());
|
||||||
return false;
|
|
||||||
if (filter_id == 0)
|
|
||||||
return true;
|
|
||||||
for (const int *f = getFilters(); f && *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == filter_id)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -106,19 +97,19 @@ void Packer::scanFilters(Filter *ft, const upx_byte *buf, unsigned buf_len,
|
||||||
#define FNOMRU 1 // filter, but not using mru
|
#define FNOMRU 1 // filter, but not using mru
|
||||||
#define MRUFLT 2 // mru filter
|
#define MRUFLT 2 // mru filter
|
||||||
|
|
||||||
static inline unsigned f80_call(int fid)
|
static inline unsigned f80_call(int filter_id)
|
||||||
{
|
{
|
||||||
return (1+ (0x0f & fid)) % 3;
|
return (1+ (0x0f & filter_id)) % 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned f80_jmp1(int fid)
|
static inline unsigned f80_jmp1(int filter_id)
|
||||||
{
|
{
|
||||||
return ((1+ (0x0f & fid)) / 3) % 3;
|
return ((1+ (0x0f & filter_id)) / 3) % 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline unsigned f80_jcc2(int fid)
|
static inline unsigned f80_jcc2(int filter_id)
|
||||||
{
|
{
|
||||||
return f80_jmp1(fid);
|
return f80_jmp1(filter_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user