Extra parameter for compressWithFilters and packExtent,

to fix 2-pass problem with --brute on linux/elf386.
Only one decompression method is allowed, chosen by
smallest output for .text; but Elf headers come first.
	packer.cpp packer.h p_unix.cpp p_unix.h p_lx_elf.cpp

committer: jreiser <jreiser> 1140241030 +0000
This commit is contained in:
John Reiser
2006-02-18 05:37:10 +00:00
parent d3bcba6a05
commit 268e322e1c
5 changed files with 80 additions and 39 deletions
+37 -8
View File
@@ -1258,13 +1258,32 @@ const char *Packer::getDecompressor() const
// executable formats.
//
// It will replace the tryFilters() / compress() call sequence.
// 2006-02-15: hdr_buf and hdr_u_len are default empty input "header" array
// to fix a 2-pass problem with Elf headers. As of today there can be
// only one decompression method per executable output file, and that method
// is the one that gives best compression for .text and loader. However,
// the Elf headers precede .text in the output file, and are written first.
// "--brute" compression often compressed the Elf headers using nrv2b
// but the .text (and loader) with nrv2e. This often resulted in SIGSEGV
// during decompression.
// The workaround is for hdr_buf and hdr_u_len to describe the Elf headers
// (typically less than 512 bytes) when .text is passed in, and include
// them in the calculation of shortest output. Then the result
// this->ph.method will say which [single] method to use for everthing.
// The Elf headers are never filtered. They are short enough (< 512 bytes)
// that compressing them more than once per method (once here when choosing,
// once again just before writing [because compressWithFilters discards])
// is OK because of the simplicity of not having two output arrays.
**************************************************************************/
void Packer::compressWithFilters(Filter *parm_ft,
const unsigned overlap_range,
int strategy, const int *parm_filters,
unsigned max_offset, unsigned max_match,
unsigned filter_off, unsigned compress_buf_off)
unsigned filter_off, unsigned compress_buf_off,
unsigned char *hdr_buf,
unsigned hdr_u_len)
{
const int *f;
//
@@ -1280,6 +1299,7 @@ void Packer::compressWithFilters(Filter *parm_ft,
best_ph.c_len = orig_ph.u_len;
best_ph.overlap_overhead = 0;
unsigned best_ph_lsize = 0;
unsigned best_hdr_clen = 0;
// preconditions
assert(orig_ph.filter == 0);
@@ -1373,6 +1393,14 @@ void Packer::compressWithFilters(Filter *parm_ft,
int nfilters_success = 0;
for (int m = 0; m < nmethods; m++) // for all methods
{
unsigned hdr_clen = 0;
if (hdr_buf && hdr_u_len) {
unsigned result[16];
upx_compress_config_t conf;
memset(&conf, 0xff, sizeof(conf));
int r = upx_compress(hdr_buf, hdr_u_len, obuf, &hdr_clen,
0, methods[m], 10, &conf, result);
}
for (int i = 0; i < nfilters; i++) // for all filters
{
ibuf.checkState();
@@ -1428,19 +1456,19 @@ void Packer::compressWithFilters(Filter *parm_ft,
lsize = buildLoader(&ft);
}
#if 0
printf("\n%2d %02x: %d +%4d = %d (best: %d +%4d = %d)\n", ph.method, ph.filter,
ph.c_len, lsize, ph.c_len + lsize,
best_ph.c_len, best_ph_lsize, best_ph.c_len + best_ph_lsize);
printf("\n%2d %02x: %d +%4d +%3d = %d (best: %d +%4d +%3d = %d)\n", ph.method, ph.filter,
ph.c_len, lsize, hdr_clen, ph.c_len + lsize + hdr_clen,
best_ph.c_len, best_ph_lsize, best_hdr_clen, best_ph.c_len + best_ph_lsize + best_hdr_clen);
#endif
bool update = false;
if (ph.c_len + lsize < best_ph.c_len + best_ph_lsize)
if (ph.c_len + lsize + hdr_clen < best_ph.c_len + best_ph_lsize + best_hdr_clen)
update = true;
else if (ph.c_len + lsize == best_ph.c_len + best_ph_lsize)
else if (ph.c_len + lsize + hdr_clen == best_ph.c_len + best_ph_lsize + best_hdr_clen)
{
// prefer smaller loaders
if (lsize < best_ph_lsize)
if (lsize + hdr_clen < best_ph_lsize + best_hdr_clen)
update = true;
else if (lsize == best_ph_lsize)
else if (lsize + hdr_clen == best_ph_lsize + best_hdr_clen)
{
// prefer less overlap_overhead
if (ph.overlap_overhead < best_ph.overlap_overhead)
@@ -1455,6 +1483,7 @@ void Packer::compressWithFilters(Filter *parm_ft,
// save compression results
best_ph = ph;
best_ph_lsize = lsize;
best_hdr_clen = hdr_clen;
best_ft = ft;
}
}