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:
parent
9a3b7a4f3f
commit
3dfe0ad478
3
PROJECTS
3
PROJECTS
|
@ -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
3
TODO
|
@ -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
|
||||
|
|
16
doc/upx.pod
16
doc/upx.pod
|
@ -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.
|
||||
|
|
|
@ -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 }
|
||||
};
|
||||
|
|
|
@ -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;
|
||||
};
|
||||
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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();
|
||||
|
|
Loading…
Reference in New Issue
Block a user