mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
More work so that watom/le now uses compressWithFilters().
This commit is contained in:
parent
ae945ed315
commit
f2b9dff596
16
src/conf.h
16
src/conf.h
|
@ -442,10 +442,13 @@ private:
|
||||||
#define UPX_F_LINUX_ELF32_ARMBE 133
|
#define UPX_F_LINUX_ELF32_ARMBE 133
|
||||||
|
|
||||||
|
|
||||||
|
// compression methods
|
||||||
|
#define M_ALL (-1)
|
||||||
|
#define M_END (-2)
|
||||||
|
#define M_NONE (-3)
|
||||||
|
#define M_SKIP (-4)
|
||||||
|
#define M_ULTRA_BRUTE (-5)
|
||||||
// compression methods - DO NOT CHANGE
|
// compression methods - DO NOT CHANGE
|
||||||
#define M_END (-1)
|
|
||||||
#define M_SKIP (-2)
|
|
||||||
#define M_ULTRA_BRUTE (-3)
|
|
||||||
#define M_NRV2B_LE32 2
|
#define M_NRV2B_LE32 2
|
||||||
#define M_NRV2B_8 3
|
#define M_NRV2B_8 3
|
||||||
#define M_NRV2B_LE16 4
|
#define M_NRV2B_LE16 4
|
||||||
|
@ -469,10 +472,11 @@ private:
|
||||||
#define M_IS_DEFLATE(x) ((x) == M_DEFLATE)
|
#define M_IS_DEFLATE(x) ((x) == M_DEFLATE)
|
||||||
|
|
||||||
|
|
||||||
// filters - DO NOT CHANGE
|
// filters
|
||||||
#define FT_END (-1)
|
#define FT_END (-1)
|
||||||
#define FT_SKIP (-2)
|
#define FT_NONE (-2)
|
||||||
#define FT_ULTRA_BRUTE (-3)
|
#define FT_SKIP (-3)
|
||||||
|
#define FT_ULTRA_BRUTE (-4)
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
|
|
|
@ -50,9 +50,9 @@ void options_t::reset()
|
||||||
o->crp.reset();
|
o->crp.reset();
|
||||||
|
|
||||||
o->cmd = CMD_NONE;
|
o->cmd = CMD_NONE;
|
||||||
o->method = -1;
|
o->method = M_NONE;
|
||||||
o->level = -1;
|
o->level = -1;
|
||||||
o->filter = -1;
|
o->filter = FT_NONE;
|
||||||
|
|
||||||
o->backup = -1;
|
o->backup = -1;
|
||||||
o->overlay = -1;
|
o->overlay = -1;
|
||||||
|
|
|
@ -123,7 +123,7 @@ const int *PackArmPe::getCompressionMethods(int method, int level) const
|
||||||
if (!use_thumb_stub)
|
if (!use_thumb_stub)
|
||||||
return getDefaultCompressionMethods_8(method, level);
|
return getDefaultCompressionMethods_8(method, level);
|
||||||
|
|
||||||
if (method == -1) return m_all;
|
if (method == M_ALL) return m_all;
|
||||||
if (M_IS_LZMA(method)) return m_lzma;
|
if (M_IS_LZMA(method)) return m_lzma;
|
||||||
if (M_IS_NRV2B(method)) return m_nrv2b;
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
if (M_IS_NRV2E(method)) return m_nrv2e;
|
if (M_IS_NRV2E(method)) return m_nrv2e;
|
||||||
|
@ -133,7 +133,7 @@ const int *PackArmPe::getCompressionMethods(int method, int level) const
|
||||||
|
|
||||||
const int *PackArmPe::getFilters() const
|
const int *PackArmPe::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0x50, -1 };
|
static const int filters[] = { 0x50, FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -710,7 +710,7 @@ void PackArmPe::pack(OutputFile *fo)
|
||||||
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, &cconf, filter_strategy,
|
compressWithFilters(&ft, 2048, &cconf, filter_strategy,
|
||||||
ih.codebase, rvamin);
|
ih.codebase, rvamin, 0, NULL, 0);
|
||||||
// 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;
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -58,7 +58,7 @@ const int *PackCom::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x06, 0x03, 0x04, 0x01, 0x05, 0x02,
|
0x06, 0x03, 0x04, 0x01, 0x05, 0x02,
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ const int *PackDjgpp2::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,7 +63,7 @@ const int *PackExe::getCompressionMethods(int method, int level) const
|
||||||
static const int m_nrv2d[] = { 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 };
|
static const int m_nrv2e[] = { M_NRV2E_8, M_END };
|
||||||
|
|
||||||
if (method == -1) return m_all;
|
if (method == M_ALL) return m_all;
|
||||||
if (M_IS_NRV2B(method)) return m_nrv2b;
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
if (M_IS_NRV2D(method)) return m_nrv2d;
|
if (M_IS_NRV2D(method)) return m_nrv2d;
|
||||||
if (M_IS_NRV2E(method)) return m_nrv2e;
|
if (M_IS_NRV2E(method)) return m_nrv2e;
|
||||||
|
|
|
@ -249,8 +249,8 @@ int const *
|
||||||
PackLinuxElf32ppc::getFilters() const
|
PackLinuxElf32ppc::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0xd0, -1
|
0xd0,
|
||||||
};
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -258,8 +258,8 @@ int const *
|
||||||
PackLinuxElf64amd::getFilters() const
|
PackLinuxElf64amd::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x49, -1
|
0x49,
|
||||||
};
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1424,8 +1424,8 @@ using namespace N_BELE_CTP;
|
||||||
static const int *
|
static const int *
|
||||||
ARM_getFilters(bool const isBE)
|
ARM_getFilters(bool const isBE)
|
||||||
{
|
{
|
||||||
static const int f50[] = { 0x50, -1 };
|
static const int f50[] = { 0x50, FT_END };
|
||||||
static const int f51[] = { 0x51, -1 };
|
static const int f51[] = { 0x51, FT_END };
|
||||||
if (isBE)
|
if (isBE)
|
||||||
return f51;
|
return f51;
|
||||||
return f50;
|
return f50;
|
||||||
|
@ -1857,7 +1857,7 @@ PackLinuxElf32x86::getFilters() const
|
||||||
0x82, 0x85,
|
0x82, 0x85,
|
||||||
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
||||||
#endif
|
#endif
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -100,7 +100,7 @@ const int *PackLinuxI386::getFilters() const
|
||||||
0x83, 0x86, 0x80, 0x84, 0x87, 0x81, 0x82, 0x85,
|
0x83, 0x86, 0x80, 0x84, 0x87, 0x81, 0x82, 0x85,
|
||||||
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
0x24, 0x16, 0x13, 0x14, 0x11, 0x25, 0x15, 0x12,
|
||||||
#endif
|
#endif
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ PackLinuxI386sh::buildLoader(Filter const *ft)
|
||||||
// get fresh filter
|
// get fresh filter
|
||||||
Filter fold_ft = *ft;
|
Filter fold_ft = *ft;
|
||||||
fold_ft.init(ft->id, ft->addvalue);
|
fold_ft.init(ft->id, ft->addvalue);
|
||||||
int preferred_ctos[2] = {ft->cto, -1};
|
int preferred_ctos[2] = { ft->cto, -1 };
|
||||||
fold_ft.preferred_ctos = preferred_ctos;
|
fold_ft.preferred_ctos = preferred_ctos;
|
||||||
|
|
||||||
// filter
|
// filter
|
||||||
|
|
|
@ -60,7 +60,7 @@ const int *PackMachPPC32::getCompressionMethods(int /*method*/, int /*level*/) c
|
||||||
|
|
||||||
const int *PackMachPPC32::getFilters() const
|
const int *PackMachPPC32::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = { 0xd0, -1 };
|
static const int filters[] = { 0xd0, FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,7 +60,7 @@ const int *PackTmt::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x12, 0x15,
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x12, 0x15,
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -346,10 +346,10 @@ void PackUnix::packExtent(
|
||||||
ft->cto = 0;
|
ft->cto = 0;
|
||||||
|
|
||||||
compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
|
compressWithFilters(ft, OVERHEAD, NULL_cconf, filter_strategy,
|
||||||
0, 0, hdr_ibuf, hdr_u_len);
|
0, 0, 0, hdr_ibuf, hdr_u_len);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
(void) compress(ibuf, obuf); // ignore return value
|
(void) compress(ibuf, ph.u_len, obuf); // ignore return value
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ph.c_len < ph.u_len) {
|
if (ph.c_len < ph.u_len) {
|
||||||
|
|
|
@ -68,7 +68,7 @@ const int *PackVmlinuxI386::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x49, 0x46,
|
0x49, 0x46,
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -358,7 +358,7 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
||||||
ph.u_len = phdri[0].p_offset;
|
ph.u_len = phdri[0].p_offset;
|
||||||
fi->seek(0, SEEK_SET);
|
fi->seek(0, SEEK_SET);
|
||||||
fi->readx(ibuf, ph.u_len);
|
fi->readx(ibuf, ph.u_len);
|
||||||
compress(ibuf, obuf);
|
compress(ibuf, ph.u_len, obuf);
|
||||||
|
|
||||||
while (0!=*p++) ;
|
while (0!=*p++) ;
|
||||||
shdro[2].sh_name = ptr_diff(p, shstrtab);
|
shdro[2].sh_name = ptr_diff(p, shstrtab);
|
||||||
|
@ -383,7 +383,7 @@ void PackVmlinuxI386::pack(OutputFile *fo)
|
||||||
ph.level = 1;
|
ph.level = 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
compress(ibuf, obuf, &cconf);
|
compress(ibuf, ph.u_len, obuf, &cconf);
|
||||||
ph.level = old_level;
|
ph.level = old_level;
|
||||||
|
|
||||||
// while (0!=*p++) ; // name is the same
|
// while (0!=*p++) ; // name is the same
|
||||||
|
|
|
@ -69,7 +69,7 @@ const int *PackVmlinuzI386::getFilters() const
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x49,
|
0x49,
|
||||||
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
0x26, 0x24, 0x11, 0x14, 0x13, 0x16, 0x25, 0x15, 0x12,
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -804,7 +804,7 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||||
}
|
}
|
||||||
|
|
||||||
compressWithFilters(&ft, 2048, NULL_cconf, filter_strategy,
|
compressWithFilters(&ft, 2048, NULL_cconf, filter_strategy,
|
||||||
ih.codebase, rvamin);
|
ih.codebase, rvamin, 0, NULL, 0);
|
||||||
// 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)
|
||||||
|
|
|
@ -77,7 +77,7 @@ const int *PackWcle::getFilters() const
|
||||||
{
|
{
|
||||||
static const int filters[] = {
|
static const int filters[] = {
|
||||||
0x26, 0x24, 0x14, 0x11, 0x16, 0x13, 0x25, 0x12, 0x15,
|
0x26, 0x24, 0x14, 0x11, 0x16, 0x13, 0x25, 0x12, 0x15,
|
||||||
-1 };
|
FT_END };
|
||||||
return filters;
|
return filters;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -428,7 +428,7 @@ void PackWcle::preprocessFixups()
|
||||||
|
|
||||||
|
|
||||||
#define RESERVED 0x1000
|
#define RESERVED 0x1000
|
||||||
void PackWcle::encodeImage(const Filter *ft)
|
void PackWcle::encodeImage(Filter *ft)
|
||||||
{
|
{
|
||||||
// concatenate image & preprocessed fixups
|
// concatenate image & preprocessed fixups
|
||||||
unsigned isize = soimage + sofixups;
|
unsigned isize = soimage + sofixups;
|
||||||
|
@ -438,16 +438,18 @@ void PackWcle::encodeImage(const Filter *ft)
|
||||||
|
|
||||||
delete[] ifixups; ifixups = NULL;
|
delete[] ifixups; ifixups = NULL;
|
||||||
|
|
||||||
// compress
|
|
||||||
oimage.allocForCompression(isize, RESERVED+512);
|
oimage.allocForCompression(isize, RESERVED+512);
|
||||||
ph.filter = ft->id;
|
// prepare packheader
|
||||||
ph.filter_cto = ft->cto;
|
|
||||||
ph.u_len = isize;
|
ph.u_len = isize;
|
||||||
// reserve RESERVED bytes for the decompressor
|
// prepare filter [already done]
|
||||||
if (!compress(ibuf,oimage+RESERVED))
|
// compress
|
||||||
throwNotCompressible();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
ph.overlap_overhead = findOverlapOverhead(oimage+RESERVED, 512);
|
cconf.conf_lzma.max_num_probs = 1846 + (768 << 4); // ushort: ~28KB stack
|
||||||
buildLoader(ft);
|
compressWithFilters(ibuf, isize,
|
||||||
|
oimage + RESERVED,
|
||||||
|
ibuf + ft->addvalue, ft->buf_len,
|
||||||
|
NULL, 0,
|
||||||
|
ft, 512, &cconf, 0);
|
||||||
|
|
||||||
ibuf.dealloc();
|
ibuf.dealloc();
|
||||||
soimage = ph.c_len;
|
soimage = ph.c_len;
|
||||||
|
@ -506,15 +508,13 @@ void PackWcle::pack(OutputFile *fo)
|
||||||
ifixups[sofixups+12] = (unsigned char) (unsigned) objects;
|
ifixups[sofixups+12] = (unsigned char) (unsigned) objects;
|
||||||
sofixups += 13;
|
sofixups += 13;
|
||||||
|
|
||||||
// filter
|
// prepare filter
|
||||||
Filter ft(ph.level);
|
Filter ft(ph.level);
|
||||||
tryFilters(&ft, iimage+text_vaddr, text_size, text_vaddr);
|
ft.buf_len = text_size;
|
||||||
|
ft.addvalue = text_vaddr;
|
||||||
|
// compress
|
||||||
encodeImage(&ft);
|
encodeImage(&ft);
|
||||||
|
|
||||||
// verify filter
|
|
||||||
ft.verifyUnfilter();
|
|
||||||
|
|
||||||
const unsigned lsize = getLoaderSize();
|
const unsigned lsize = getLoaderSize();
|
||||||
neweip = getLoaderSection("WCLEMAIN");
|
neweip = getLoaderSection("WCLEMAIN");
|
||||||
int e_len = getLoaderSectionStart("WCLECUTP");
|
int e_len = getLoaderSectionStart("WCLECUTP");
|
||||||
|
|
|
@ -74,7 +74,7 @@ protected:
|
||||||
virtual void encodeFixups();
|
virtual void encodeFixups();
|
||||||
virtual void decodeFixups();
|
virtual void decodeFixups();
|
||||||
|
|
||||||
virtual void encodeImage(const Filter *ft);
|
virtual void encodeImage(Filter *ft);
|
||||||
virtual void decodeImage();
|
virtual void decodeImage();
|
||||||
|
|
||||||
static void virt2rela(const le_object_table_entry_t *, unsigned *objn, unsigned *addr);
|
static void virt2rela(const le_object_table_entry_t *, unsigned *objn, unsigned *addr);
|
||||||
|
|
132
src/packer.cpp
132
src/packer.cpp
|
@ -177,9 +177,10 @@ bool ph_skipVerify(const PackHeader &ph)
|
||||||
// compress - wrap call to low-level upx_compress()
|
// compress - wrap call to low-level upx_compress()
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
||||||
bool Packer::compress(upx_bytep in, upx_bytep out,
|
bool Packer::compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
||||||
const upx_compress_config_t *cconf_parm)
|
const upx_compress_config_t *cconf_parm)
|
||||||
{
|
{
|
||||||
|
ph.u_len = i_len;
|
||||||
ph.c_len = 0;
|
ph.c_len = 0;
|
||||||
assert(ph.level >= 1); assert(ph.level <= 10);
|
assert(ph.level >= 1); assert(ph.level <= 10);
|
||||||
|
|
||||||
|
@ -190,7 +191,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
||||||
ph.saved_u_adler = ph.u_adler;
|
ph.saved_u_adler = ph.u_adler;
|
||||||
ph.saved_c_adler = ph.c_adler;
|
ph.saved_c_adler = ph.c_adler;
|
||||||
// update checksum of uncompressed data
|
// update checksum of uncompressed data
|
||||||
ph.u_adler = upx_adler32(in, ph.u_len, ph.u_adler);
|
ph.u_adler = upx_adler32(i_ptr, ph.u_len, ph.u_adler);
|
||||||
|
|
||||||
// set compression paramters
|
// set compression paramters
|
||||||
upx_compress_config_t cconf; cconf.reset();
|
upx_compress_config_t cconf; cconf.reset();
|
||||||
|
@ -236,7 +237,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
||||||
//OutputFile::dump("data.raw", in, ph.u_len);
|
//OutputFile::dump("data.raw", in, ph.u_len);
|
||||||
|
|
||||||
// compress
|
// compress
|
||||||
int r = upx_compress(in, ph.u_len, out, &ph.c_len,
|
int r = upx_compress(i_ptr, ph.u_len, o_ptr, &ph.c_len,
|
||||||
uip->getCallback(),
|
uip->getCallback(),
|
||||||
ph.method, ph.level, &cconf, &ph.compress_result);
|
ph.method, ph.level, &cconf, &ph.compress_result);
|
||||||
|
|
||||||
|
@ -274,13 +275,13 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
// update checksum of compressed data
|
// update checksum of compressed data
|
||||||
ph.c_adler = upx_adler32(out, ph.c_len, ph.c_adler);
|
ph.c_adler = upx_adler32(o_ptr, ph.c_len, ph.c_adler);
|
||||||
// Decompress and verify. Skip this when using the fastest level.
|
// Decompress and verify. Skip this when using the fastest level.
|
||||||
if (!ph_skipVerify(ph))
|
if (!ph_skipVerify(ph))
|
||||||
{
|
{
|
||||||
// decompress
|
// decompress
|
||||||
unsigned new_len = ph.u_len;
|
unsigned new_len = ph.u_len;
|
||||||
r = upx_decompress(out, ph.c_len, in, &new_len, ph.method, &ph.compress_result);
|
r = upx_decompress(o_ptr, ph.c_len, i_ptr, &new_len, ph.method, &ph.compress_result);
|
||||||
//printf("%d %d: %d %d %d\n", ph.method, r, ph.c_len, ph.u_len, new_len);
|
//printf("%d %d: %d %d %d\n", ph.method, r, ph.c_len, ph.u_len, new_len);
|
||||||
if (r != UPX_E_OK)
|
if (r != UPX_E_OK)
|
||||||
throwInternalError("decompression failed");
|
throwInternalError("decompression failed");
|
||||||
|
@ -288,7 +289,7 @@ bool Packer::compress(upx_bytep in, upx_bytep out,
|
||||||
throwInternalError("decompression failed (size error)");
|
throwInternalError("decompression failed (size error)");
|
||||||
|
|
||||||
// verify decompression
|
// verify decompression
|
||||||
if (ph.u_adler != upx_adler32(in, ph.u_len, ph.saved_u_adler))
|
if (ph.u_adler != upx_adler32(i_ptr, ph.u_len, ph.saved_u_adler))
|
||||||
throwInternalError("decompression failed (checksum error)");
|
throwInternalError("decompression failed (checksum error)");
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
@ -627,7 +628,7 @@ void Packer::initPackHeader()
|
||||||
memset(&ph, 0, sizeof(ph));
|
memset(&ph, 0, sizeof(ph));
|
||||||
ph.version = getVersion();
|
ph.version = getVersion();
|
||||||
ph.format = getFormat();
|
ph.format = getFormat();
|
||||||
ph.method = -1;
|
ph.method = M_NONE;
|
||||||
ph.level = -1;
|
ph.level = -1;
|
||||||
ph.u_adler = ph.c_adler = ph.saved_u_adler = ph.saved_c_adler = upx_adler32(NULL,0);
|
ph.u_adler = ph.c_adler = ph.saved_u_adler = ph.saved_c_adler = upx_adler32(NULL,0);
|
||||||
ph.buf_offset = -1;
|
ph.buf_offset = -1;
|
||||||
|
@ -1139,8 +1140,8 @@ void Packer::relocateLoader()
|
||||||
//
|
//
|
||||||
// - updates this->ph
|
// - updates this->ph
|
||||||
// - updates *ft
|
// - updates *ft
|
||||||
// - ibuf[] is restored to the original unfiltered version
|
// - i_ptr[] is restored to the original unfiltered version
|
||||||
// - obuf[] contains the best compressed version
|
// - o_ptr[] contains the best compressed version
|
||||||
//
|
//
|
||||||
// filter_strategy:
|
// filter_strategy:
|
||||||
// n: try the first N filters, use best one
|
// n: try the first N filters, use best one
|
||||||
|
@ -1258,23 +1259,23 @@ done:
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Packer::compressWithFilters(Filter *parm_ft,
|
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 unsigned overlap_range,
|
||||||
const upx_compress_config_t *cconf,
|
const upx_compress_config_t *cconf,
|
||||||
int filter_strategy,
|
int filter_strategy)
|
||||||
unsigned filter_off, unsigned compress_buf_off,
|
|
||||||
const upx_bytep hdr_buf, unsigned hdr_u_len)
|
|
||||||
{
|
{
|
||||||
|
parm_ft->buf_len = f_len;
|
||||||
// struct copies
|
// 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;
|
||||||
//
|
//
|
||||||
const unsigned compress_buf_len = orig_ph.u_len;
|
best_ph.c_len = i_len;
|
||||||
const unsigned filter_len = orig_ft.buf_len ? orig_ft.buf_len : compress_buf_len;
|
|
||||||
//
|
|
||||||
best_ph.c_len = orig_ph.u_len;
|
|
||||||
best_ph.overlap_overhead = 0;
|
best_ph.overlap_overhead = 0;
|
||||||
unsigned best_ph_lsize = 0;
|
unsigned best_ph_lsize = 0;
|
||||||
unsigned best_hdr_c_len = 0;
|
unsigned best_hdr_c_len = 0;
|
||||||
|
@ -1282,11 +1283,10 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
// preconditions
|
// preconditions
|
||||||
assert(orig_ph.filter == 0);
|
assert(orig_ph.filter == 0);
|
||||||
assert(orig_ft.id == 0);
|
assert(orig_ft.id == 0);
|
||||||
assert(filter_off + filter_len <= compress_buf_off + compress_buf_len);
|
|
||||||
|
|
||||||
// prepare methods and filters
|
// prepare methods and filters
|
||||||
int methods[256];
|
int methods[256];
|
||||||
int nmethods = prepareMethods(methods, ph.method, getCompressionMethods(-1, ph.level));
|
int nmethods = prepareMethods(methods, ph.method, getCompressionMethods(M_ALL, ph.level));
|
||||||
assert(nmethods > 0); assert(nmethods < 256);
|
assert(nmethods > 0); assert(nmethods < 256);
|
||||||
int filters[256];
|
int filters[256];
|
||||||
int nfilters = prepareFilters(filters, filter_strategy, getFilters());
|
int nfilters = prepareFilters(filters, filter_strategy, getFilters());
|
||||||
|
@ -1307,9 +1307,9 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
else
|
else
|
||||||
uip->ui_total_passes += nfilters * nmethods;
|
uip->ui_total_passes += nfilters * nmethods;
|
||||||
|
|
||||||
// Working buffer for compressed data. Don't waste memory.
|
// Working buffer for compressed data. Don't waste memory and allocate as needed.
|
||||||
MemBuffer *otemp = &obuf;
|
upx_bytep o_tmp = o_ptr;
|
||||||
MemBuffer otemp_buf;
|
MemBuffer o_tmp_buf;
|
||||||
|
|
||||||
// compress using all methods/filters
|
// compress using all methods/filters
|
||||||
int nfilters_success_total = 0;
|
int nfilters_success_total = 0;
|
||||||
|
@ -1317,27 +1317,25 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
{
|
{
|
||||||
assert(isValidCompressionMethod(methods[mm]));
|
assert(isValidCompressionMethod(methods[mm]));
|
||||||
unsigned hdr_c_len = 0;
|
unsigned hdr_c_len = 0;
|
||||||
if (hdr_buf && hdr_u_len)
|
if (hdr_ptr != NULL && hdr_len)
|
||||||
{
|
{
|
||||||
if (nfilters_success_total != 0 && otemp == &obuf)
|
if (nfilters_success_total != 0 && o_tmp == o_ptr)
|
||||||
{
|
{
|
||||||
// do not overwrite obuf
|
// do not overwrite o_ptr
|
||||||
otemp_buf.allocForCompression(compress_buf_len);
|
o_tmp_buf.allocForCompression(UPX_MAX(hdr_len, i_len));
|
||||||
otemp = &otemp_buf;
|
o_tmp = o_tmp_buf;
|
||||||
}
|
}
|
||||||
int r = upx_compress(hdr_buf, hdr_u_len, *otemp, &hdr_c_len,
|
int r = upx_compress(hdr_ptr, hdr_len, o_tmp, &hdr_c_len,
|
||||||
NULL, methods[mm], 10, NULL, NULL);
|
NULL, methods[mm], 10, NULL, NULL);
|
||||||
if (r != UPX_E_OK)
|
if (r != UPX_E_OK)
|
||||||
throwInternalError("header compression failed");
|
throwInternalError("header compression failed");
|
||||||
if (hdr_c_len >= hdr_u_len)
|
if (hdr_c_len >= hdr_len)
|
||||||
throwInternalError("header compression size increase");
|
throwInternalError("header compression size increase");
|
||||||
}
|
}
|
||||||
int nfilters_success_mm = 0;
|
int nfilters_success_mm = 0;
|
||||||
for (int ff = 0; ff < nfilters; ff++) // for all filters
|
for (int ff = 0; ff < nfilters; ff++) // for all filters
|
||||||
{
|
{
|
||||||
assert(isValidFilter(filters[ff]));
|
assert(isValidFilter(filters[ff]));
|
||||||
ibuf.checkState();
|
|
||||||
obuf.checkState();
|
|
||||||
// get fresh packheader
|
// get fresh packheader
|
||||||
ph = orig_ph;
|
ph = orig_ph;
|
||||||
ph.method = methods[mm];
|
ph.method = methods[mm];
|
||||||
|
@ -1347,8 +1345,8 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
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, f_ptr, f_len);
|
||||||
bool success = ft.filter(ibuf + filter_off, filter_len);
|
bool success = ft.filter(f_ptr, f_len);
|
||||||
if (ft.id != 0 && ft.calls == 0)
|
if (ft.id != 0 && ft.calls == 0)
|
||||||
{
|
{
|
||||||
// filter did not do anything - no need to call ft.unfilter()
|
// filter did not do anything - no need to call ft.unfilter()
|
||||||
|
@ -1370,23 +1368,23 @@ 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_total != 0 && otemp == &obuf)
|
if (nfilters_success_total != 0 && o_tmp == o_ptr)
|
||||||
{
|
{
|
||||||
otemp_buf.allocForCompression(compress_buf_len);
|
o_tmp_buf.allocForCompression(i_len);
|
||||||
otemp = &otemp_buf;
|
o_tmp = o_tmp_buf;
|
||||||
}
|
}
|
||||||
nfilters_success_total++;
|
nfilters_success_total++;
|
||||||
nfilters_success_mm++;
|
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
|
||||||
if (compress(ibuf + compress_buf_off, *otemp, cconf))
|
if (compress(i_ptr, i_len, o_tmp, cconf))
|
||||||
{
|
{
|
||||||
unsigned lsize = 0;
|
unsigned lsize = 0;
|
||||||
if (ph.c_len + lsize + hdr_c_len <= best_ph.c_len + best_ph_lsize + best_hdr_c_len)
|
if (ph.c_len + lsize + hdr_c_len <= best_ph.c_len + best_ph_lsize + best_hdr_c_len)
|
||||||
{
|
{
|
||||||
// get results
|
// get results
|
||||||
ph.overlap_overhead = findOverlapOverhead(*otemp, overlap_range);
|
ph.overlap_overhead = findOverlapOverhead(o_tmp, overlap_range);
|
||||||
buildLoader(&ft);
|
buildLoader(&ft);
|
||||||
lsize = getLoaderSize();
|
lsize = getLoaderSize();
|
||||||
assert(lsize > 0);
|
assert(lsize > 0);
|
||||||
|
@ -1414,9 +1412,9 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
if (update)
|
if (update)
|
||||||
{
|
{
|
||||||
assert((int)ph.overlap_overhead > 0);
|
assert((int)ph.overlap_overhead > 0);
|
||||||
// update obuf[] with best version
|
// update o_ptr[] with best version
|
||||||
if (otemp != &obuf)
|
if (o_tmp != o_ptr)
|
||||||
memcpy(obuf, *otemp, ph.c_len);
|
memcpy(o_ptr, o_tmp, ph.c_len);
|
||||||
// save compression results
|
// save compression results
|
||||||
best_ph = ph;
|
best_ph = ph;
|
||||||
best_ph_lsize = lsize;
|
best_ph_lsize = lsize;
|
||||||
|
@ -1424,13 +1422,8 @@ void Packer::compressWithFilters(Filter *parm_ft,
|
||||||
best_ft = ft;
|
best_ft = ft;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// restore ibuf[] - unfilter with verify
|
// restore - unfilter with verify
|
||||||
ft.unfilter(ibuf + filter_off, filter_len, true);
|
ft.unfilter(f_ptr, f_len, true);
|
||||||
//
|
|
||||||
ibuf.checkState();
|
|
||||||
obuf.checkState();
|
|
||||||
otemp->checkState();
|
|
||||||
//
|
|
||||||
if (filter_strategy < 0)
|
if (filter_strategy < 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1462,6 +1455,49 @@ void Packer::compressWithFilters(Filter *parm_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
|
vi:ts=4:et:nowrap
|
||||||
*/
|
*/
|
||||||
|
|
29
src/packer.h
29
src/packer.h
|
@ -169,7 +169,7 @@ public:
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
// main compression drivers
|
// main compression drivers
|
||||||
virtual bool compress(upx_bytep in, upx_bytep out,
|
virtual bool compress(upx_bytep i_ptr, unsigned i_len, upx_bytep o_ptr,
|
||||||
const upx_compress_config_t *cconf = NULL);
|
const upx_compress_config_t *cconf = NULL);
|
||||||
virtual void decompress(const upx_bytep in, upx_bytep out,
|
virtual void decompress(const upx_bytep in, upx_bytep out,
|
||||||
bool verify_checksum = true, Filter *ft = NULL);
|
bool verify_checksum = true, Filter *ft = NULL);
|
||||||
|
@ -181,11 +181,24 @@ protected:
|
||||||
void compressWithFilters(Filter *ft,
|
void compressWithFilters(Filter *ft,
|
||||||
const unsigned overlap_range,
|
const unsigned overlap_range,
|
||||||
const upx_compress_config_t *cconf,
|
const upx_compress_config_t *cconf,
|
||||||
int filter_strategy = 0,
|
int filter_strategy = 0);
|
||||||
unsigned filter_buf_off = 0,
|
void compressWithFilters(Filter *ft,
|
||||||
unsigned compress_buf_off = 0,
|
const unsigned overlap_range,
|
||||||
const upx_bytep header_buffer = NULL,
|
const upx_compress_config_t *cconf,
|
||||||
unsigned header_length = 0);
|
int filter_strategy,
|
||||||
|
unsigned filter_buf_off,
|
||||||
|
unsigned compress_ibuf_off,
|
||||||
|
unsigned compress_obuf_off,
|
||||||
|
const upx_bytep hdr_ptr, unsigned hdr_len);
|
||||||
|
// real compression driver
|
||||||
|
void 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 *ft,
|
||||||
|
const unsigned overlap_range,
|
||||||
|
const upx_compress_config_t *cconf,
|
||||||
|
int filter_strategy);
|
||||||
|
|
||||||
// util for verifying overlapping decompresion
|
// util for verifying overlapping decompresion
|
||||||
// non-destructive test
|
// non-destructive test
|
||||||
|
@ -233,10 +246,6 @@ protected:
|
||||||
|
|
||||||
// filter handling [see packer_f.cpp]
|
// filter handling [see packer_f.cpp]
|
||||||
virtual bool isValidFilter(int filter_id) const;
|
virtual bool isValidFilter(int filter_id) const;
|
||||||
virtual void tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
|
||||||
unsigned addvalue=0) const;
|
|
||||||
virtual void scanFilters(Filter *ft, const upx_byte *buf, unsigned buf_len,
|
|
||||||
unsigned addvalue=0) const;
|
|
||||||
virtual void optimizeFilter(Filter *, const upx_byte *, unsigned) const
|
virtual void optimizeFilter(Filter *, const upx_byte *, unsigned) const
|
||||||
{ }
|
{ }
|
||||||
virtual void addFilter32(int filter_id);
|
virtual void addFilter32(int filter_id);
|
||||||
|
|
|
@ -60,7 +60,7 @@ const int *Packer::getDefaultCompressionMethods_8(int method, int level, int sma
|
||||||
static const int m_nrv2d[] = { 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 };
|
static const int m_nrv2e[] = { M_NRV2E_8, M_END };
|
||||||
|
|
||||||
if (method == -1) return m_all;
|
if (method == M_ALL) return m_all;
|
||||||
//if (M_IS_CL1B(method)) return m_cl1b;
|
//if (M_IS_CL1B(method)) return m_cl1b;
|
||||||
if (M_IS_LZMA(method)) return m_lzma;
|
if (M_IS_LZMA(method)) return m_lzma;
|
||||||
if (M_IS_NRV2B(method)) return m_nrv2b;
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
|
@ -83,7 +83,7 @@ const int *Packer::getDefaultCompressionMethods_le32(int method, int level, int
|
||||||
static const int m_nrv2d[] = { M_NRV2D_LE32, M_END };
|
static const int m_nrv2d[] = { M_NRV2D_LE32, M_END };
|
||||||
static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
|
static const int m_nrv2e[] = { M_NRV2E_LE32, M_END };
|
||||||
|
|
||||||
if (method == -1) return m_all;
|
if (method == M_ALL) return m_all;
|
||||||
//if (M_IS_CL1B(method)) return m_cl1b;
|
//if (M_IS_CL1B(method)) return m_cl1b;
|
||||||
if (M_IS_LZMA(method)) return m_lzma;
|
if (M_IS_LZMA(method)) return m_lzma;
|
||||||
if (M_IS_NRV2B(method)) return m_nrv2b;
|
if (M_IS_NRV2B(method)) return m_nrv2b;
|
||||||
|
|
|
@ -41,54 +41,6 @@ bool Packer::isValidFilter(int filter_id) const
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void Packer::tryFilters(Filter *ft, upx_byte *buf, unsigned buf_len,
|
|
||||||
unsigned addvalue) const
|
|
||||||
{
|
|
||||||
// debug
|
|
||||||
//scanFilters(ft, buf, buf_len, addvalue);
|
|
||||||
|
|
||||||
ft->init();
|
|
||||||
if (opt->filter == 0)
|
|
||||||
return;
|
|
||||||
for (const int *f = getFilters(); f && *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == 0) // skip no-filter
|
|
||||||
continue;
|
|
||||||
if (opt->filter < 0 || *f == opt->filter)
|
|
||||||
{
|
|
||||||
ft->init(*f, addvalue);
|
|
||||||
optimizeFilter(ft, buf, buf_len);
|
|
||||||
if (ft->filter(buf, buf_len) && ft->calls > 0)
|
|
||||||
break; // success
|
|
||||||
ft->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void Packer::scanFilters(Filter *ft, const upx_byte *buf, unsigned buf_len,
|
|
||||||
unsigned addvalue) const
|
|
||||||
{
|
|
||||||
ft->init();
|
|
||||||
if (opt->filter == 0)
|
|
||||||
return;
|
|
||||||
for (const int *f = getFilters(); f && *f >= 0; f++)
|
|
||||||
{
|
|
||||||
if (*f == 0) // skip no-filter
|
|
||||||
continue;
|
|
||||||
ft->init(*f, addvalue);
|
|
||||||
//static const int ctos[] = { 0xff, 0xfe, 0x80, 0x22, -1 };
|
|
||||||
//ft->preferred_ctos = ctos;
|
|
||||||
if (ft->scan(buf, buf_len))
|
|
||||||
{
|
|
||||||
printf("scanFilters: id 0x%02x size: %6d: calls %5d/%5d/%3d, cto 0x%02x\n",
|
|
||||||
ft->id, ft->buf_len, ft->calls, ft->noncalls, ft->wrongcalls, ft->cto);
|
|
||||||
}
|
|
||||||
ft->init();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*************************************************************************
|
/*************************************************************************
|
||||||
// addFilter32
|
// addFilter32
|
||||||
**************************************************************************/
|
**************************************************************************/
|
||||||
|
|
Loading…
Reference in New Issue
Block a user