diff --git a/.cvsignore b/.cvsignore index 7e8cb999..0b65399d 100644 --- a/.cvsignore +++ b/.cvsignore @@ -1,4 +1,5 @@ .cvsignore .mfxcvsup ChangeLog.cvs* +build maint diff --git a/NEWS b/NEWS index 00b68490..0ae60ccd 100644 --- a/NEWS +++ b/NEWS @@ -2,13 +2,19 @@ User visible changes for UPX ================================================================== -Changes in 1.09.4 beta (13 Nov 2000): - * BETA VERSION - DO NOT USE EXCEPT FOR TESTING!!! REALLY. - * linux/i386: added the new direct-to-memory executable formats - no - more temp files are needed for decompression +Changes in 1.10 beta (20 Dec 2000): + * UNSTABLE BETA VERSION - DO NOT USE EXCEPT FOR TESTING!!! REALLY. + * vmlinuz/386: new format - UPX now supports bootable linux kernels + * linux/386: added the new direct-to-memory executable formats - no + more temp files are needed for decompression! * reduced overall memory requirements during packing * quite a number of internal source code rearrangements +Changes in 1.04 (19 Dec 2000) + * dos/exe: fixed an internal error when using `--no-reloc' + * win32/pe: fixed a rare bug in the relocation handling code + * some tunings for the default compression level + Changes in 1.03 (30 Nov 2000) * linked with a new version of the NRV compression library: - improved compression ratio a little bit @@ -51,7 +57,7 @@ Changes in 0.99 (25 Feb 2000) * FULL SOURCE CODE RELEASED UNDER THE TERMS OF THE GNU GPL * win32/pe: changed default to `--strip-relocs=1' * dos/com and dos/sys: fixed a bad decompressor problem - * linux/i386: the counter for the progress indicator was off by one + * linux/386: the counter for the progress indicator was off by one Changes in 0.94 (06 Dec 1999) * win32/pe: the stub now calls ExitProcess in case of import errors @@ -61,7 +67,7 @@ Changes in 0.94 (06 Dec 1999) Changes in 0.93 (22 Nov 1999) * win32/pe: fixed --strip-relocs problem with uncompression * win32/pe: fixed a bug which could produce a broken decompressor stub - * linux/i386: yet another FreeBSD compatibility fix + * linux/386: yet another FreeBSD compatibility fix Changes in 0.92 (14 Nov 1999) * win32/pe: really fixed that one line (see below) @@ -80,8 +86,8 @@ Changes in 0.90 (10 Nov 1999) * win32/pe: resource handling is rewritten * win32/pe: the last :-) TLS problem is fixed * win32/pe: somewhat less memory is required during compression - * linux/i386: fixed compression of scripts which was broken since 0.71 - * linux/i386: more FreeBSD compatibility issues + * linux/386: fixed compression of scripts which was broken since 0.71 + * linux/386: more FreeBSD compatibility issues * changed option: `-i' now prints some more details during compression (not finished yet) @@ -92,12 +98,12 @@ Changes in 0.84 (04 Oct 1999) Changes in 0.83 (17 Sep 1999) * dos/exe: fixed minimal memory requirement problem for some files * win32/pe: fixed a bug which caused a crash in some compressed files - * linux/i386: various improvements in the stub; also, for the sake + * linux/386: various improvements in the stub; also, for the sake of FreeBSD users, the stub is now branded as Linux/ELF Changes in 0.82 (16 Aug 1999) * dos/exe: fixed a decompressor bug which could cause crash on some files - * linux/i386: section headers are now stripped from the stub so that + * linux/386: section headers are now stripped from the stub so that `strip' won't ruin a compressed file any longer * wc/le: support for stack not in the last object disabled again * win32/pe: removed some unneeded data @@ -143,11 +149,11 @@ Changes in 0.72 (12 May 1999) * win32/pe: never compress TYPELIB resources * win32/pe: compressed files are hopefully less suspicious to heuristic virus scanners now - * linux/i386: minor decompressor stub updates, nicer progress bar + * linux/386: minor decompressor stub updates, nicer progress bar Changes in 0.71 (19 Apr 1999) * dos/exe: added option `--no-overlay' - * linux/i386: various improvements in the stub, most notably the + * linux/386: various improvements in the stub, most notably the overhead for an extra cleanup process has been removed * win32/pe: added support for export forwarders * win32/pe: added support for DLLs without entry point or imports @@ -157,7 +163,7 @@ Changes in 0.71 (19 Apr 1999) * win32/pe: rearranged stub to avoid false alerts from some virus scanners Changes in 0.70 (30 Mar 1999) - * added support for linux/i386 executables + * added support for linux/386 executables * improved compression ratio quite a bit * added new compression level `--best' to squeeze out even some more bytes * win32/pe: TLS support is much better now diff --git a/doc/upx.pod b/doc/upx.pod index 2877c405..40e06b9b 100644 --- a/doc/upx.pod +++ b/doc/upx.pod @@ -146,7 +146,8 @@ B<--stdout>: writes all output to stdout =head1 COMPRESSION LEVELS & TUNING B offers ten different compression levels from B<-1> to B<-9>, -and B<--best>. The default compression level is B<-7>. +and B<--best>. The default compression level is B<-8> for files +smaller than 512 kB, and B<-7> otherwise. =over 4 @@ -479,6 +480,8 @@ and does not use /proc. Linux/elf386 is automatically selected for Linux ELF exectuables. +Packed programs will be byte-identical to the original after uncompression. + How it works: For ELF executables, UPX decompresses directly to memory, simulating @@ -525,6 +528,8 @@ It does not use space in /tmp, and does not use /proc. Linux/sh386 is automatically selected for shell scripts that use a known shell. +Packed programs will be byte-identical to the original after uncompression. + How it works: For shell script executables (files beginning with "#!/" or "#! /") @@ -567,6 +572,8 @@ and needs /proc filesystem support. Linux/386 is only selected if the specialized linux/elf386 and linux/sh386 won't recognize a file. +Packed programs will be byte-identical to the original after uncompression. + How it works: For files which are not ELF and not a script for a known "-c" shell, diff --git a/src/Makefile b/src/Makefile index d2eea5b3..47c95b59 100644 --- a/src/Makefile +++ b/src/Makefile @@ -85,7 +85,7 @@ INCLUDES = -I$(srcdir) CFLAGS_OUTPUT = -o $@ CXXFLAGS_OUTPUT = $(CFLAGS_OUTPUT) -LINK_EXE = $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) +LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS) STUBEDIT_EXE = o = .o @@ -257,7 +257,7 @@ else endif ##LINK_LDFLAGS += /verbose -LINK_EXE = $(CC) $(LDFLAGS) -Fe$@ $^ $(LDLIBS) $(LINK_LDFLAGS) +LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -Fe$@ $^ $(LDLIBS) $(LINK_LDFLAGS) endif # vc6 @@ -284,10 +284,10 @@ endif ifeq (1,2) # purify DEFS += -D__PURIFY__ LDFLAGS = -g -L/home/ethmola/local/lib - LINK_EXE = purify $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + LINK_EXE = purify $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS) else LDFLAGS += -g -L/home/ethmola/local/lib - LINK_EXE = $(CC) $(LDFLAGS) -o $@ $^ $(LDLIBS) + LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -o $@ $^ $(LDLIBS) endif endif # sparc @@ -320,7 +320,7 @@ else CFLAGS += -O2 -d endif -LINK_EXE = $(CC) $(LDFLAGS) -e$@ $^ $(LDLIBS) +LINK_EXE = $(CC) $(LDFLAGS) $(EXTRA_LDFLAGS) -e$@ $^ $(LDLIBS) endif # bcc diff --git a/src/main.cpp b/src/main.cpp index 9ed2d391..1c5858e6 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -42,17 +42,18 @@ void init_options(struct options_t *o) o->cmd = CMD_NONE; o->method = -1; - o->level = 7; + o->level = -1; o->mem_level = -1; o->filter = -1; o->backup = -1; o->overlay = -1; + o->console = CON_FILE; #if defined(__MFX_DOS) || defined(__MFX_WIN) o->console = CON_INIT; -#else - o->console = CON_FILE; +#elif 1 && defined(__linux__) + o->console = CON_INIT; #endif o->verbose = 2; diff --git a/src/p_lx_elf.cpp b/src/p_lx_elf.cpp index 88685443..98aeeba3 100644 --- a/src/p_lx_elf.cpp +++ b/src/p_lx_elf.cpp @@ -113,6 +113,7 @@ void PackLinuxI386elf::updateLoader(OutputFile *fo) #undef PAGE_MASK } + void PackLinuxI386elf::patchLoader() { lsize = getLoaderSize(); @@ -170,6 +171,8 @@ bool PackLinuxI386elf::canPack() { unsigned char buf[512]; + // FIXME: add special checks for uncompresed "vmlinux" kernel + fi->readx(buf,512); fi->seek(0,0); if (0==memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) { // ELF 32-bit LSB @@ -188,6 +191,7 @@ bool PackLinuxI386elf::canPack() break; } } + exetype = 1; return super::canPack(); } return false; @@ -406,11 +410,6 @@ void PackLinuxI386elf::unpackExtent(unsigned wanted, OutputFile *fo, } -bool PackLinuxI386elf::canUnpackFormat(int format) const -{ - return UPX_F_LINUX_ELF_i386==format || UPX_F_LINUX_SEP_i386==format; -} - void PackLinuxI386elf::unpack(OutputFile *fo) { #define MAX_ELF_HDR 512 diff --git a/src/p_lx_elf.h b/src/p_lx_elf.h index 82588d9b..0662796b 100644 --- a/src/p_lx_elf.h +++ b/src/p_lx_elf.h @@ -33,8 +33,10 @@ #ifndef __UPX_P_LX_ELF_H //{ #define __UPX_P_LX_ELF_H -#include "p_unix.h" -#include "p_elf.h" + +/************************************************************************* +// linux/elf386 +**************************************************************************/ class PackLinuxI386elf : public PackLinuxI386 { @@ -51,10 +53,10 @@ public: virtual void unpack(OutputFile *fo); virtual bool canPack(); - virtual bool canUnpackFormat(int format) const; virtual bool canUnpackVersion(int version) const { return (version >= 11); } +protected: struct Extent { off_t offset; off_t size; @@ -76,7 +78,8 @@ protected: Elf_LE32_Phdr *phdri; // for input file }; -#endif //}__UPX_P_LX_ELF_H + +#endif /*} already included */ /* diff --git a/src/p_lx_sep.cpp b/src/p_lx_sep.cpp index 12de38ba..37be0f9e 100644 --- a/src/p_lx_sep.cpp +++ b/src/p_lx_sep.cpp @@ -34,6 +34,9 @@ #include "file.h" #include "packer.h" +#include "p_elf.h" +#include "p_unix.h" +#include "p_lx_elf.h" #include "p_lx_sep.h" diff --git a/src/p_lx_sep.h b/src/p_lx_sep.h index b007060a..6b396614 100644 --- a/src/p_lx_sep.h +++ b/src/p_lx_sep.h @@ -26,10 +26,14 @@ jreiser@BitWagon.com */ + #ifndef __UPX_P_LX_SEP_H //{ #define __UPX_P_LX_SEP_H -#include "p_lx_elf.h" + +/************************************************************************* +// linux/sep386 +**************************************************************************/ class PackLinuxI386sep : public PackLinuxI386elf { @@ -49,7 +53,7 @@ protected: }; -#endif //}__UPX_P_LX_SEP_H +#endif /*} already included */ /* vi:ts=4:et diff --git a/src/p_lx_sh.cpp b/src/p_lx_sh.cpp index 76a4ad3c..d35ca115 100644 --- a/src/p_lx_sh.cpp +++ b/src/p_lx_sh.cpp @@ -167,12 +167,6 @@ bool PackLinuxI386sh::getShellName(char *buf) } -bool PackLinuxI386sh::canUnpackFormat(int format) const -{ - return UPX_F_LINUX_SH_i386==format; -} - - bool PackLinuxI386sh::canPack() { #if defined(__linux__) //{ diff --git a/src/p_lx_sh.h b/src/p_lx_sh.h index c73346b2..bb363a39 100644 --- a/src/p_lx_sh.h +++ b/src/p_lx_sh.h @@ -33,6 +33,11 @@ #ifndef __UPX_P_LX_SH_H //{ #define __UPX_P_LX_SH_H + +/************************************************************************* +// linux/sh386 +**************************************************************************/ + class PackLinuxI386sh : public PackLinuxI386 { typedef PackLinuxI386 super; @@ -47,8 +52,6 @@ public: virtual bool canPack(); virtual void pack(OutputFile *fo); // virtual void unpack(OutputFile *fo) { super::unpack(fo); } - - virtual bool canUnpackFormat(int format) const; virtual bool canUnpackVersion(int version) const { return (version >= 11); } @@ -65,7 +68,8 @@ protected: int l_shname; // length of name_of_shell }; -#endif //}__UPX_P_LX_SH_H + +#endif /*} already included */ /* diff --git a/src/p_tos.cpp b/src/p_tos.cpp index c52763e1..730e2bb2 100644 --- a/src/p_tos.cpp +++ b/src/p_tos.cpp @@ -186,6 +186,7 @@ unsigned PackTos::patch_d0_subq(void *b, int blen, unsigned d0, // patch a "subq.l #1,d0" or "subq.w #1,d0". // also convert into "dbra" if possible assert((int)d0 > 0); + int boff = find_be16(b, blen, get_be16(subq_marker)); if (boff < 0) throwBadLoader(); diff --git a/src/p_unix.cpp b/src/p_unix.cpp index afe02a53..bab0434f 100644 --- a/src/p_unix.cpp +++ b/src/p_unix.cpp @@ -322,7 +322,7 @@ void PackUnix::unpack(OutputFile *fo) /************************************************************************* -// Linux/i386 specific (execve format) +// linux/i386 (generic "execve" format) **************************************************************************/ static const @@ -350,6 +350,7 @@ const upx_byte *PackLinuxI386::getLoader() const return NULL; } + int PackLinuxI386::getLoaderSize() const { if (0!=lsize) { @@ -362,13 +363,18 @@ int PackLinuxI386::getLoaderSize() const return 0; } + int PackLinuxI386::getLoaderPrefixSize() const { return 116; } + bool PackLinuxI386::canPack() { + if (exetype != 0) + return super::canPack(); + Elf_LE32_Ehdr ehdr; unsigned char *buf = ehdr.e_ident; @@ -377,8 +383,11 @@ bool PackLinuxI386::canPack() exetype = 0; const unsigned l = get_le32(buf); +#if 0 + // NOTE: ELF executables are now handled by p_lx_elf.cpp. if (!memcmp(buf, "\x7f\x45\x4c\x46\x01\x01\x01", 7)) // ELF 32-bit LSB { + // FIXME: add special checks for uncompresed "vmlinux" kernel exetype = 1; // now check the ELF header if (!memcmp(buf+8, "FreeBSD", 7)) // branded @@ -390,7 +399,9 @@ bool PackLinuxI386::canPack() if (ehdr.e_version != 1) // version exetype = 0; } - else if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc) + else +#endif + if (l == 0x00640107 || l == 0x00640108 || l == 0x0064010b || l == 0x006400cc) { // OMAGIC / NMAGIC / ZMAGIC / QMAGIC exetype = 2; @@ -506,6 +517,8 @@ void PackLinuxI386::updateLoader(OutputFile *fo) fo->rewrite(loader, 0x80); #undef PAGE_MASK } + + /* vi:ts=4:et */ diff --git a/src/p_unix.h b/src/p_unix.h index 163c7bb2..1684569d 100644 --- a/src/p_unix.h +++ b/src/p_unix.h @@ -127,7 +127,7 @@ protected: /************************************************************************* -// linux/i386 (execve format) +// linux/i386 (generic "execve" format) **************************************************************************/ class PackLinuxI386 : public PackUnixLe32 diff --git a/src/p_vmlinz.cpp b/src/p_vmlinz.cpp index d0301b2a..b4dae103 100644 --- a/src/p_vmlinz.cpp +++ b/src/p_vmlinz.cpp @@ -345,7 +345,7 @@ void PackBvmlinuzI386::pack(OutputFile *fo) int PackVmlinuzI386::canUnpack() { - return false; + return readFileHeader() == getFormat(); } @@ -353,6 +353,9 @@ void PackVmlinuzI386::unpack(OutputFile *) { // no uncompression support for this format, so that // it is possible to remove the original deflate code (>10KB) + + // FIXME: but we could write the uncompressed "vmlinux" image + throwCantUnpack("build a new kernel instead :-)"); } diff --git a/src/p_vmlinz.h b/src/p_vmlinz.h index 30a4b008..35a33c56 100644 --- a/src/p_vmlinz.h +++ b/src/p_vmlinz.h @@ -73,7 +73,7 @@ protected: unsigned char hdrs[4]; // "HdrS" LE16 version; // boot protocol char _____[9]; - unsigned char load_flags; + unsigned char load_flags; char ______[2]; LE32 code32_start; diff --git a/src/p_w32pe.cpp b/src/p_w32pe.cpp index 28f212a8..9a1eadee 100644 --- a/src/p_w32pe.cpp +++ b/src/p_w32pe.cpp @@ -25,6 +25,7 @@ markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu */ + #include "conf.h" #include "file.h" #include "filter.h" diff --git a/src/p_wcle.cpp b/src/p_wcle.cpp index 4acfd3e4..6e24c6e5 100644 --- a/src/p_wcle.cpp +++ b/src/p_wcle.cpp @@ -510,7 +510,7 @@ void PackWcle::pack(OutputFile *fo) ic = (OOT(0,virtual_size) - d_len) &~ 15; assert(ic > ((ph.u_len + overlapoh + 31) &~ 15)); - upx_byte *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,"ESP0",ih.init_esp_offset+IOT(ih.init_ss_object-1,my_base_address)); if (patchFilter32(p, d_len, &ft) && text_vaddr) diff --git a/src/packer.cpp b/src/packer.cpp index e953923b..95b9419c 100644 --- a/src/packer.cpp +++ b/src/packer.cpp @@ -569,11 +569,13 @@ void Packer::initPackHeader() // this is called directly after canPack() from class PackMaster void Packer::updatePackHeader() { - ph.method = getCompressionMethod(); - ph.level = getCompressionLevel(); // update our local options - opt->method = ph.method; - opt->level = ph.level; + if (opt->level < 0) + opt->level = file_size < 512*1024 ? 8 : 7; + opt->method = getCompressionMethod(); + // set ph + ph.level = opt->level; + ph.method = opt->method; } diff --git a/src/packer.h b/src/packer.h index 90c50fc6..5072ce3f 100644 --- a/src/packer.h +++ b/src/packer.h @@ -108,7 +108,6 @@ public: virtual int getFormat() const = 0; virtual const char *getName() const = 0; virtual int getCompressionMethod() const = 0; - virtual int getCompressionLevel() const { return opt->level; } virtual const int *getFilters() const = 0; // PackMaster entries diff --git a/src/packmast.cpp b/src/packmast.cpp index 538dd8bb..108a2a95 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -144,6 +144,10 @@ static Packer* try_packers(InputFile *f, try_function func) Packer *p = NULL; // note: order of tries is important ! + + // + // .exe + // if (!opt->dos.force_stub) { if ((p = func(new PackDjgpp2(f),f)) != NULL) @@ -161,8 +165,16 @@ static Packer* try_packers(InputFile *f, try_function func) } if ((p = func(new PackExe(f),f)) != NULL) return p; + + // + // atari + // if ((p = func(new PackTos(f),f)) != NULL) return p; + + // + // linux + // #if 0 if (opt->unix.script_name) { @@ -180,6 +192,10 @@ static Packer* try_packers(InputFile *f, try_function func) return p; if ((p = func(new PackLinuxI386(f),f)) != NULL) return p; + + // + // .sys and .com + // if ((p = func(new PackSys(f),f)) != NULL) return p; if ((p = func(new PackCom(f),f)) != NULL)