Added new field PackHeader::overlap_overhead.

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