From a8177201efb9c52c2e6327babb65dffa81e55576 Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Sat, 30 Dec 2000 15:35:33 +0000 Subject: [PATCH] Added new field PackHeader::overlap_overhead. committer: mfx 978190533 +0000 --- src/p_com.cpp | 14 ++++++-------- src/p_com.h | 2 +- src/p_djgpp2.cpp | 47 ++++++++++++++++++++++++++--------------------- src/p_djgpp2.h | 8 ++++++-- src/p_elks.cpp | 5 +---- src/p_sys.cpp | 8 ++++---- src/p_sys.h | 2 +- src/p_tmt.cpp | 43 +++++++++++++++++++++++++------------------ src/p_tmt.h | 6 +++++- src/p_tos.cpp | 14 +++++++------- src/p_tos.h | 2 +- src/p_vmlinz.cpp | 14 ++++---------- src/p_w16ne.cpp | 5 +++-- src/p_w16ne.h | 3 ++- src/p_w32pe.cpp | 19 ++++++++----------- src/p_w32pe.h | 3 ++- src/p_wcle.cpp | 6 +++--- src/p_wcle.h | 4 ++-- src/packer.cpp | 24 ++++++++++++++++++------ src/packer.h | 22 +++++++++++++--------- src/packhead.cpp | 2 +- 21 files changed, 139 insertions(+), 114 deletions(-) diff --git a/src/p_com.cpp b/src/p_com.cpp index 18e41aa3..9c24104b 100644 --- a/src/p_com.cpp +++ b/src/p_com.cpp @@ -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)) diff --git a/src/p_com.h b/src/p_com.h index f43b4caa..10ffbeca 100644 --- a/src/p_com.h +++ b/src/p_com.h @@ -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); }; diff --git a/src/p_djgpp2.cpp b/src/p_djgpp2.cpp index 1896b7ae..bc468fda 100644 --- a/src/p_djgpp2.cpp +++ b/src/p_djgpp2.cpp @@ -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 diff --git a/src/p_djgpp2.h b/src/p_djgpp2.h index 4c8d77fa..227716c7 100644 --- a/src/p_djgpp2.h +++ b/src/p_djgpp2.h @@ -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; diff --git a/src/p_elks.cpp b/src/p_elks.cpp index 88c39969..25657170 100644 --- a/src/p_elks.cpp +++ b/src/p_elks.cpp @@ -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); diff --git a/src/p_sys.cpp b/src/p_sys.cpp index 77308432..b7b4d483 100644 --- a/src/p_sys.cpp +++ b/src/p_sys.cpp @@ -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); diff --git a/src/p_sys.h b/src/p_sys.h index bc4a192a..69607321 100644 --- a/src/p_sys.h +++ b/src/p_sys.h @@ -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); }; diff --git a/src/p_tmt.cpp b/src/p_tmt.cpp index 175410d3..a0f10fbf 100644 --- a/src/p_tmt.cpp +++ b/src/p_tmt.cpp @@ -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); diff --git a/src/p_tmt.h b/src/p_tmt.h index 05d4c87e..86edda7b 100644 --- a/src/p_tmt.h +++ b/src/p_tmt.h @@ -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; diff --git a/src/p_tos.cpp b/src/p_tos.cpp index 781e826b..262e3033 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -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); diff --git a/src/p_tos.h b/src/p_tos.h index df7b3c05..803c307c 100644 --- a/src/p_tos.h +++ b/src/p_tos.h @@ -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 diff --git a/src/p_vmlinz.cpp b/src/p_vmlinz.cpp index cde74a76..9b0dfdf5 100644 --- a/src/p_vmlinz.cpp +++ b/src/p_vmlinz.cpp @@ -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)) diff --git a/src/p_w16ne.cpp b/src/p_w16ne.cpp index 80d3d703..84222a2b 100644 --- a/src/p_w16ne.cpp +++ b/src/p_w16ne.cpp @@ -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; } diff --git a/src/p_w16ne.h b/src/p_w16ne.h index 44ee8a4e..7222d8e0 100644 --- a/src/p_w16ne.h +++ b/src/p_w16ne.h @@ -52,7 +52,8 @@ public: virtual int canUnpack(); protected: - virtual bool readFileHeader(void); + virtual int readFileHeader(void); + virtual int buildLoader(const Filter *ft); }; diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index 640b1ce5..1ba284f1 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -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; diff --git a/src/p_w32pe.h b/src/p_w32pe.h index c08fbbdd..48dd7d56 100644 --- a/src/p_w32pe.h +++ b/src/p_w32pe.h @@ -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; diff --git a/src/p_wcle.cpp b/src/p_wcle.cpp index 19f41cba..110a06a6 100644 --- a/src/p_wcle.cpp +++ b/src/p_wcle.cpp @@ -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)); diff --git a/src/p_wcle.h b/src/p_wcle.h index 3ee53b3a..8e7b96df 100644 --- a/src/p_wcle.h +++ b/src/p_wcle.h @@ -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; }; diff --git a/src/packer.cpp b/src/packer.cpp index 6a09e9b1..a67484e0 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -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) diff --git a/src/packer.h b/src/packer.h index 177de0a4..9604f333 100644 --- a/src/packer.h +++ b/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 diff --git a/src/packhead.cpp b/src/packhead.cpp index 10ea8ce3..d4bddd5c 100644 --- a/src/packhead.cpp +++ b/src/packhead.cpp @@ -38,7 +38,7 @@ **************************************************************************/ PackHeader::PackHeader() : - version(-1), format(-1) + version(-1), format(-1), filter(0), filter_cto(0), overlap_overhead(0) { }