diff --git a/src/.cvsignore b/src/.cvsignore index b386ae3d..9d537e6c 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -4,6 +4,7 @@ *.pdb *.upx .gdbinit +.Attic upx upx_nrv upx_nrv.* diff --git a/src/Makefile b/src/Makefile index 02fcf38a..f46acdc0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -59,7 +59,7 @@ OBJECTS1 = \ packer$o packhead$o packmast$o \ p_com$o p_djgpp2$o p_exe$o p_lx_elf$o p_lx_sep$o p_lx_sh$o \ p_sys$o p_tmt$o p_tos$o \ - p_unix$o p_w32pe$o p_wcle$o p_vmlinz$o + p_unix$o p_vmlinz$o p_w32pe$o p_wcle$o # no exceptions or RTTI OBJECTS2 = \ @@ -122,7 +122,7 @@ LDFLAGS = -s endif LDFLAGS += -Wl,-Map,$(basename $@).map LDLIBS = -##LDLIBS = -lz +LDLIBS = -lz LIBDIRS = DOS_LIBDIRS = @@ -164,7 +164,7 @@ DEFS += '-DUPX_CONFIG_H="config_h/linux.h"' ##CFLAGS_M += -mno-schedule-prologue CFLAGS_M += -march=i386 -mcpu=pentium CFLAGS_WERROR = -Werror -LDLIBS += -lmcheck -lz +LDLIBS += -lmcheck ifeq (1,2) # checkergcc CC = checkergcc @@ -435,7 +435,7 @@ packhead$o: packer.h packmast$o: packmast.h packer.h lefile.h \ p_com.h p_djgpp2.h p_exe.h p_lx_elf.h p_lx_sep.h p_lx_sh.h \ p_sys.h p_tmt.h p_tos.h \ - p_unix.h p_vxd.h p_w32pe.h p_wcle.h p_vmlinz.h + p_unix.h p_vmlinz.h p_vxd.h p_w32pe.h p_wcle.h ui$o: packer.h ui.h work$o: packer.h ui.h packmast.h @@ -456,13 +456,11 @@ p_tos$o: packer.h p_tos.h \ stub/l_t_n2d.h stub/l_t_n2ds.h p_unix$o: packer.h p_unix.h p_elf.h \ stub/l_lx_n2b.h stub/l_lx_n2d.h -p_vmlinux$o: packer.h p_unix.h p_elf.h \ - stub/l_lx_n2b.h stub/l_lx_n2d.h +p_vmlinz$o: packer.h p_vmlinz.h \ + stub/l_vmlinz.h p_w32pe$o: packer.h p_w32pe.h \ stub/l_w32pe.h p_wcle$o: packer.h p_wcle.h lefile.h \ stub/l_wcle.h -p_vmlinz$o: packer.h p_vmlinz.h \ - stub/l_vmlinz.h # vi:nowrap diff --git a/src/p_vmlinz.cpp b/src/p_vmlinz.cpp index 6d2efb19..322aa3e4 100644 --- a/src/p_vmlinz.cpp +++ b/src/p_vmlinz.cpp @@ -36,22 +36,26 @@ static const #include "stub/l_vmlinz.h" -const unsigned kernel_entry = 0x100000; -const unsigned stack_during_uncompression = 0x90000; +static const unsigned kernel_entry = 0x100000; +static const unsigned stack_during_uncompression = 0x90000; // from /usr/src/linux/arch/i386/boot/compressed/Makefile -const unsigned bzimage_offset = 0x100000; -const unsigned zimage_offset = 0x1000; +static const unsigned zimage_offset = 0x1000; +static const unsigned bzimage_offset = 0x100000; -PackvmlinuzI386::PackvmlinuzI386(InputFile *f) : +/************************************************************************* +// +**************************************************************************/ + +PackVmlinuzI386::PackVmlinuzI386(InputFile *f) : super(f) { assert(sizeof(boot_sect_t) == 0x218); } -int PackvmlinuzI386::getCompressionMethod() const +int PackVmlinuzI386::getCompressionMethod() const { if (M_IS_NRV2B(opt->method)) return M_NRV2B_LE32; @@ -61,25 +65,37 @@ int PackvmlinuzI386::getCompressionMethod() const } -const int *PackvmlinuzI386::getFilters() const +const int *PackVmlinuzI386::getFilters() const { return NULL; } -bool PackvmlinuzI386::canPack() +/************************************************************************* +// +**************************************************************************/ + +int PackVmlinuzI386::readHeader() { boot_sect_t h; + fi->readx(&h, sizeof(h)); if (h.boot_flag != 0xAA55) - return false; + return -1; setup_size = (1 + (h.setup_sects ? h.setup_sects : 4)) * 0x200; if (setup_size > file_size) - return false; + return -1; - bzImage = memcmp(h.hdrs, "HdrS", 4) == 0 && (h.load_flags & 1) != 0; + if (memcmp(h.hdrs, "HdrS", 4) == 0 && (h.load_flags & 1) != 0) + return UPX_F_BVMLINUZ_i386; + return UPX_F_VMLINUZ_i386; +} + + +bool PackVmlinuzI386::readKernel() +{ obuf.alloc(file_size); fi->seek(0, SEEK_SET); fi->readx(obuf, file_size); @@ -104,81 +120,136 @@ bool PackvmlinuzI386::canPack() if (zf == 0) return false; ulen = gzread(zf, ibuf, ibuf.getSize()); - return ulen > (unsigned) file_size; + return ulen > (unsigned) file_size && ulen < ibuf.getSize(); #endif } return false; } -void PackvmlinuzI386::pack(OutputFile *fo) +/************************************************************************* +// vmlinuz specific +**************************************************************************/ + +bool PackVmlinuzI386::canPack() { + return readHeader() == UPX_F_VMLINUZ_i386; +} + + +void PackVmlinuzI386::pack(OutputFile *fo) +{ + if (!readKernel()) + throwCantPack("kernel decompression failed"); + // OutputFile::dump("kernel.img", ibuf, ulen); + MemBuffer setupbuf(setup_size); memcpy(setupbuf, obuf, setup_size); obuf.free(); obuf.allocForCompression(ibuf.getSize()); - // FILE *f1 = fopen("kernel.img", "wb"); fwrite(ibuf, 1, ulen, f1); fclose(f1); - ph.u_len = ulen; if (!compress(ibuf, obuf)) throwNotCompressible(); + const unsigned clen = ph.c_len; initLoader(nrv_loader, sizeof(nrv_loader)); - const unsigned overlapoh = bzImage ? findOverlapOverhead(obuf, 512) : 0; - unsigned clen = ph.c_len; - - if (bzImage) - { - // align everything to dword boundary - it is easier to handle - memset(obuf + clen, 0, 4); - clen = ALIGN_UP(clen, 4); - - addLoader("LINUZ000""LBZIMAGE""IDENTSTR", - "+40D++++", // align the stuff to 4 byte boundary - "UPX1HEAD", // 32 byte - "LZCUTPOI""+0000000", - getDecompressor(), - "LINUZ990", - NULL - ); - } - else - addLoader("LINUZ000""LZIMAGE0", - getDecompressor(), - "LINUZ990""IDENTSTR""UPX1HEAD", - NULL - ); + addLoader("LINUZ000""LZIMAGE0", + getDecompressor(), + "LINUZ990""IDENTSTR""UPX1HEAD", + NULL + ); const unsigned lsize = getLoaderSize(); MemBuffer loader(lsize); memcpy(loader, getLoader(), lsize); - int e_len = bzImage ? getLoaderSectionStart("LZCUTPOI") : lsize; patchPackHeader(loader, lsize); - if (bzImage) - { - assert(e_len > 0); + patch_le32(loader, lsize, "ESI1", zimage_offset + lsize); - const unsigned d_len4 = ALIGN_UP(lsize - e_len, 4); - const unsigned decompr_pos = ALIGN_UP(ulen + overlapoh, 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 + patch_le32(loader, lsize, "KEIP", kernel_entry); + patch_le32(loader, lsize, "STAK", stack_during_uncompression); - unsigned jpos = find_le32(loader, e_len, get_le32("JMPD")); - patch_le32(loader, e_len, "JMPD", decompr_pos - jpos - 4); + ((boot_sect_t *)((unsigned char *)setupbuf))->sys_size = ALIGN_UP(lsize + clen, 16) / 16; - patch_le32(loader, e_len, "ESI1", bzimage_offset + decompr_pos - clen); - patch_le32(loader, e_len, "ECX0", copy_size / 4); - patch_le32(loader, e_len, "EDI0", bzimage_offset + edi); - patch_le32(loader, e_len, "ESI0", bzimage_offset + esi); - } - else - patch_le32(loader, lsize, "ESI1", zimage_offset + lsize); + fo->write(setupbuf, setupbuf.getSize()); + fo->write(loader, lsize); + fo->write(obuf, clen); + + //if (!checkCompressionRatio(file_size, fo->getBytesWritten())) + // throwNotCompressible(); +} + + +/************************************************************************* +// bvmlinuz specific +**************************************************************************/ + +bool PackBvmlinuzI386::canPack() +{ + return readHeader() == UPX_F_BVMLINUZ_i386; +} + + +void PackBvmlinuzI386::pack(OutputFile *fo) +{ + if (!readKernel()) + throwCantPack("kernel decompression failed"); + // OutputFile::dump("kernel.img", ibuf, ulen); + + MemBuffer setupbuf(setup_size); + memcpy(setupbuf, obuf, setup_size); + + obuf.free(); + obuf.allocForCompression(ibuf.getSize()); + + ph.u_len = ulen; + if (!compress(ibuf, obuf)) + throwNotCompressible(); + + const unsigned overlapoh = findOverlapOverhead(obuf, 512); + + // align everything to dword boundary - it is easier to handle + unsigned clen = ph.c_len; + memset(obuf + clen, 0, 4); + clen = ALIGN_UP(clen, 4); + + initLoader(nrv_loader, sizeof(nrv_loader)); + + addLoader("LINUZ000""LBZIMAGE""IDENTSTR", + "+40D++++", // align the stuff to 4 byte boundary + "UPX1HEAD", // 32 byte + "LZCUTPOI""+0000000", + getDecompressor(), + "LINUZ990", + NULL + ); + + const unsigned lsize = getLoaderSize(); + MemBuffer loader(lsize); + memcpy(loader, getLoader(), lsize); + + const int e_len = getLoaderSectionStart("LZCUTPOI"); + assert(e_len > 0); + + patchPackHeader(loader, lsize); + + const unsigned d_len4 = ALIGN_UP(lsize - e_len, 4); + const unsigned decompr_pos = ALIGN_UP(ulen + overlapoh, 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 + + unsigned jpos = find_le32(loader, e_len, get_le32("JMPD")); + patch_le32(loader, e_len, "JMPD", decompr_pos - jpos - 4); + + patch_le32(loader, e_len, "ESI1", bzimage_offset + decompr_pos - clen); + patch_le32(loader, e_len, "ECX0", copy_size / 4); + patch_le32(loader, e_len, "EDI0", bzimage_offset + edi); + patch_le32(loader, e_len, "ESI0", bzimage_offset + esi); patch_le32(loader, e_len, "KEIP", kernel_entry); patch_le32(loader, e_len, "STAK", stack_during_uncompression); @@ -194,18 +265,26 @@ void PackvmlinuzI386::pack(OutputFile *fo) // throwNotCompressible(); } + /************************************************************************* -// +// unpack **************************************************************************/ -int PackvmlinuzI386::canUnpack() +int PackVmlinuzI386::canUnpack() { return false; } -void PackvmlinuzI386::unpack(OutputFile *) +void PackVmlinuzI386::unpack(OutputFile *) { - // no uncompression support for this format, so + // no uncompression support for this format, so that // it is possible to remove the original deflate code (>10KB) throwCantUnpack("build a new kernel instead :-)"); } + + +/* +vi:ts=4:et +*/ + + diff --git a/src/p_vmlinz.h b/src/p_vmlinz.h index 1ebb8e83..b7c4702d 100644 --- a/src/p_vmlinz.h +++ b/src/p_vmlinz.h @@ -25,15 +25,20 @@ markus.oberhumer@jk.uni-linz.ac.at ml1050@cdata.tvnet.hu */ + +#ifndef __UPX_P_VMLINZ_H +#define __UPX_P_VMLINZ_H + + /************************************************************************* // vmlinuz/i386 (zlib compressed Linux kernel image) **************************************************************************/ -class PackvmlinuzI386 : public Packer +class PackVmlinuzI386 : public Packer { typedef Packer super; public: - PackvmlinuzI386(InputFile *f); + PackVmlinuzI386(InputFile *f); virtual int getVersion() const { return 1; } virtual int getFormat() const { return UPX_F_VMLINUZ_i386; } virtual const char *getName() const { return "vmlinuz/386"; } @@ -47,6 +52,9 @@ public: virtual int canUnpack(); protected: + virtual int readHeader(); + virtual bool readKernel(); + // virtual const upx_byte *getLoader() const; // virtual int getLoaderSize() const; @@ -72,6 +80,32 @@ protected: }; off_t setup_size; - bool bzImage; unsigned long ulen; }; + + +/************************************************************************* +// bvmlinuz/i386 (zlib compressed Linux kernel image) +**************************************************************************/ + +class PackBvmlinuzI386 : public PackVmlinuzI386 +{ + typedef PackVmlinuzI386 super; +public: + PackBvmlinuzI386(InputFile *f) : super(f) { } + virtual int getFormat() const { return UPX_F_BVMLINUZ_i386; } + virtual const char *getName() const { return "bvmlinuz/386"; } + + virtual void pack(OutputFile *fo); + + virtual bool canPack(); +}; + + +#endif /* already included */ + + +/* +vi:ts=4:et +*/ + diff --git a/src/packmast.cpp b/src/packmast.cpp index 8fa2ff8b..ba8a91d6 100644 --- a/src/packmast.cpp +++ b/src/packmast.cpp @@ -174,11 +174,9 @@ static Packer* try_packers(InputFile *f, try_function func) return p; if ((p = func(new PackLinuxI386sh(f),f)) != NULL) return p; -#if 0 - if ((p = func(new PackBvmlinuxI386(f),f)) != NULL) + if ((p = func(new PackBvmlinuzI386(f),f)) != NULL) return p; -#endif - if ((p = func(new PackvmlinuzI386(f),f)) != NULL) + if ((p = func(new PackVmlinuzI386(f),f)) != NULL) return p; if ((p = func(new PackLinuxI386(f),f)) != NULL) return p; diff --git a/src/stub/Makefile b/src/stub/Makefile index a4a55951..5586bc18 100644 --- a/src/stub/Makefile +++ b/src/stub/Makefile @@ -157,10 +157,6 @@ l_sys.h: l_sys.asx $(NASM) -f bin -o $T.bin $< $(BIN2H) $T.bin nrv2b_loader $@ -l_tmt.h: l_tmt.asx - $(NASM) -f bin -o $T.bin $< - $(BIN2H) $T.bin nrv_loader $@ - l_t_n2b.h: l_tos.s $(CPP_A68K) -DNRV2B -o $T.i $< $(A68K) $T.i @@ -185,7 +181,15 @@ l_t_n2ds.h: l_tos.s $(O2BIN) $T.o $T.bin 'UPX1' 'UPX9' $(BIN2H) $T.bin nrv2d_loader_small $@ -l_vxd.h: l_vxd.asm +l_tmt.h: l_tmt.asx + $(NASM) -f bin -o $T.bin $< + $(BIN2H) $T.bin nrv_loader $@ + +l_vmlinz.h: l_vmlinz.asx + $(NASM) -f bin -o $T.bin $< + $(BIN2H) $T.bin nrv_loader $@ + +l_vxd.h: l_vxd.asx $(NASM) -f bin -o $T.bin $< $(BIN2H) $T.bin nrv_loader $@ @@ -197,10 +201,6 @@ l_w32pe.h: l_w32pe.asx $(NASM) -f bin -o $T.bin $< $(BIN2H) $T.bin nrv_loader $@ -l_vmlinz.h: l_vmlinz.asx - $(NASM) -f bin -o $T.bin $< - $(BIN2H) $T.bin nrv_loader $@ - # /*********************************************************************** # // linux rules (exec, elf, sh, sep) @@ -301,10 +301,10 @@ l_t_n2bs.h: n2b_d.ash bits.ash $(DEPS1) l_t_n2d.h: n2d_d.ash bits.ash $(DEPS1) l_t_n2ds.h: n2d_d.ash bits.ash $(DEPS1) l_tmt.h: n2b_d32.asy n2d_d32.asy $(DEPS2) +l_vmlinz.h: n2b_d32.asy n2d_d32.asy $(DEPS2) l_vxd.h: n2b_d32.asy n2d_d32.asy $(DEPS2) l_wcle.h: n2b_d32.asy n2d_d32.asy $(DEPS2) l_w32pe.h: n2b_d32.asy n2d_d32.asy $(DEPS2) -l_vmlinz.h: n2b_d32.asy n2d_d32.asy $(DEPS2) l_xe_n2b.o: n2b_d32.ash $(DEPS1) l_6e_n2b.o: n2b_d32.ash $(DEPS1) diff --git a/src/unupx.h b/src/unupx.h index 5fb1ea2d..88f986d9 100644 --- a/src/unupx.h +++ b/src/unupx.h @@ -81,7 +81,7 @@ typedef unsigned upx_uint32; #define UPX_F_LINUX_SEP_i386 13 #define UPX_F_LINUX_SH_i386 14 #define UPX_F_VMLINUZ_i386 15 -#define UPX_F_BVMLINUX_i386 16 +#define UPX_F_BVMLINUZ_i386 16 #define UPX_F_ATARI_TOS 129 #define UPX_F_SOLARIS_SPARC 130