1
0
mirror of https://github.com/upx/upx synced 2025-09-28 19:06:07 +08:00

pe: fined grain control over resource compression

This commit is contained in:
László Molnár 2006-05-18 15:20:37 +02:00
parent 9a3b7a4f3f
commit 3dfe0ad478
7 changed files with 129 additions and 8 deletions

View File

@ -66,8 +66,7 @@ Existing formats:
- win32/pe: display a nice dialog box in the stub in case
of problems (like importing a DLL or function fails)
- win32/pe: finer control over resource compression, per section
compression
- win32/pe: per section compression
Compression ratio:

3
TODO
View File

@ -105,9 +105,6 @@ FORMAT WIN32/PE
- decrease runtime memory overhead
2 - easy - mfx + ml) new switch(es) : do not compress resource types x,y,z
or resource names a,b,c
3 - difficult) don't compress the BSS section and other holes.
4 - medium - ml) fix when objectalign < 0x1000

View File

@ -870,6 +870,22 @@ Extra options available for this executable format:
--compress-resources=0 Don't compress any resources at all.
--keep-resource=list Don't compress resources specified by the list.
The members of the list are separated by commas.
A list member has the following format: I<type[/name]>.
I<Type> is the type of the resource. Standard types
must be specified as decimal numbers, user types can be
specified by decimal IDs or strings. I<Name> is the
identifier of the resource. It can be a decimal number
or a string. For example:
--keep-resource=2/MYBITMAP,5,6/12345
UPX won't compress the named bitmap resource "MYBITMAP",
it leaves every dialog (5) resource uncompressed, and
it won't touch the string table resource with identifier
12345.
--force Force compression even when there is an
unexpected value in a header field.
Use with care.

View File

@ -72,6 +72,7 @@ void init_options(struct options_t *o)
o->win32_pe.compress_rt[i] = -1;
o->win32_pe.compress_rt[24] = false; // 24 == RT_MANIFEST
o->win32_pe.strip_relocs = -1;
o->win32_pe.keep_resource = "";
}
static struct options_t global_options;
@ -702,6 +703,11 @@ static int do_option(int optc, const char *arg)
opt->win32_pe.strip_relocs = 0;
//printf("strip_relocs: %d\n", opt->win32_pe.strip_relocs);
break;
case 635:
if (!mfx_optarg || !mfx_optarg[0])
e_optarg(arg);
opt->win32_pe.keep_resource = mfx_optarg;
break;
case 650:
opt->atari_tos.split_segments = true;
break;
@ -859,6 +865,7 @@ static const struct mfx_option longopts[] =
{"compress-resources", 2, 0, 632},
{"strip-loadconf", 0x12, 0, 633}, // OBSOLETE - IGNORED
{"strip-relocs", 0x12, 0, 634},
{"keep-resource", 0x31, 0, 635},
// ps1/exe
{"boot-only", 0x10, 0, 670},
{"no-align", 0x10, 0, 671},
@ -941,6 +948,7 @@ static const struct mfx_option longopts[] =
{"compress-resources", 2, 0, 632},
{"strip-loadconf", 0x12, 0, 633}, // OBSOLETE - IGNORED
{"strip-relocs", 0x12, 0, 634},
{"keep-resource", 0x31, 0, 635},
{ NULL, 0, NULL, 0 }
};

View File

@ -139,6 +139,7 @@ struct options_t {
int compress_resources;
signed char compress_rt[25]; // 25 == RT_LAST
int strip_relocs;
const char *keep_resource;
} win32_pe;
};

View File

@ -1218,10 +1218,10 @@ public:
bool clear();
void dump() const { dump(root,0); }
/*
unsigned iname() const {return current->parent->id;}
const upx_byte *nname() const {return current->parent->name;}
/*
unsigned ilang() const {return current->id;}
const upx_byte *nlang() const {return current->name;}
*/
@ -1420,6 +1420,52 @@ void PackArmPe::processResources(Resource *res,unsigned newaddr)
delete [] p;
}
static bool match(unsigned itype, const unsigned char *ntype,
unsigned iname, const unsigned char *nname,
const char *keep)
{
// format of string keep: type1[/name1],type2[/name2], ....
// typex and namex can be string or number
// hopefully resource names do not have '/' or ',' characters inside
struct helper
{
static bool match(unsigned num, const unsigned char *unistr,
const char *keep)
{
if (!unistr)
return (unsigned) atoi(keep) == num;
unsigned ic;
for (ic = 0; ic < get_le16(unistr); ic++)
if (unistr[2 + ic * 2] != (unsigned char) keep[ic])
return false;
return keep[ic] == 0 || keep[ic] == ',' || keep[ic] == '/';
};
};
// FIXME this comparison is not too exact
while (1)
{
char *delim1 = strchr(keep, '/');
char *delim2 = strchr(keep, ',');
if (helper::match(itype, ntype, keep))
{
if (!delim1)
return true;
if (delim2 && delim2 < delim1)
return true;
if (helper::match(iname, nname, delim1 + 1))
return true;
}
if (delim2 == NULL)
break;
keep = delim2 + 1;
}
return false;
}
void PackArmPe::processResources(Resource *res)
{
const unsigned vaddr = IDADDR(PEDIR_RESOURCE);
@ -1488,6 +1534,10 @@ void PackArmPe::processResources(Resource *res)
do_compress = false; // u"REGISTRY"
}
if (do_compress && opt->win32_pe.keep_resource[0])
do_compress ^= match(res->itype(), res->ntype(), res->iname(),
res->nname(), opt->win32_pe.keep_resource);
if (do_compress)
{
csize += res->size();

View File

@ -1178,10 +1178,10 @@ public:
bool clear();
void dump() const { dump(root,0); }
/*
unsigned iname() const {return current->parent->id;}
const upx_byte *nname() const {return current->parent->name;}
/*
unsigned ilang() const {return current->id;}
const upx_byte *nlang() const {return current->name;}
*/
@ -1380,6 +1380,52 @@ void PackW32Pe::processResources(Resource *res,unsigned newaddr)
delete [] p;
}
static bool match(unsigned itype, const unsigned char *ntype,
unsigned iname, const unsigned char *nname,
const char *keep)
{
// format of string keep: type1[/name1],type2[/name2], ....
// typex and namex can be string or number
// hopefully resource names do not have '/' or ',' characters inside
struct helper
{
static bool match(unsigned num, const unsigned char *unistr,
const char *keep)
{
if (!unistr)
return (unsigned) atoi(keep) == num;
unsigned ic;
for (ic = 0; ic < get_le16(unistr); ic++)
if (unistr[2 + ic * 2] != (unsigned char) keep[ic])
return false;
return keep[ic] == 0 || keep[ic] == ',' || keep[ic] == '/';
};
};
// FIXME this comparison is not too exact
while (1)
{
char *delim1 = strchr(keep, '/');
char *delim2 = strchr(keep, ',');
if (helper::match(itype, ntype, keep))
{
if (!delim1)
return true;
if (delim2 && delim2 < delim1)
return true;
if (helper::match(iname, nname, delim1 + 1))
return true;
}
if (delim2 == NULL)
break;
keep = delim2 + 1;
}
return false;
}
void PackW32Pe::processResources(Resource *res)
{
const unsigned vaddr = IDADDR(PEDIR_RESOURCE);
@ -1448,6 +1494,10 @@ void PackW32Pe::processResources(Resource *res)
do_compress = false; // u"REGISTRY"
}
if (do_compress && opt->win32_pe.keep_resource[0])
do_compress ^= match(res->itype(), res->ntype(), res->iname(),
res->nname(), opt->win32_pe.keep_resource);
if (do_compress)
{
csize += res->size();