Added new field PackHeader::overlap_overhead.
committer: mfx <mfx> 978190533 +0000
This commit is contained in:
parent
85bebf0b43
commit
a8177201ef
@ -93,7 +93,7 @@ bool PackCom::canPack()
|
||||
|
||||
void PackCom::patchLoader(OutputFile *fo,
|
||||
upx_byte *loader, int lsize,
|
||||
unsigned calls, unsigned overlapoh)
|
||||
unsigned calls)
|
||||
{
|
||||
const int filter_id = ph.filter;
|
||||
const int e_len = getLoaderSectionStart("COMCUTPO");
|
||||
@ -101,7 +101,7 @@ void PackCom::patchLoader(OutputFile *fo,
|
||||
assert(e_len > 0 && e_len < 256);
|
||||
assert(d_len > 0 && d_len < 256);
|
||||
|
||||
const unsigned upper_end = ph.u_len + overlapoh + d_len + 0x100;
|
||||
const unsigned upper_end = ph.u_len + ph.overlap_overhead + d_len + 0x100;
|
||||
if (upper_end + STACKSIZE > 0xfffe)
|
||||
throwNotCompressible();
|
||||
|
||||
@ -195,9 +195,6 @@ void PackCom::pack(OutputFile *fo)
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
ft.addvalue = getCallTrickOffset();
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
@ -209,17 +206,18 @@ void PackCom::pack(OutputFile *fo)
|
||||
else if (opt->level == 9)
|
||||
// choose best from the first 4 filters
|
||||
strategy = 4;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
||||
const unsigned overlap_range = ph.u_len < 0xFE00 - ft.addvalue ? 32 : 0;
|
||||
compressWithFilters(&ft, overlap_range, strategy);
|
||||
|
||||
const int lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader,getLoader(),lsize);
|
||||
|
||||
const unsigned calls = ft.id % 3 ? ft.lastcall - 2 * ft.calls : ft.calls;
|
||||
patchLoader(fo, loader, lsize, calls, overlapoh);
|
||||
patchLoader(fo, loader, lsize, calls);
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
|
||||
|
||||
// finally check the compression ratio
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
|
||||
@ -56,7 +56,7 @@ protected:
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned, unsigned);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned);
|
||||
virtual void addFilter16(int filter_id);
|
||||
};
|
||||
|
||||
|
||||
@ -67,6 +67,16 @@ const int *PackDjgpp2::getFilters() const
|
||||
}
|
||||
|
||||
|
||||
unsigned PackDjgpp2::findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range,
|
||||
unsigned upper_limit) const
|
||||
{
|
||||
unsigned o = super::findOverlapOverhead(buf, range, upper_limit);
|
||||
o = (o + 0x3ff) &~ 0x1ff;
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
int PackDjgpp2::buildLoader(const Filter *ft)
|
||||
{
|
||||
// prepare loader
|
||||
@ -158,7 +168,7 @@ static void handle_allegropak(InputFile *fi, OutputFile *fo)
|
||||
}
|
||||
|
||||
|
||||
bool PackDjgpp2::readFileHeader()
|
||||
int PackDjgpp2::readFileHeader()
|
||||
{
|
||||
unsigned char hdr[0x1c];
|
||||
unsigned char magic[8];
|
||||
@ -173,7 +183,7 @@ bool PackDjgpp2::readFileHeader()
|
||||
fi->seek(512,SEEK_SET);
|
||||
fi->readx(magic,8);
|
||||
if (memcmp("go32stub",magic,8) != 0)
|
||||
return false; // not V2 image
|
||||
return 0; // not V2 image
|
||||
fi->seek(coff_offset,SEEK_SET);
|
||||
if (fi->read(&coff_hdr,sizeof(coff_hdr)) != sizeof(coff_hdr))
|
||||
throwCantPack("skipping djgpp symlink");
|
||||
@ -184,17 +194,17 @@ bool PackDjgpp2::readFileHeader()
|
||||
fi->readx(&coff_hdr,0xa8);
|
||||
}
|
||||
if (coff_hdr.f_magic != 0x014c) // I386MAGIC
|
||||
return false;
|
||||
return 0;
|
||||
if ((coff_hdr.f_flags & 2) == 0) // F_EXEC - COFF executable
|
||||
return false;
|
||||
return 0;
|
||||
if (coff_hdr.a_magic != 0413) // ZMAGIC - demand load format
|
||||
return false;
|
||||
return 0;
|
||||
// FIXME: check for Linux etc.
|
||||
|
||||
text = coff_hdr.sh;
|
||||
data = text + 1;
|
||||
bss = data + 1;
|
||||
return true;
|
||||
return UPX_F_DJGPP2_COFF;
|
||||
}
|
||||
|
||||
|
||||
@ -278,10 +288,9 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
ph.u_len = usize;
|
||||
if (!compress(ibuf,obuf))
|
||||
throwNotCompressible();
|
||||
buildLoader(&ft);
|
||||
|
||||
unsigned overlapoh = findOverlapOverhead(obuf,ibuf,512);
|
||||
overlapoh = (overlapoh + 0x3ff) & ~0x1ff;
|
||||
ph.overlap_overhead = findOverlapOverhead(obuf,ibuf,512);
|
||||
buildLoader(&ft);
|
||||
|
||||
// verify filter
|
||||
ft.verifyUnfilter();
|
||||
@ -295,9 +304,6 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
Filter ft(opt->level);
|
||||
ft.buf_len = usize - data->size;
|
||||
ft.addvalue = text->vaddr & ~0x1ff;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 512;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
@ -306,8 +312,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
else if (opt->all_filters)
|
||||
// choose best from all available filters
|
||||
strategy = 0;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
||||
overlapoh = (overlapoh + 0x3ff) & ~0x1ff;
|
||||
compressWithFilters(&ft, 512, strategy);
|
||||
#endif
|
||||
|
||||
// patch coff header #2
|
||||
@ -315,12 +320,12 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
text->size = lsize; // new size of .text
|
||||
data->size = ph.c_len; // new size of .data
|
||||
|
||||
if (bss->size < overlapoh) // give it a .bss
|
||||
bss->size = overlapoh;
|
||||
if (bss->size < ph.overlap_overhead) // give it a .bss
|
||||
bss->size = ph.overlap_overhead;
|
||||
|
||||
text->scnptr = sizeof(coff_hdr);
|
||||
data->scnptr = text->scnptr + text->size;
|
||||
data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size + overlapoh - 0x200;
|
||||
data->vaddr = bss->vaddr + ((data->scnptr + data->size) & 0x1ff) - data->size + ph.overlap_overhead - 0x200;
|
||||
coff_hdr.f_nscns = 3;
|
||||
|
||||
// prepare loader
|
||||
@ -331,7 +336,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
patchPackHeader(loader,lsize);
|
||||
patch_le32(loader,lsize,"ENTR",coff_hdr.a_entry);
|
||||
patchFilter32(loader, lsize, &ft);
|
||||
patch_le32(loader,lsize,"BSSL",overlapoh/4);
|
||||
patch_le32(loader,lsize,"BSSL",ph.overlap_overhead/4);
|
||||
assert(bss->vaddr == ((size + 0x1ff) &~ 0x1ff) + (text->vaddr &~ 0x1ff));
|
||||
patch_le32(loader,lsize,"OUTP",text->vaddr &~ 0x1ff);
|
||||
patch_le32(loader,lsize,"INPP",data->vaddr);
|
||||
@ -339,8 +344,8 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
// patch coff header #3
|
||||
text->vaddr = sizeof(coff_hdr);
|
||||
coff_hdr.a_entry = sizeof(coff_hdr) + getLoaderSection("DJ2MAIN1");
|
||||
bss->vaddr += overlapoh;
|
||||
bss->size -= overlapoh;
|
||||
bss->vaddr += ph.overlap_overhead;
|
||||
bss->size -= ph.overlap_overhead;
|
||||
|
||||
// because of a feature (bug?) in stub.asm we need some padding
|
||||
memcpy(obuf+data->size,"UPX",3);
|
||||
@ -357,7 +362,7 @@ void PackDjgpp2::pack(OutputFile *fo)
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
|
||||
|
||||
// handle overlay
|
||||
// FIXME: only Allegro pakfiles are supported
|
||||
|
||||
@ -53,9 +53,13 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual void handleStub(OutputFile *fo);
|
||||
virtual bool readFileHeader();
|
||||
virtual int readFileHeader();
|
||||
|
||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const;
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
|
||||
long coff_offset;
|
||||
|
||||
|
||||
@ -116,9 +116,6 @@ void PackElks8086::pack(OutputFile *fo)
|
||||
Filter ft(opt->level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = kernel_entry;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 1 << 20;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
@ -127,7 +124,7 @@ void PackElks8086::pack(OutputFile *fo)
|
||||
else if (opt->all_filters)
|
||||
// choose best from all available filters
|
||||
strategy = 0;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
||||
compressWithFilters(&ft, overlap_range, strategy);
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
|
||||
@ -65,7 +65,7 @@ bool PackSys::canPack()
|
||||
|
||||
void PackSys::patchLoader(OutputFile *fo,
|
||||
upx_byte *loader, int lsize,
|
||||
unsigned calls, unsigned overlapoh)
|
||||
unsigned calls)
|
||||
{
|
||||
const int filter_id = ph.filter;
|
||||
const int e_len = getLoaderSectionStart("SYSCUTPO");
|
||||
@ -73,13 +73,13 @@ void PackSys::patchLoader(OutputFile *fo,
|
||||
assert(e_len > 0 && e_len < 256);
|
||||
assert(d_len > 0 && d_len < 256);
|
||||
|
||||
if (ph.u_len + d_len + overlapoh > 0xfffe)
|
||||
if (ph.u_len + d_len + ph.overlap_overhead > 0xfffe)
|
||||
throwNotCompressible();
|
||||
|
||||
memcpy(loader,ibuf,6); // copy from orig. header
|
||||
memcpy(loader+8,ibuf+8,2); // opendos wants this word too
|
||||
|
||||
unsigned copy_to = ph.u_len + d_len + overlapoh;
|
||||
unsigned copy_to = ph.u_len + d_len + ph.overlap_overhead;
|
||||
|
||||
patch_le16(loader,lsize,"JO",get_le16(ibuf+6)-copy_to-1);
|
||||
if (filter_id)
|
||||
@ -90,7 +90,7 @@ void PackSys::patchLoader(OutputFile *fo,
|
||||
patchPackHeader(loader,e_len);
|
||||
|
||||
const unsigned jmp_pos = find_le16(loader,e_len,get_le16("JM"));
|
||||
patch_le16(loader,e_len,"JM",ph.u_len+overlapoh+2-jmp_pos-2);
|
||||
patch_le16(loader,e_len,"JM",ph.u_len+ph.overlap_overhead+2-jmp_pos-2);
|
||||
loader[getLoaderSection("SYSSUBSI") - 1] = (upx_byte) -e_len;
|
||||
patch_le16(loader,e_len,"DI",copy_to);
|
||||
patch_le16(loader,e_len,"SI",ph.c_len+e_len+d_len-1);
|
||||
|
||||
@ -50,7 +50,7 @@ protected:
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned, unsigned);
|
||||
virtual void patchLoader(OutputFile *fo, upx_byte *, int, unsigned);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@ -65,6 +65,17 @@ const int *PackTmt::getFilters() const
|
||||
}
|
||||
|
||||
|
||||
unsigned PackTmt::findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range,
|
||||
unsigned upper_limit) const
|
||||
{
|
||||
// make sure the decompressor will be paragraph aligned
|
||||
unsigned o = super::findOverlapOverhead(buf, range, upper_limit);
|
||||
o = ((o + 0x20) &~ 0xf) - (ph.u_len & 0xf);
|
||||
return o;
|
||||
}
|
||||
|
||||
|
||||
int PackTmt::buildLoader(const Filter *ft)
|
||||
{
|
||||
// prepare loader
|
||||
@ -95,7 +106,7 @@ int PackTmt::buildLoader(const Filter *ft)
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
bool PackTmt::readFileHeader()
|
||||
int PackTmt::readFileHeader()
|
||||
{
|
||||
#define H(x) get_le16(h,2*(x))
|
||||
#define H4(x) get_le32(h,x)
|
||||
@ -143,14 +154,16 @@ bool PackTmt::readFileHeader()
|
||||
else if (memcmp(h,"Adam",4) == 0)
|
||||
break;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (ic == 20)
|
||||
return false;
|
||||
return 0;
|
||||
|
||||
fi->seek(adam_offset,SEEK_SET);
|
||||
fi->readx(&ih,sizeof(ih));
|
||||
// FIXME: should add some checks for the values in `ih'
|
||||
|
||||
return true;
|
||||
return UPX_F_TMT_ADAM;
|
||||
#undef H4
|
||||
#undef H
|
||||
}
|
||||
@ -218,9 +231,9 @@ void PackTmt::pack(OutputFile *fo)
|
||||
ph.u_len = usize + relocsize;
|
||||
if (!compress(ibuf,obuf))
|
||||
throwNotCompressible();
|
||||
buildLoader(&ft);
|
||||
|
||||
unsigned overlapoh = findOverlapOverhead(obuf,512);
|
||||
ph.overlap_overhead = findOverlapOverhead(obuf,512);
|
||||
buildLoader(&ft);
|
||||
|
||||
// verify filter
|
||||
ft.verifyUnfilter();
|
||||
@ -233,9 +246,6 @@ void PackTmt::pack(OutputFile *fo)
|
||||
// prepare filter
|
||||
Filter ft(opt->level);
|
||||
ft.buf_len = usize;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 512;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
@ -244,12 +254,9 @@ void PackTmt::pack(OutputFile *fo)
|
||||
else if (opt->all_filters)
|
||||
// choose best from all available filters
|
||||
strategy = 0;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
||||
compressWithFilters(&ft, 512, strategy);
|
||||
#endif
|
||||
|
||||
// make sure the decompressor will be paragraph aligned
|
||||
overlapoh = ((overlapoh + 0x20) &~ 0xf) - (ph.u_len & 0xf);
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
memcpy(loader,getLoader(),lsize);
|
||||
@ -260,18 +267,18 @@ void PackTmt::pack(OutputFile *fo)
|
||||
assert(e_len > 0 && s_point > 0);
|
||||
|
||||
// patch loader
|
||||
patch_le32(loader,lsize,"JMPO",ih.entry-(ph.u_len+overlapoh+d_len));
|
||||
patch_le32(loader,lsize,"JMPO",ih.entry-(ph.u_len+ph.overlap_overhead+d_len));
|
||||
patchFilter32(loader, lsize, &ft);
|
||||
patchPackHeader(loader,e_len);
|
||||
|
||||
const unsigned jmp_pos = find_le32(loader,e_len,get_le32("JMPD"));
|
||||
patch_le32(loader,e_len,"JMPD",ph.u_len+overlapoh-jmp_pos-4);
|
||||
patch_le32(loader,e_len,"JMPD",ph.u_len+ph.overlap_overhead-jmp_pos-4);
|
||||
|
||||
patch_le32(loader,e_len,"ECX0",ph.c_len+d_len);
|
||||
patch_le32(loader,e_len,"EDI0",ph.u_len+overlapoh+d_len-1);
|
||||
patch_le32(loader,e_len,"EDI0",ph.u_len+ph.overlap_overhead+d_len-1);
|
||||
patch_le32(loader,e_len,"ESI0",ph.c_len+e_len+d_len-1);
|
||||
//fprintf(stderr,"\nelen=%x dlen=%x copy_len=%x copy_to=%x oo=%x jmp_pos=%x ulen=%x clen=%x \n\n",
|
||||
// e_len,d_len,copy_len,copy_to,overlapoh,jmp_pos,ph.u_len,ph.c_len);
|
||||
// e_len,d_len,copy_len,copy_to,ph.overlap_overhead,jmp_pos,ph.u_len,ph.c_len);
|
||||
|
||||
memcpy(&oh,&ih,sizeof(oh));
|
||||
oh.imagesize = ph.c_len+e_len+d_len; // new size
|
||||
@ -288,7 +295,7 @@ void PackTmt::pack(OutputFile *fo)
|
||||
fo->write(rel_entry,sizeof (rel_entry));
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
|
||||
@ -52,8 +52,12 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual int readFileHeader();
|
||||
|
||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const;
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual bool readFileHeader();
|
||||
|
||||
unsigned adam_offset;
|
||||
int big_relocs;
|
||||
|
||||
@ -132,15 +132,15 @@ int PackTos::getLoaderSize() const
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
bool PackTos::readFileHeader()
|
||||
int PackTos::readFileHeader()
|
||||
{
|
||||
fi->seek(0,SEEK_SET);
|
||||
fi->readx(&ih, FH_SIZE);
|
||||
if (ih.fh_magic != 0x601a)
|
||||
return false;
|
||||
return 0;
|
||||
if (FH_SIZE + ih.fh_text + ih.fh_data + ih.fh_sym > (unsigned) file_size)
|
||||
return false;
|
||||
return true;
|
||||
return 0;
|
||||
return UPX_F_ATARI_TOS;
|
||||
}
|
||||
|
||||
|
||||
@ -412,8 +412,8 @@ void PackTos::pack(OutputFile *fo)
|
||||
throwNotCompressible();
|
||||
|
||||
// The decompressed data will now get placed at this offset:
|
||||
const unsigned overlapoh = findOverlapOverhead(obuf, 512);
|
||||
unsigned offset = (ph.u_len + overlapoh) - ph.c_len;
|
||||
ph.overlap_overhead = findOverlapOverhead(obuf, 512);
|
||||
unsigned offset = (ph.u_len + ph.overlap_overhead) - ph.c_len;
|
||||
|
||||
// compute addresses
|
||||
unsigned o_text, o_data, o_bss;
|
||||
@ -538,7 +538,7 @@ void PackTos::pack(OutputFile *fo)
|
||||
fo->write("\x00\x00\x00\x00",4);
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
|
||||
|
||||
// copy the overlay
|
||||
copyOverlay(fo, overlay, &obuf);
|
||||
|
||||
@ -57,7 +57,7 @@ protected:
|
||||
virtual const upx_byte *getLoader() const;
|
||||
virtual int getLoaderSize() const;
|
||||
|
||||
virtual bool readFileHeader();
|
||||
virtual int readFileHeader();
|
||||
virtual bool checkFileHeader();
|
||||
|
||||
struct tos_header_t
|
||||
|
||||
@ -220,9 +220,6 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
||||
Filter ft(opt->level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = kernel_entry;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 1 << 20;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
@ -231,7 +228,7 @@ void PackVmlinuzI386::pack(OutputFile *fo)
|
||||
else if (opt->all_filters)
|
||||
// choose best from all available filters
|
||||
strategy = 0;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
||||
compressWithFilters(&ft, 1 << 20, strategy);
|
||||
|
||||
const unsigned lsize = getLoaderSize();
|
||||
MemBuffer loader(lsize);
|
||||
@ -297,9 +294,6 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
Filter ft(opt->level);
|
||||
ft.buf_len = ph.u_len;
|
||||
ft.addvalue = kernel_entry;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 512;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (opt->filter >= 0 && isValidFilter(opt->filter))
|
||||
@ -308,7 +302,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
else if (opt->all_filters)
|
||||
// choose best from all available filters
|
||||
strategy = 0;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy);
|
||||
compressWithFilters(&ft, 512, strategy);
|
||||
|
||||
// align everything to dword boundary - it is easier to handle
|
||||
unsigned clen = ph.c_len;
|
||||
@ -326,7 +320,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
assert(e_len > 0);
|
||||
|
||||
const unsigned d_len4 = ALIGN_UP(lsize - e_len, 4);
|
||||
const unsigned decompr_pos = ALIGN_UP(ph.u_len + overlapoh, 16);
|
||||
const unsigned decompr_pos = ALIGN_UP(ph.u_len + ph.overlap_overhead, 16);
|
||||
const unsigned copy_size = clen + d_len4;
|
||||
const unsigned edi = decompr_pos + d_len4 - 4; // copy to
|
||||
const unsigned esi = ALIGN_UP(clen + lsize, 4) - 4; // copy from
|
||||
@ -357,7 +351,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo)
|
||||
#endif
|
||||
|
||||
// verify
|
||||
verifyOverlappingDecompression(&obuf, overlapoh);
|
||||
verifyOverlappingDecompression(&obuf, ph.overlap_overhead);
|
||||
|
||||
// finally check the compression ratio
|
||||
if (!checkFinalCompressionRatio(fo))
|
||||
|
||||
@ -78,11 +78,12 @@ int PackW16Ne::buildLoader(const Filter *ft)
|
||||
//
|
||||
**************************************************************************/
|
||||
|
||||
bool PackW16Ne::readFileHeader()
|
||||
int PackW16Ne::readFileHeader()
|
||||
{
|
||||
// FIXME: identify a win16/ne executable, so that the call
|
||||
// for contribution below will get thrown
|
||||
return false;
|
||||
return 0;
|
||||
//return UPX_F_WIN16_NE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@ -52,7 +52,8 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual bool readFileHeader(void);
|
||||
virtual int readFileHeader(void);
|
||||
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
};
|
||||
|
||||
|
||||
@ -130,7 +130,7 @@ bool PackW32Pe::testUnpackVersion(int version) const
|
||||
// util
|
||||
**************************************************************************/
|
||||
|
||||
bool PackW32Pe::readFileHeader()
|
||||
int PackW32Pe::readFileHeader()
|
||||
{
|
||||
struct h_t
|
||||
{
|
||||
@ -161,16 +161,16 @@ bool PackW32Pe::readFileHeader()
|
||||
else if (get_le32(&h) == 'P' + 'E'*256)
|
||||
break;
|
||||
else
|
||||
return false;
|
||||
return 0;
|
||||
}
|
||||
if (ic == 20)
|
||||
return false;
|
||||
return 0;
|
||||
fi->seek(pe_offset,SEEK_SET);
|
||||
fi->readx(&ih,sizeof(ih));
|
||||
fi->seek(0x200,SEEK_SET);
|
||||
fi->readx(&h,6);
|
||||
isrtm = memcmp(&h,"32STUB",6) == 0;
|
||||
return true;
|
||||
return UPX_F_WIN32_PE;
|
||||
}
|
||||
|
||||
|
||||
@ -1625,9 +1625,9 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
ph.filter_cto = ft.cto;
|
||||
if (!compress(ibuf + rvamin,obuf))
|
||||
throwNotCompressible();
|
||||
buildLoader(&ft);
|
||||
|
||||
const unsigned overlapoh = findOverlapOverhead(obuf, 2048);
|
||||
ph.overlap_overhead = findOverlapOverhead(obuf, 2048);
|
||||
buildLoader(&ft);
|
||||
|
||||
// verify filter
|
||||
ft.verifyUnfilter();
|
||||
@ -1640,9 +1640,6 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
Filter ft(opt->level);
|
||||
ft.buf_len = ih.codesize;
|
||||
ft.addvalue = 0;
|
||||
// prepare other settings
|
||||
const unsigned overlap_range = 2048;
|
||||
unsigned overlapoh;
|
||||
|
||||
int strategy = -1; // try the first working filter
|
||||
if (!allow_filter)
|
||||
@ -1654,11 +1651,11 @@ void PackW32Pe::pack(OutputFile *fo)
|
||||
else if (opt->all_filters)
|
||||
// choose best from all available filters
|
||||
strategy = 0;
|
||||
compressWithFilters(&ft, &overlapoh, overlap_range, strategy,
|
||||
compressWithFilters(&ft, 2048, strategy,
|
||||
NULL, 0, 0, ih.codebase, rvamin);
|
||||
#endif
|
||||
|
||||
newvsize = (ph.u_len + rvamin + overlapoh + oam1) &~ oam1;
|
||||
newvsize = (ph.u_len + rvamin + ph.overlap_overhead + oam1) &~ oam1;
|
||||
if (tlsindex && ((newvsize - ph.c_len - 1024 + oam1) &~ oam1) > tlsindex + 4)
|
||||
tlsindex = 0;
|
||||
|
||||
|
||||
@ -64,8 +64,9 @@ public:
|
||||
{ return (version == 12); }
|
||||
|
||||
protected:
|
||||
virtual bool readFileHeader();
|
||||
virtual int readFileHeader();
|
||||
virtual bool testUnpackVersion(int version) const;
|
||||
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
|
||||
unsigned pe_offset;
|
||||
|
||||
@ -208,7 +208,7 @@ void PackWcle::encodeObjectTable()
|
||||
if (ic < jc)
|
||||
ic = jc;
|
||||
|
||||
unsigned csection = (ic + overlapoh + mps-1) &~ (mps-1);
|
||||
unsigned csection = (ic + ph.overlap_overhead + mps-1) &~ (mps-1);
|
||||
|
||||
OOT(0,virtual_size) = csection + mps;
|
||||
OOT(0,flags) = LEOF_READ|LEOF_EXEC|LEOF_HUGE32|LEOF_PRELOAD;
|
||||
@ -421,9 +421,9 @@ void PackWcle::encodeImage(const Filter *ft)
|
||||
// reserve RESERVED bytes for the decompressor
|
||||
if (!compress(ibuf,oimage+RESERVED))
|
||||
throwNotCompressible();
|
||||
ph.overlap_overhead = findOverlapOverhead(oimage+RESERVED, 512);
|
||||
buildLoader(ft);
|
||||
|
||||
overlapoh = findOverlapOverhead(oimage+RESERVED, 512);
|
||||
ibuf.free();
|
||||
soimage = (ph.c_len + 3) &~ 3;
|
||||
}
|
||||
@ -516,7 +516,7 @@ void PackWcle::pack(OutputFile *fo)
|
||||
|
||||
// patch loader
|
||||
ic = (OOT(0,virtual_size) - d_len) &~ 15;
|
||||
assert(ic > ((ph.u_len + overlapoh + 31) &~ 15));
|
||||
assert(ic > ((ph.u_len + ph.overlap_overhead + 31) &~ 15));
|
||||
|
||||
upx_byte * const p = oimage + soimage - d_len;
|
||||
patch_le32(p,d_len,"JMPO",ih.init_eip_offset+text_vaddr-(ic+d_len));
|
||||
|
||||
@ -52,9 +52,10 @@ public:
|
||||
virtual int canUnpack();
|
||||
|
||||
protected:
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
virtual void handleStub(OutputFile *fo);
|
||||
|
||||
virtual int buildLoader(const Filter *ft);
|
||||
|
||||
virtual void readObjectTable();
|
||||
virtual void encodeObjectTable();
|
||||
virtual void decodeObjectTable();
|
||||
@ -81,7 +82,6 @@ protected:
|
||||
|
||||
int big_relocs;
|
||||
bool has_extra_code;
|
||||
unsigned overlapoh;
|
||||
unsigned neweip;
|
||||
};
|
||||
|
||||
|
||||
@ -1088,7 +1088,7 @@ void Packer::addFilter32(int filter_id)
|
||||
// It will replace the tryFilters() / compress() call sequence.
|
||||
**************************************************************************/
|
||||
|
||||
void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
||||
void Packer::compressWithFilters(Filter *parm_ft,
|
||||
const unsigned overlap_range,
|
||||
int strategy, const int *parm_filters,
|
||||
unsigned max_offset, unsigned max_match,
|
||||
@ -1106,8 +1106,8 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
||||
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;
|
||||
unsigned best_ph_lsize = 0;
|
||||
unsigned best_overlapoh = 0;
|
||||
|
||||
// preconditions
|
||||
assert(orig_ph.filter == 0);
|
||||
@ -1209,14 +1209,27 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
||||
// compress
|
||||
if (compress(ibuf + compress_buf_off, otemp, max_offset, max_match))
|
||||
{
|
||||
// get results
|
||||
const unsigned lsize = buildLoader(&ft);
|
||||
unsigned lsize = 0;
|
||||
if (ph.c_len + lsize < best_ph.c_len + best_ph_lsize)
|
||||
{
|
||||
// get results
|
||||
ph.overlap_overhead = findOverlapOverhead(otemp, overlap_range);
|
||||
lsize = buildLoader(&ft);
|
||||
}
|
||||
#if 0
|
||||
printf("\n%02x: %d + %d = %d (best: %d + %d = %d)\n", ft.id,
|
||||
ph.c_len, getLoaderSize(), ph.c_len + getLoaderSize(),
|
||||
best_ph.c_len, best_ph_lsize, best_ph.c_len + best_ph_lsize);
|
||||
#endif
|
||||
bool update = false;
|
||||
if (ph.c_len + lsize < best_ph.c_len + best_ph_lsize)
|
||||
update = true;
|
||||
else if (ph.c_len + lsize == best_ph.c_len + best_ph_lsize)
|
||||
{
|
||||
if (ph.overlap_overhead < best_ph.overlap_overhead)
|
||||
update = true;
|
||||
}
|
||||
if (update)
|
||||
{
|
||||
// update obuf[] with best version
|
||||
if (otemp != obuf)
|
||||
@ -1225,7 +1238,6 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
||||
best_ph = ph;
|
||||
best_ph_lsize = lsize;
|
||||
best_ft = ft;
|
||||
best_overlapoh = findOverlapOverhead(obuf, overlap_range);
|
||||
}
|
||||
}
|
||||
// restore ibuf[] - unfilter with verify
|
||||
@ -1240,11 +1252,11 @@ void Packer::compressWithFilters(Filter *parm_ft, unsigned *parm_overlapoh,
|
||||
assert(best_ph.u_len == orig_ph.u_len);
|
||||
assert(best_ph.filter == best_ft.id);
|
||||
assert(best_ph.filter_cto == best_ft.cto);
|
||||
assert(best_ph.overlap_overhead > 0);
|
||||
|
||||
// copy back results
|
||||
this->ph = best_ph;
|
||||
*parm_ft = best_ft;
|
||||
*parm_overlapoh = best_overlapoh;
|
||||
|
||||
// finally check compression ratio
|
||||
if (best_ph.c_len + best_ph_lsize >= best_ph.u_len)
|
||||
|
||||
22
src/packer.h
22
src/packer.h
@ -87,6 +87,9 @@ public:
|
||||
unsigned max_run_found;
|
||||
unsigned first_offset_found;
|
||||
//unsigned same_match_offsets_found;
|
||||
|
||||
// info fields set by Packer::compressWithFilters()
|
||||
unsigned overlap_overhead;
|
||||
};
|
||||
|
||||
|
||||
@ -158,24 +161,25 @@ protected:
|
||||
virtual bool checkFinalCompressionRatio(const OutputFile *fo) const;
|
||||
|
||||
// high-level compression drivers
|
||||
void compressWithFilters(Filter *ft, unsigned *overlapoh,
|
||||
void compressWithFilters(Filter *ft,
|
||||
const unsigned overlap_range,
|
||||
int strategy = -1, const int *filters = NULL,
|
||||
int strategy,
|
||||
const int *filters = NULL,
|
||||
unsigned max_offset = 0, unsigned max_match = 0,
|
||||
unsigned filter_buf_off = 0,
|
||||
unsigned compress_buf_off = 0);
|
||||
|
||||
// util for verifying overlapping decompresion
|
||||
// non-destructive test
|
||||
bool testOverlappingDecompression(const upx_bytep buf,
|
||||
unsigned overlap_overhead) const;
|
||||
virtual bool testOverlappingDecompression(const upx_bytep buf,
|
||||
unsigned overlap_overhead) const;
|
||||
// non-destructive find
|
||||
unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const;
|
||||
virtual unsigned findOverlapOverhead(const upx_bytep buf,
|
||||
unsigned range = 0,
|
||||
unsigned upper_limit = ~0u) const;
|
||||
// destructive decompress + verify
|
||||
void verifyOverlappingDecompression(MemBuffer *buf,
|
||||
unsigned overlap_overhead);
|
||||
virtual void verifyOverlappingDecompression(MemBuffer *buf,
|
||||
unsigned overlap_overhead);
|
||||
|
||||
|
||||
// packheader handling
|
||||
|
||||
@ -38,7 +38,7 @@
|
||||
**************************************************************************/
|
||||
|
||||
PackHeader::PackHeader() :
|
||||
version(-1), format(-1)
|
||||
version(-1), format(-1), filter(0), filter_cto(0), overlap_overhead(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user