mirror of
https://github.com/upx/upx
synced 2025-09-28 19:06:07 +08:00
pe: better icon compression handling
This commit is contained in:
parent
5b1c154ee2
commit
fe53b135eb
1
NEWS
1
NEWS
|
@ -6,6 +6,7 @@ Changes in 2.93 beta (XX XXX 2007):
|
||||||
* new formats Mach/i386 and Mach/fat support Mac OS X i686 and
|
* new formats Mach/i386 and Mach/fat support Mac OS X i686 and
|
||||||
Univeral binaries [i686 and PowerPC only]
|
Univeral binaries [i686 and PowerPC only]
|
||||||
* LZMA algorithm support for dos/exe added; use option '--lzma' to enable
|
* LZMA algorithm support for dos/exe added; use option '--lzma' to enable
|
||||||
|
* pe: better icon compression handling
|
||||||
|
|
||||||
Changes in 2.92 beta (23 Jan 2007):
|
Changes in 2.92 beta (23 Jan 2007):
|
||||||
* new option '--ultra-brute' which tries even more variants
|
* new option '--ultra-brute' which tries even more variants
|
||||||
|
|
|
@ -50,18 +50,6 @@
|
||||||
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
|
# define strcpy(a,b) strcpy((char *)(a),(const char *)(b))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
// Unicode string compare
|
|
||||||
static bool ustrsame(const void *s1, const void *s2)
|
|
||||||
{
|
|
||||||
unsigned len1 = get_le16(s1);
|
|
||||||
unsigned len2 = get_le16(s2);
|
|
||||||
if (len1 != len2)
|
|
||||||
return false;
|
|
||||||
return memcmp(s1, s2, 2 + 2*len1) == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)
|
#if (__ACC_CXX_HAVE_PLACEMENT_DELETE) || defined(__DJGPP__)
|
||||||
#include "bptr.h"
|
#include "bptr.h"
|
||||||
#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
|
#define IPTR(type, var) BoundedPtr<type> var(ibuf, ibuf.getSize())
|
||||||
|
@ -1245,6 +1233,12 @@ upx_byte *PeFile::Resource::build()
|
||||||
newstart = new upx_byte [dirsize()];
|
newstart = new upx_byte [dirsize()];
|
||||||
unsigned bpos = 0,spos = dsize;
|
unsigned bpos = 0,spos = dsize;
|
||||||
build(root,bpos,spos,0);
|
build(root,bpos,spos,0);
|
||||||
|
|
||||||
|
// dirsize() is 4 bytes aligned, so we may need to zero
|
||||||
|
// up to 2 bytes to make valgrind happy
|
||||||
|
while (spos < dirsize())
|
||||||
|
newstart[spos++] = 0;
|
||||||
|
|
||||||
return newstart;
|
return newstart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1349,7 +1343,7 @@ static bool match(unsigned itype, const unsigned char *ntype,
|
||||||
if (unistr[2 + ic * 2] != (unsigned char) mkeep[ic])
|
if (unistr[2 + ic * 2] != (unsigned char) mkeep[ic])
|
||||||
return false;
|
return false;
|
||||||
return mkeep[ic] == 0 || mkeep[ic] == ',' || mkeep[ic] == '/';
|
return mkeep[ic] == 0 || mkeep[ic] == ',' || mkeep[ic] == '/';
|
||||||
};
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME this comparison is not too exact
|
// FIXME this comparison is not too exact
|
||||||
|
@ -1404,15 +1398,31 @@ void PeFile::processResources(Resource *res)
|
||||||
oresources = new upx_byte[soresources];
|
oresources = new upx_byte[soresources];
|
||||||
upx_byte *ores = oresources + res->dirsize();
|
upx_byte *ores = oresources + res->dirsize();
|
||||||
|
|
||||||
|
char *keep_icons = NULL; // icon ids in the first icon group
|
||||||
unsigned iconsin1stdir = 0;
|
unsigned iconsin1stdir = 0;
|
||||||
if (opt->win32_pe.compress_icons == 2)
|
if (opt->win32_pe.compress_icons == 2)
|
||||||
while (res->next()) // there is no rewind() in Resource
|
while (res->next()) // there is no rewind() in Resource
|
||||||
if (res->itype() == RT_GROUP_ICON && iconsin1stdir == 0)
|
if (res->itype() == RT_GROUP_ICON && iconsin1stdir == 0)
|
||||||
|
{
|
||||||
iconsin1stdir = get_le16(ibuf + res->offs() + 4);
|
iconsin1stdir = get_le16(ibuf + res->offs() + 4);
|
||||||
|
keep_icons = new char[1 + iconsin1stdir * 9];
|
||||||
|
*keep_icons = 0;
|
||||||
|
for (unsigned ic = 0; ic < iconsin1stdir; ic++)
|
||||||
|
snprintf(keep_icons + strlen(keep_icons), 9, "3/%u,",
|
||||||
|
get_le16(ibuf + res->offs() + 6 + ic * 14 + 12));
|
||||||
|
if (*keep_icons)
|
||||||
|
keep_icons[strlen(keep_icons) - 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
bool compress_icon = opt->win32_pe.compress_icons == 3;
|
// the icon id which should not be compressed when compress_icons == 1
|
||||||
bool compress_idir = false;
|
unsigned first_icon_id = (unsigned) -1;
|
||||||
unsigned iconcnt = 0;
|
if (opt->win32_pe.compress_icons == 1)
|
||||||
|
while (res->next())
|
||||||
|
if (res->itype() == RT_GROUP_ICON && first_icon_id == (unsigned) -1)
|
||||||
|
first_icon_id = get_le16(ibuf + res->offs() + 6 + 12);
|
||||||
|
|
||||||
|
bool compress_icon = opt->win32_pe.compress_icons > 1;
|
||||||
|
bool compress_idir = opt->win32_pe.compress_icons == 3;
|
||||||
|
|
||||||
// some statistics
|
// some statistics
|
||||||
unsigned usize = 0;
|
unsigned usize = 0;
|
||||||
|
@ -1426,26 +1436,27 @@ void PeFile::processResources(Resource *res)
|
||||||
bool do_compress = true;
|
bool do_compress = true;
|
||||||
if (!opt->win32_pe.compress_resources)
|
if (!opt->win32_pe.compress_resources)
|
||||||
do_compress = false;
|
do_compress = false;
|
||||||
else if (rtype == RT_VERSION) // version info
|
|
||||||
do_compress = false;
|
|
||||||
else if (rtype == RT_ICON) // icon
|
else if (rtype == RT_ICON) // icon
|
||||||
do_compress = compress_icon && opt->win32_pe.compress_icons;
|
{
|
||||||
|
if (opt->win32_pe.compress_icons == 0)
|
||||||
|
do_compress = false;
|
||||||
|
else if (opt->win32_pe.compress_icons == 1)
|
||||||
|
if ((first_icon_id == (unsigned) -1
|
||||||
|
|| first_icon_id == res->iname()))
|
||||||
|
do_compress = compress_icon;
|
||||||
|
}
|
||||||
else if (rtype == RT_GROUP_ICON) // icon directory
|
else if (rtype == RT_GROUP_ICON) // icon directory
|
||||||
do_compress = compress_idir && opt->win32_pe.compress_icons;
|
do_compress = compress_idir && opt->win32_pe.compress_icons;
|
||||||
else if (rtype > 0 && rtype < RT_LAST)
|
else if (rtype > 0 && rtype < RT_LAST)
|
||||||
do_compress = opt->win32_pe.compress_rt[rtype] ? true : false;
|
do_compress = opt->win32_pe.compress_rt[rtype] ? true : false;
|
||||||
else if (res->ntype()) // named resource type
|
|
||||||
{
|
|
||||||
const upx_byte * const t = res->ntype();
|
|
||||||
if (ustrsame(t, "\x7\x0T\x0Y\x0P\x0""E\x0L\x0I\x0""B\x0"))
|
|
||||||
do_compress = false; // u"TYPELIB"
|
|
||||||
else if (ustrsame(t, "\x8\x0R\x0""E\x0G\x0I\x0S\x0T\x0R\x0Y\x0"))
|
|
||||||
do_compress = false; // u"REGISTRY"
|
|
||||||
}
|
|
||||||
|
|
||||||
if (do_compress && opt->win32_pe.keep_resource[0])
|
if (keep_icons)
|
||||||
do_compress ^= match(res->itype(), res->ntype(), res->iname(),
|
do_compress &= !match(res->itype(), res->ntype(), res->iname(),
|
||||||
res->nname(), opt->win32_pe.keep_resource);
|
res->nname(), keep_icons);
|
||||||
|
do_compress &= !match(res->itype(), res->ntype(), res->iname(),
|
||||||
|
res->nname(), "TYPELIB,REGISTRY,16");
|
||||||
|
do_compress &= !match(res->itype(), res->ntype(), res->iname(),
|
||||||
|
res->nname(), opt->win32_pe.keep_resource);
|
||||||
|
|
||||||
if (do_compress)
|
if (do_compress)
|
||||||
{
|
{
|
||||||
|
@ -1463,8 +1474,8 @@ void PeFile::processResources(Resource *res)
|
||||||
memcpy(ores, ibuf + res->offs(), res->size());
|
memcpy(ores, ibuf + res->offs(), res->size());
|
||||||
ibuf.fill(res->offs(), res->size(), FILLVAL);
|
ibuf.fill(res->offs(), res->size(), FILLVAL);
|
||||||
res->newoffs() = ptr_diff(ores,oresources);
|
res->newoffs() = ptr_diff(ores,oresources);
|
||||||
if (rtype == RT_ICON)
|
if (rtype == RT_ICON && opt->win32_pe.compress_icons == 1)
|
||||||
compress_icon = (++iconcnt >= iconsin1stdir || opt->win32_pe.compress_icons == 1);
|
compress_icon = true;
|
||||||
else if (rtype == RT_GROUP_ICON)
|
else if (rtype == RT_GROUP_ICON)
|
||||||
{
|
{
|
||||||
if (opt->win32_pe.compress_icons == 1)
|
if (opt->win32_pe.compress_icons == 1)
|
||||||
|
@ -1479,6 +1490,7 @@ void PeFile::processResources(Resource *res)
|
||||||
}
|
}
|
||||||
soresources = ptr_diff(ores,oresources);
|
soresources = ptr_diff(ores,oresources);
|
||||||
|
|
||||||
|
delete[] keep_icons;
|
||||||
if (!res->clear())
|
if (!res->clear())
|
||||||
{
|
{
|
||||||
// The area occupied by the resource directory is not continuous
|
// The area occupied by the resource directory is not continuous
|
||||||
|
|
Loading…
Reference in New Issue
Block a user